Crypto offramp (stablecoin to fiat)
Use this guide when your business needs to convert stablecoin (USDC or USDT) into fiat and pay an external bank account — without holding a fiat wallet balance first.
Sznd maps a crypto deposit address to each fiat beneficiary (bank account). When you accept an offramp quote, Sznd returns that address together with the amount and funding deadline for that specific transaction. Send the exact stablecoin amount within the window and fiat is delivered to the beneficiary bank account you registered for the customer.
Important: The beneficiary is the fiat payout destination (bank account). It is not the crypto address. Sznd returns the crypto address and transaction payment instructions only after you accept the quote.
Crypto address vs transaction
Do not send crypto without accepting first. Do not reuse an amount or deadline from a previous accept — only the address may repeat for the same beneficiary.
Who this is for
End-to-end flow
Status lifecycle
CREATED → AWAITING_PAYMENT → PAYMENT_CONFIRMED → PROCESSING_PAYOUT → COMPLETED
Poll GET /api/v1/client/quotes/{id} or use transaction webhooks for updates.
Prerequisites
Before your first offramp:
- Business API access — HMAC-authenticated Client API key (Authentication).
- Customer registered —
POST /api/v1/client/customersor/full. - Customer verification complete —
kyc_stateisCOMPLETEDonGET /api/v1/client/customers/{id}/onboarding-status. - Offramp corridor enabled — Contact Sznd support if GBP, EUR, or CAD bank-transfer offramp is not yet active on your account.
- Beneficiary synced — Fiat beneficiary created for the customer; status must allow payout (see Beneficiaries).
Step 1: Register the customer
Register the end customer your business is acting for. Store the returned customer user id — you will pass it as on_behalf_of on quotes and as user_id on beneficiaries.
POST /api/v1/client/customers/full (recommended when you already hold KYC data)
Monitor onboarding until verification is complete:
GET /api/v1/client/customers/{customer_id}/onboarding-status
Step 2: Create a fiat beneficiary for the customer
Create the bank account that will receive fiat after the stablecoin is converted. Pass the customer's user id in user_id.
POST /api/v1/client/beneficiaries
Example: GBP bank account
Example: EUR bank account (SEPA)
Example: CAD bank transfer (EFT)
Store the beneficiary id from the response for the quote.
Field requirements by currency: Beneficiaries API — crypto offramp fiat beneficiaries.
Step 3: Create a DIRECT_EXCHANGE quote
Create a quote with stablecoin as the source and fiat as the target. Set payment_method to CRYPTO and include the network you intend to fund from.
POST /api/v1/client/quotes
Required parameters
Success response (201)
Step 4: Accept the quote — receive payment instructions
Accepting locks the quote and returns payment instructions. For crypto offramp, Sznd returns the crypto deposit address mapped to your fiat beneficiary, along with the exact amount and 15-minute funding deadline for this transaction.
The address belongs to the beneficiary's fiat destination — if you offramp to the same bank account again, you will typically receive the same address, but you must still accept each new quote and use the new amount and deadline from that accept response.
POST /api/v1/client/quotes/{quote_id}/accept
Success response (200)
Fields to use in your product UI
The crypto address is mapped to the fiat beneficiary, not generated arbitrarily per quote. Always read payment_address, total_payable, and funding_deadline from the current accept response.
Step 5: Send stablecoin within the funding window
- Send
total_payableofpayment_tokenon the specifiedpayment_networktopayment_address. - Complete the transfer within 15 minutes of accept (
funding_deadline). - Use the exact token and network returned — sending the wrong asset or chain can result in loss of funds.
Your business treasury or the customer may send the crypto. Sznd attributes the deposit to the quote you accepted for this transaction, using the amount and deadline from that accept response.
After Sznd detects the deposit, fiat payout to the beneficiary bank account is processed automatically.
Step 6: Webhook and reconciliation
Subscribe to transaction webhooks. You will receive updates as the quote moves from payment confirmed through payout to completed.
Example completion payload (shape):
Reconcile using origin_reference, transaction_reference, and quote_id.
Complete cURL example
Best practices
- Register the customer first — Offramp quotes require a verified customer (
on_behalf_of). - Separate beneficiary from crypto address — Register bank details once; Sznd maps a crypto deposit address to that fiat beneficiary. Accept each quote to get the amount and deadline for that transaction.
- Show the 15-minute countdown — Use
funding_deadlinein your UI; expired quotes need a new accept (and new amount/deadline). - Send exact amount and network — Use
total_payable,payment_token, andpayment_networkfrom the accept response only — never from a previous quote. - Unique
origin_reference— Prevents duplicate quotes for the same business intent. - Webhooks over polling — Handle
AWAITING_PAYMENT→COMPLETEDasynchronously with idempotent webhook handlers.
Crypto offramp vs other flows
Related documentation
- Customers — Register and verify end customers
- Beneficiaries — Fiat payout destinations
- Create and accept quotes — Quote API reference
- Transaction webhooks — Completion notifications