curl --request POST \
--url https://api.sand.etherfuse.com/ramp/onboarding-url \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"bankAccountId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"blockchain": "stellar",
"customerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"publicKey": "GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL",
"userInfo": {
"displayName": "Ana García",
"email": "[email protected]"
}
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bankAccountId: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
blockchain: 'stellar',
customerId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
publicKey: 'GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL',
userInfo: {displayName: 'Ana García', email: '[email protected]'}
})
};
fetch('https://api.sand.etherfuse.com/ramp/onboarding-url', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/ramp/onboarding-url"
payload = {
"bankAccountId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"blockchain": "stellar",
"customerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"publicKey": "GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL",
"userInfo": {
"displayName": "Ana García",
"email": "[email protected]"
}
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"presigned_url": "https://api.sand.etherfuse.com/onboarding?org_id=a1b2c3d4-...&customer_id=a1b2c3d4-...&expires=1748345400&signature=..."
}"You have already added user with this address, see org: b45a5a15-3e4b-4e92-9167-635dd7e95252"Generate onboarding URL
Generates a presigned URL for customer onboarding. If the customer does not exist, it
will be created. You generate a UUID for customerId and bankAccountId, and Etherfuse creates the
customer and bank account records associated with your organization.
Deprecated. Sunset August 16, 2026. Customer onboarding has consolidated onto a
single hosted flow: create the customer’s personal organization with
POST /ramp/organization, then launch them into /idv, which runs identity
verification and agreement signing in one step. See
Customer Onboarding (KYC). Migrate before the sunset date.
Upon visiting the URL, the customer has 15 minutes to complete onboarding (KYC verification and bank account linking).
Personal organizations only
This endpoint always creates a personal organization; it forces individual KYC.
There is no accountType field; pass business orgs through
POST /ramp/organization instead.
userInfo
Pass userInfo with the end user’s email and display name. When provided, Etherfuse
pre-creates the user record so the customer’s eventual sign-in attaches to the right
user and we can email them on status changes (KYC approved/rejected, bank account
verified, etc.). userInfo is required, and neither email nor displayName may be blank. The
email is required for the customer’s verification record and status notifications. A
customer created without an email address cannot start KYC.
Authenticating as the customer
If the customer signs in with a JWT (see JWT User Authentication), use the same value for customerId as the JWT sub. The shared id links the customer record to the user who signs in.
curl --request POST \
--url https://api.sand.etherfuse.com/ramp/onboarding-url \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"bankAccountId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"blockchain": "stellar",
"customerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"publicKey": "GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL",
"userInfo": {
"displayName": "Ana García",
"email": "[email protected]"
}
}
'const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
bankAccountId: 'b2c3d4e5-f6a7-8901-bcde-f12345678901',
blockchain: 'stellar',
customerId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
publicKey: 'GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL',
userInfo: {displayName: 'Ana García', email: '[email protected]'}
})
};
fetch('https://api.sand.etherfuse.com/ramp/onboarding-url', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://api.sand.etherfuse.com/ramp/onboarding-url"
payload = {
"bankAccountId": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"blockchain": "stellar",
"customerId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"publicKey": "GDUKMGUGD3V6VXTU2RLAUM7A2FABLMHCPWTMDHKP7HHJ6FCZKEY4PVWL",
"userInfo": {
"displayName": "Ana García",
"email": "[email protected]"
}
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"presigned_url": "https://api.sand.etherfuse.com/onboarding?org_id=a1b2c3d4-...&customer_id=a1b2c3d4-...&expires=1748345400&signature=..."
}"You have already added user with this address, see org: b45a5a15-3e4b-4e92-9167-635dd7e95252"Authorizations
API key sent in the Authorization header.
Body
Canonical blockchain enum for API serialization.
Use this type for JSON APIs and WebSocket messages.
For database storage, convert to BlockchainType.
stellar, solana, base, polygon, monad Info about the end user. Both fields are required and neither may be
blank. email is required for the verification record and status
notifications. A customer created without an email address cannot start
KYC. displayName is how the customer is addressed in notices.
Show child attributes
Show child attributes
Response
A presigned onboarding URL