Create a settlement request by sending a POST request to /v0/settlement-requests endpoint on Superbank’s API.
Send an Idempotency-Key header. Recommended today, required
in a future API version. Generate a UUID v4 per logical operation
and include Idempotency-Key: <uuid> on the POST. Same key
replayed → we return the original response, no duplicate settlement.
See the Idempotency guide for
retention, scope, error codes, and dispatcher pattern.
We recommend supplying an external_id (your own identifier for this
settlement) and optional metadata (free-form key/value pairs) on
create. Both are echoed back on every read and webhook, and external_id
is filterable on the list endpoint — meaning you don’t need to persist
anything from the create response (not Superbank’s id, not
payment_instructions). Look the settlement up by external_id
whenever you need it; the full record (including payment_instructions)
comes back on every lookup.
curl --request POST \ --url https://api-sandbox.superbank.co/v0/settlement-requests \ --header 'Content-Type: application/json' \ --header 'X-Api-Key: YOUR_API_KEY' \ --data '{ "type": "STABLECOIN_TO_STABLECOIN", "payment_reason": "REMITTANCES", "amount": 20, "external_id": "txn_abc123", "metadata": { "user_id": "usr_42", "source": "mobile_app" }, // Optional. Override only when your processor's settlement window // differs from the T+3 default. ISO 8601, must be in the future, max 30 days out. "reconciliation_expected_at": "2026-05-04T17:00:00Z", "destination": { "currency": "USDC", "rail": "SOLANA", "is_third_party": true, "wallet_address": "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", "beneficiary": { "type": "BUSINESS", "address": { "country_code": "US" }, "business_name": "Acme Corp" } } }'
Picking the right payment_reason. The enum is broad and is used for categorisation and
reporting, not customer-visible metadata. For typical fintech flows the values you’ll actually use
are: REMITTANCES (cross-border consumer transfers), PAYMENT_FOR_GOODS_AND_SERVICES (merchant
payments), EMPLOYEE_SALARIES_OR_WAGES (payroll). Pick the closest specific value rather than
reaching for OTHER.
destination.is_third_party — pick what’s true, not what’s convenient. Set true when the
beneficiary is not your own registered company (e.g., a payout to a vendor, contractor, or
end-user). Set false only when the destination is your own company / registered account.
Some fields (e.g. outbound_payment, inbound_payment, timestamps, failure fields) are omitted in the examples on this page for brevity — see the Settlement Request reference for the full schema.
You don’t need to persist anything from this response - not Superbank’s
id, and not payment_instructions. Both come back on the lookup.
Look the settlement up later via the external_id filter whenever the
next step runs:
external_id is not enforced as unique on Superbank’s side. If you reuse the same value
(intentionally or by mistake), the response can include multiple settlements. If you need to
disambiguate, filter the results client-side using metadata.
Step 3: Start on-ramping with your infrastructure provider
Use thepayment_instructions returned in the previous step as the on-ramping destination to request the deposit instructions from your infrastructure provider.For example, here’s how to do it with Bridge as your infrastructure provider.
Step 4: Update settlement request status to FUNDS_SENT
Once the End-User has initated the payment using your infrastructure provider, update the settlement request status to FUNDS_SENT by sending the PUT request to /v0/settlement-requests/:id.This triggers the instant settlement from your pre-funded wallet, to your User’s destination wallet.
Once you confirm the funds are sent via Step 4, Superbank moves USDC from your pre-funded wallet to the End-User’s wallet in real time.The End-User receives their USDC instantly (blockchain speed).
Between Step 5 (Superbank moves the funds) and Step 6 (you call REQUEST_COMPLETED with the transaction hash), your system needs to know that the settlement is done. There are two ways to find out, and we strongly recommend the first.
Subscribe a webhook endpoint and listen for settlement_request.updated events where data.status === 'SETTLEMENT_COMPLETED'. As soon as Superbank moves the funds, you’ll get a signed POST to your endpoint and can immediately fire Step 6.
If you can’t accept webhooks, poll GET /v0/settlement-requests/:id until status === 'SETTLEMENT_COMPLETED'. Recommended interval: 5 seconds or longer. Polling more aggressively wastes your rate-limit budget without speeding up settlement (the underlying blockchain confirmation is the gating factor, not our API).
Webhooks are the better choice in almost every case: lower latency, no wasted requests, and you don’t have to keep state about what you’re polling for.
After T+X — when you’ve collected the fiat from the end user and reconciled
it on-chain into your Superbank prefunded wallet — close the settlement by
calling REQUEST_COMPLETED with the transaction hash of the on-chain
reconciliation.The on-chain reconciliation typically happens one of two ways:(a) Direct deposit via payment_instructions. Use the wallet address
or bank details shown in payment_instructions from Step 2’s response.
Funds deposited there settle automatically into the prefunded wallet, so
you don’t need to perform a separate forwarding step.(b) Third-party forwarding. If you receive the funds on a third-party
infrastructure first (e.g. Bridge, Coinbase, your own off-ramp), forward
the resulting stablecoin on-chain to the Superbank prefunded wallet to
reconcile.In both cases, the transaction_hash in the request below is the hash of
the on-chain transfer that lands stablecoin in the prefunded wallet — not
the destination payment Superbank made to the end user (that’s the
OUTBOUND, which auto-confirms in seconds and doesn’t need to be reported
back).
This step is crucial. Without the on-chain transaction hash from the reconciliation step,
Superbank cannot match the settlement to the inbound funds.
The status in the response depends on whether Superbank has already
detected the inbound on-chain transfer to your prefunded wallet at the
moment you submit this call:
REQUEST_COMPLETED — the inbound PAYIN was already detected and
the amount matched. The settlement is final; completed_at is set and
inbound_payment is populated. This is the typical path when you call
REQUEST_COMPLETED after the on-chain transfer has had time to confirm
and be picked up by Superbank’s indexer.
AWAITING_PAYIN_RECONCILIATION — your transaction_hash is
recorded, but the matching inbound PAYIN has not yet been observed.
Superbank will defer the amount check until the PAYIN lands. As soon as
it does, the request automatically resolves to REQUEST_COMPLETED (or
PAYIN_AMOUNT_MISMATCH if the received amount differs from the
settlement amount) and Superbank emits another settlement_request.updated
webhook. No further action is required from your side. This is most
commonly seen when you call REQUEST_COMPLETED immediately after
broadcasting the on-chain transfer, before it has confirmed and been
indexed, or on rails with slower finality.
AWAITING_PAYIN_RECONCILIATION (deferred path)Same request, but the inbound PAYIN has not yet been indexed. Note the
absent inbound_payment and completed_at — both will be populated when
Superbank later detects the on-chain transfer and finalises the request.
What to do when you receive AWAITING_PAYIN_RECONCILIATION. Treat
it as a successful acknowledgement — do not retry the
REQUEST_COMPLETED call. Wait for the follow-up
settlement_request.updated webhook (or poll the settlement) to see
the request transition to REQUEST_COMPLETED once the inbound PAYIN
lands and matches.
Wire up a webhook handler to detect SETTLEMENT_COMPLETED without polling — envelope, headers,
signature verification, and the full event list.
Fiat → Stablecoin on-ramping
Same destination shape, but the end-user deposits fiat instead of
stablecoin. Use this when there’s a fiat leg on the source side and
you want Superbank to handle the conversion and deposit instructions.