A payout moves money out of your balance to a beneficiary you have already registered. It is a
single, idempotent, unattended call: no step-up authentication, no multi-call preview-then-confirm.
There are two rails, and they behave the same way in every respect except where the money lands.
Both take the same request body. The rail you call, and the beneficiary you name, decide
everything else — there is no rail field, no network field and no token field to set.
This page covers what the two rails share. The per-rail pages cover what differs.
You pay a beneficiary, not an address
You cannot send money to a raw account number or wallet address. You
register a beneficiary first, and then pay out to its beneficiaryId.
A beneficiary is bound to one rail. A bank-rail beneficiary cannot receive a stablecoin payout and
a wallet-rail beneficiary cannot receive a fiat one.
A wrong-rail beneficiary fails with 400, not 404. The beneficiary is yours, so it
resolves; the call then fails on the rail details it does not carry — sending a bank-rail
beneficiary to POST /v1/payouts/token returns 400 with errorKey: InvalidWalletAddress.
A 404 here means the id is unknown or belongs to another partner, which is a different fix.
Check rail on the beneficiary before you pay it.
Idempotency
Every payout requires an idempotencyKey, and it is the mechanism that makes a retry safe.
- The key namespace is shared across both rails. A key used for a fiat payout cannot be reused
for a stablecoin payout.
- Replay detection hashes the mapped request, not the raw bytes. Whitespace or field ordering
in your JSON cannot cause a spurious conflict.
- Reusing a key with a different payload returns
409 with idempotency_key_reuse.
- A blank key is treated as absent rather than as a value, so blanks do not collide with one
another. Send a real key.
Generate the key from something stable in your own system — an invoice or order id — rather than
a random value. A random key regenerated on retry defeats the protection entirely.
status is the outcome, not the HTTP code
A 201 means the payout was accepted, not that it settled. Treat status as an open set of
strings, not a fixed enum — new values can be added without a breaking version change, so match
on the values you know and handle the rest gracefully rather than failing closed.Settlement is asynchronous on both rails. The terminal state arrives by webhook, never in the
response to the call that created the payout.
Errors
Tracking a payout
The reference on the response is the business reference. Use it to look the payout up in
Transactions, and subscribe to transaction.status.changed to be told when
it settles rather than polling. See Receiving webhooks.