Before you can create quotes or orders, your organization needs at least one registered wallet and one active bank account. Set these up via the API (shown below), or in the Etherfuse dashboard — wallets (sandbox · production) and bank accounts (sandbox · production).
Wallets and bank accounts here belong to your organization (the parent org). To onboard your customers and their accounts, see Onboard your customers below.
Complete KYB before going to production. We strongly recommend verifying your organization (Know Your Business) with Etherfuse before setting up production accounts. KYB simplifies wallet onboarding by letting you claim ownership at the organization level, can make you eligible for reduced fee tiers, and ensures your accounts are managed under your company’s identity rather than individual credentials. Contact your Etherfuse representative to start the KYB process.
Set claimOwnership: true — Claiming ownership links the wallet’s KYC status to your organization’s KYB status, so the wallet is automatically compliant. Without this flag, you’ll need to complete individual KYC for each wallet you register.
This endpoint is idempotent — registering an already-active wallet returns the existing record. If the wallet was previously soft-deleted, it will be restored.
2
Check Wallet Status — GET /ramp/wallet/{wallet_id}
Treat production bank account registration as permanent. Mexican banking regulations make it extremely difficult to change or replace a bank account once it has been registered under a given RFC. Double-check the CLABE, RFC, and CURP before submitting in production. Errors may require manual intervention with Etherfuse support and can delay your ability to transact.
STP CLABEs (prefix 646) are not supported. CLABEs starting with 646 belong to STP (Sistema de Transferencias y Pagos), and STP-to-STP transfers are not currently supported. Please use a CLABE from a different bank.
1
Register a Bank Account — POST /ramp/customer/{customer_id}/bank-account
Sandbox uses a placeholder RFC to auto-approve the account. Submit XEXX010101000 as the rfc in sandbox — this causes Etherfuse to skip SPEI provider registration and mark the account compliant: true immediately. Any other RFC in sandbox is sent through to the SPEI provider’s sandbox environment and treated as a real registration — it will not auto-approve. The placeholder is rejected in production; use the real RFC there. See the Sandbox Reference for details.
2
Check Bank Account Status — GET /ramp/bank-accounts
Your customers complete Know Your Customer (KYC) verification before they can transact — they submit identity data, upload a selfie and a government-issued ID, and sign three agreements (electronic signature, terms and conditions, customer agreement). It works the same in sandbox as in production.You have two ways to collect that data:
Approach
Best For
Section
Hosted UI (Presigned URL)
Fastest integration — Etherfuse handles identity collection, document upload, and agreement signing in one hosted page
Start with the Hosted UI if you want the fastest path to testing. You can migrate to Programmatic later without re-onboarding existing customers.In the Programmatic flow, the customer completes the required agreements step by being launched into the app to review and sign them. See Sign agreements.
KYC Requirements (Production)In production, the following must be submitted for each customer:
Selfie — A photo of the customer’s face
Government-issued identification — A valid ID document (passport, driver’s license, national ID)
Proof of address — Document showing the customer’s current address (utility bill, bank statement)
If the government-issued ID includes the customer’s address (e.g., a driver’s license), it can satisfy both requirements. After all data is submitted, Etherfuse reviews the information for accuracy before approving the customer.In sandbox, you can complete KYC using fake data — no real personal information is required.
How identity is verified. Etherfuse verifies identity with face match + liveness — the selfie is matched against the government-issued ID, plus a liveness check. There’s no single mandated document (e.g. no INE requirement specifically); any valid government ID works. A liveness check is required for Mexican nationals transacting against their own bank account — a SPEI compliance requirement.Production vs. sandbox collection. In production, agreement signing and the liveness check are completed through a minimal Etherfuse UI step that you can embed (iframe) in your app. In sandbox, you can accept agreements programmatically and customers auto-approve — no liveness UI is involved.
The hosted UI flow is the fastest way to onboard a customer. You generate a presigned URL, redirect the user to Etherfuse’s verification page, and they complete identity verification, document upload, bank account registration, and agreement signing in one session.
Supported blockchains: The blockchain field accepts solana, stellar, base, polygon, or monad. All examples use Solana, but the flow works identically across chains — just pass the appropriate value and a valid public key for that chain.
1
Generate Presigned URL — POST /ramp/onboarding-url
Show Details
This creates the customer organization and returns a presigned URL valid for 15 minutes. You generate the customerId and bankAccountId UUIDs. See POST /ramp/onboarding-url for the full schema.
curl -X POST https://api.sand.etherfuse.com/ramp/onboarding-url \ -H "Authorization: <api_key>" \ -H "Content-Type: application/json" \ -d '{ "customerId": "<customer_uuid>", # You generate this UUID "bankAccountId": "<bank_account_uuid>", # You generate this UUID "publicKey": "<wallet_public_key>", "blockchain": "solana", "userInfo": { "email": "[email protected]", "displayName": "Ana García" } }'
Store these IDs — you’ll need customerId for quotes, and bankAccountId for orders. The customerId must be a new UUID, not your own organization’s ID.
userInfo is recommended and will eventually be required. 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.).
2
Redirect the User
Show Details
Send the customer to the presigned_url. They have 15 minutes to complete the full flow in the Etherfuse-hosted UI:
In sandbox, the customer is auto-approved when the customer agreement is signed. In production, Etherfuse admins review the submitted documents before approving. See Checking KYC status for response details and status values.
Field naming convention: API responses use snake_case (e.g., presigned_url), while request bodies use camelCase (e.g., presignedUrl). This is consistent across all Etherfuse endpoints.
Programmatic onboarding lets you create a customer’s organization via API and collect identity data in your own UI rather than the Etherfuse-hosted verification page. This is ideal for white-label integrations where the customer never leaves your app.
Supported blockchains: The blockchain field accepts solana, stellar, base, polygon, or monad. All examples use Solana, but the flow works identically across chains.
Two types of auth are used in this flow:
The API steps (create organization, submit identity, upload documents, register bank) use your API key with the customer_id in the URL path.
The launch steps (identity verification when a bank is not compliant, and signing agreements) send the customer into the Etherfuse app with a scoped JWT. These are browser launches, not API calls (no API key).
1
Create Customer Organization — POST /ramp/organization
Show Details
Create a child organization for your customer. You can optionally include wallets and a bank account to set everything up in a single call. See POST /ramp/organization for the full schema.
userInfo is recommended and will eventually be required. 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.).
Partner fees: To set a default partner fee for this child org, add "partnerFeeDefaultBps": 100 (0–500 bps) to the request body. This fee layers on top of platform fees for all quotes under this org. See Fees.
2
Submit Identity Data — POST /ramp/customer/{customer_uuid}/kyc
Show Details
Submit the customer’s identity information via your API key. KYC attaches to the customer org — no wallet key required. See POST /ramp/customer/{id}/kyc for the full schema.
The Submit KYC endpoint requires the following fields on submission and returns a 400 listing any that are missing:
Field
Required
Path in identity payload
First Name
Yes
name.givenName
Last Name
Yes
name.familyName
Phone Number
Yes
phoneNumber
Email
Yes
email
Occupation
Yes
occupation
Address
Yes
address (object: street, city, region, postalCode, country)
Date of Birth
Yes
dateOfBirth
CURP
Mexico: required
idNumbers entry with type: "CURP"
RFC
Mexico: required
idNumbers entry with type: "RFC"
For Mexican customers (country: "MX"), both a CURP and an RFC are required. For all other countries, omit idNumbers entirely — any other ID type is rejected.
Sandbox skips manual review, not the steps. Submitting KYC sets the customer to proposed — this call does not approve them on its own. In sandbox there is no admin review: the customer auto-approves once all agreements are signed (Step 5), at which point a kyc_updated webhook fires and the wallet becomes order-eligible. Steps 3 and 5 are both required in sandbox, the same as in production — sandbox only differs in that approval is automatic rather than manually reviewed.
3
Upload Documents — POST /ramp/customer/{customer_uuid}/kyc/documents
Show Details
Upload government ID and selfie images as base64-encoded data URLs. See POST /ramp/customer/{id}/kyc/documents for the full schema.Upload ID Document (front and back):
Requirements: JPEG or PNG, max 10MB per image. Labels: id_front, id_back (if applicable), selfie.
In sandbox, you can submit any placeholder image — the content isn’t validated — but the upload is still required. The customer is not approved until all agreements are signed (Step 5).
4
Register Bank Account — POST /ramp/customer/{customer_uuid}/bank-account
Use the sandbox RFC to auto-approve the account. In sandbox, submit XEXX010101000 as the rfc. This placeholder causes Etherfuse to skip the SPEI provider registration and mark the account compliant: true immediately, so the customer can start transacting. Any other RFC in sandbox is sent through to the SPEI provider’s sandbox environment and treated as a real registration — it will not auto-approve. The placeholder is rejected in production; use the customer’s real RFC there.
Alternative: Presigned URL auth — You can also register bank accounts via POST /ramp/bank-account using the presigned URL instead of your API key. This is the path used by the Etherfuse hosted onboarding UI. See POST /ramp/bank-account for details.
5
Launch the customer to verify a non-compliant bank
Show Details
Check the bank account’s compliant flag after registering it (in the registration response, or via GET /ramp/bank-accounts). If it comes back compliant: false, the customer must complete additional identity verification before the bank can be used in orders. For Mexican (STP) accounts this is a liveness face scan matched against the ID already on file.Launch the customer into the Identity verification flow (scope: verification, target: /idv), using the same UUID as the sub. The launch carries no bank id; the session resolves which bank still needs verifying. When it succeeds the bank flips to compliant: true and you receive a bank_account_updated webhook, so you can react without polling.
In sandbox, registering with the placeholder RFC XEXX010101000 marks the bank compliant: true immediately, so you can skip this step. Register with any other RFC to leave it compliant: false and exercise the /idv flow end to end.
The face scan needs camera access. If you embed the launch in an iframe, set allow="camera" on the iframe element, or the scan cannot start.
6
Launch the customer to sign agreements
Show Details
The customer signs the three agreements (electronic signature, terms and conditions, and customer agreement) inside the Etherfuse app, in a real authenticated session rather than against a presigned URL. Authenticate them with a launch JWT (using the same UUID you used for customerId as the sub) and send them into the agreements flow. See Sign agreements for the flow’s scope and target, and JWT User Authentication for signing and launching.
The signing page prefills from the identity you submitted in Step 2; the customer accepts each agreement and can fill any identity fields still missing. Pass an optional return_url on the launch to send them back to your app when they finish.
In sandbox, the customer is auto-approved once all agreements are signed.
If KYC is rejected, the updateReason in the webhook (or currentRejectionReason in the status response) explains why. To resubmit:
Address the rejection reason (e.g., upload a clearer document)
Submit new data via the same endpoints
The new submission creates a fresh review; old rejected data remains for audit purposes
Show Bank account compliance
A bank account must be compliant: true before you can create orders. Two paths to compliance:
Customer self-verifies — After submitting data via API, redirect the customer to the presigned URL. They complete identity verification (facial scan + ID matching) in the Etherfuse UI, which marks the bank account compliant immediately.
Etherfuse admin reviews — Submit everything programmatically and wait for admins to review the uploaded documents. The customer’s selfie and government ID must be uploaded before the admin can complete the compliance check.
While a bank is compliant: false, the customer must complete additional verification before it can be used. The form that takes depends on the bank type: Mexican STP banks require an identity face scan, which you trigger by launching the customer into the Identity verification flow (scope: verification, target: /idv). Once it succeeds the bank flips to compliant: true. You receive a bank_account_updated webhook when this changes, so you can react without polling.
In sandbox, register the bank account with the sandbox RFC XEXX010101000 to skip SPEI provider registration and have the account marked compliant: true immediately. Any other RFC goes through the SPEI provider’s sandbox as a real registration and will not auto-approve. A bank’s compliant state reflects reality in sandbox too, so you can exercise the /idv flow there end-to-end.
Show Webhooks
Register a webhook for kyc_updated events to receive status updates. See POST /ramp/webhook for setup and payload details.Approved:
Only data where source_organization_id matches their org
Wallet Owner
All data for their wallet
Admin
All data
This prevents partners from accessing PII submitted by other partners or directly by users.
Show Email suppression
When you submit KYC programmatically, Etherfuse suppresses standard KYC notification emails to the user. Your application is responsible for communicating status updates via webhook events.