Flow of Funds
Refresher on how instant off-ramping works with Superbank’s API.
Pre-requisites
Before you begin, ensure you have:- A Superbank Developer account with API access
- Your API key
- A wallet you control that holds the source stablecoin on the chain you’ll use
- A destination bank account that supports an instant payment rail
How off-ramping differs from on-ramping
Off-ramping (stablecoin → fiat) uses a destination-amount-driven flow with a locked quote. Two practical implications worth knowing up front:- You specify what the end-user receives (e.g.
destination.amount: 100USD, or1000CAD). Superbank quotes the source crypto amount needed to deliver that — fees and FX baked in. - The deposit wallet is per-payment and short-lived. Each settlement returns a unique
payment_instructions.wallet_addressvalid for 15 minutes. After that the quote expires and you’ll need a new settlement request.
Off-Ramping
Step 1: Receive an off-ramping request
Your end-user requests to off-ramp through your UI or API. They specify the destination bank account and how much fiat they want to receive. Persist the destination bank details for the next step.Step 2: Create the settlement request
Create a settlement request by sending aPOST to /v0/settlement-requests. The response’s
payment_instructions block carries the locked quote (amount, exchange_rate, fee) and
the per-payment wallet_address you’ll send the source stablecoin to.
As with on-ramping, we recommend supplying external_id (your internal identifier) and optional
metadata — both are echoed back on every read and webhook, and external_id is filterable on
the list endpoint.
Example A — USDC on Solana → USD via RTP (same-currency, instant)
Source and destination map 1:1 (USDC ≈ USD), so no FX is performed. The quoted source amount covers the flat RTP fee plus a small variable component.Request
cURL
Response
payment_instructions so you can
render exactly what your end-user will be charged before they confirm.
Example B — USDC on Ethereum → CAD via LOCAL (cross-currency, instant)
Cross-currency: source is USDC on Ethereum, destination is CAD via Interac (routed asLOCAL).
The quote includes both the CAD-lane fee and the locked FX rate.
Request
cURL
Response
Step 3: Send the source stablecoin to payment_instructions.wallet_address
Broadcast an on-chain transfer of exactly payment_instructions.amount of
payment_instructions.currency from the wallet you specified in source.wallet_address to
payment_instructions.wallet_address.
Step 4: Wait for SETTLEMENT_COMPLETED
Listen for settlement_request.updated webhooks. The settlement progresses through:
You’ll receive a webhook on each transition:
X-Superbank-Event and X-Superbank-Signature headers, and the complete
list of event types are documented in the Webhooks guide.
Polling (fallback)
If you can’t accept webhooks, pollGET /v0/settlement-requests/:id until
status === 'SETTLEMENT_COMPLETED'. Recommended interval: 5 seconds or longer.
Step 5: Acknowledge with REQUEST_COMPLETED
Once SETTLEMENT_COMPLETED arrives, close the settlement by calling REQUEST_COMPLETED with the
on-chain transaction hash of your Step 3 deposit. This is the audit reference Superbank records
to tie the settlement to its on-chain leg.
Request
cURL
Response
Testing in sandbox
The sandbox lets you exercise the full off-ramp flow end-to-end without ever moving real crypto on-chain.Step 1: Create the settlement request
Same call as Step 2 above. Save theid from the response — that’s {settlement_id} below.
Step 2: Read the outbound payment id
Because Step 3 is a no-op in sandbox, advance the flow by transitioning the outbound payment directly. Fetch the settlement to grab the payment id:cURL
outbound_payment.id — call it {payment_id} below.
Step 3: Transition the payout to PROCESSING → COMPLETED
Use the sandbox payment-transition endpoint. Each PATCH fires the same
payment.updated and settlement_request.updated webhooks your production
handler will see.
cURL
SETTLEMENT_COMPLETED. See the Sandbox Testing guide
for the full set of sandbox endpoints.
Step 4: Acknowledge with REQUEST_COMPLETED
Same call as Step 5 above. The
transaction_hash value isn’t validated against any chain in sandbox, so any
non-empty string works:
cURL
status: "REQUEST_COMPLETED".
Common pitfalls
- Quote expired. If more than 15 minutes pass between settlement creation and your on-chain
deposit (
valid_until), the quote expires. Create a new settlement request — same destination, newpayment_instructionswith a fresh rate.
Next Steps
Webhooks
Wire up a webhook handler to detect
SETTLEMENT_COMPLETED — envelope, headers, signature
verification, and the full event list.Real-time On-Ramping
The fiat-to-stablecoin counterpart. Same product family, different direction.