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.Hybrid is also common — use the programmatic API for identity and documents, then redirect the user to the presigned URL for agreements and compliance verification.
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 tutorial below walks through the KYC flow against a real environment using your API key. It demonstrates the programmatic approach with a hybrid presigned-URL step for agreements; the same shape applies to the pure hosted flow except the customer completes Steps 2–4 in the Etherfuse UI instead of via API. Toggle Sandbox/Production at the top.
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 throughout the flow:
Steps 1–5 use your API key with the customer_id in the URL path
Step 6 uses the presigned URL as the authentication token (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. The pubkey field is the wallet public key (not a UUID). See POST /ramp/customer/{id}/kyc for the full schema.
When the customer signs their agreement (Step 6), all required fields must be present — either from this endpoint or via the customerInfo field on the customer agreement.
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
No
dateOfBirth
CURP
Mexico only
idNumbers entry with type: "CURP"
RFC
Mexico only
idNumbers entry with type: "RFC"
If any required field is missing at agreement signing, the request returns a 400 indicating which field was not provided.
idNumbers is optional — defaults to empty. Only needed for Mexican customers (CURP and RFC). Non-Mexican customers can omit it entirely.
In sandbox, this call auto-approves the customer. When you submit KYC programmatically in sandbox, the customer is marked approved immediately, a kyc_updated webhook fires, and the wallet becomes order-eligible. The response status returns "approved" instead of "proposed". Steps 3, 5, and 6 are not required in sandbox — they remain required in production.
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. This step is optional in sandbox since Step 2 already auto-approves the customer.
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
Generate Presigned URL — POST /ramp/onboarding-url
Show Details
Generate a presigned URL to use as the authentication token for agreement signing. The customerId must match the organization ID from Step 1. See POST /ramp/onboarding-url for the full schema.
User Authorization Required — These create legally binding obligations. The presigned URL authenticates the user and serves as their electronic signature authorization. Ensure the actual end user initiates or explicitly authorizes these requests.
1. Electronic Signature Consent:
POST /ramp/agreements/electronic-signature{ "presignedUrl": "<presigned_url_from_step_5>" }
2. Terms and Conditions:
POST /ramp/agreements/terms-and-conditions{ "presignedUrl": "<presigned_url_from_step_5>" }
3. Customer Agreement:
POST /ramp/agreements/customer-agreement{ "presignedUrl": "<presigned_url_from_step_5>" }
If any required identity fields are missing from Step 2, you can provide them here via customerInfo:
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.
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.
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.