Skip to main content
A payout advances through a fixed sequence. Statuses are never skipped and never move backwards.

What moves a payout forward

1

CREATED → PENDING_PAYMENT

We lock an FX rate, compute the settlement amount and fees, and issue a payment instruction with an expiry. Generation starts as soon as the payout is created; a sweep every 30 seconds re-picks anything left behind.Until this runs, settlement_amount is 0 and payment_instruction is null. That is not an error — the amount is genuinely unknown until the rate is locked.
2

PENDING_PAYMENT → PAYMENT_RECEIVED

We match your settlement to the instruction by the account it was paid into and the amount. Crypto settlements additionally wait for network confirmations.Underpayment does not advance the payout — it is held for review rather than partially processed. Overpayment proceeds, and the excess is recorded and returned with any later refund.
3

PAYMENT_RECEIVED → PROCESSING

We dispatch the transfer to the processor. Each attempt is a separate record, so a retry never overwrites the history of a failed one — see GET /v1/payouts/{id}/outflows.
4

PROCESSING → SUCCESSFUL or FAILED

We poll the processor until it reports a terminal outcome. A failed attempt with retries remaining returns the payout to PAYMENT_RECEIVED so a fresh attempt is dispatched; only once attempts are exhausted does it become FAILED.

Expiry is terminal

If the instruction expires unpaid, the instruction is marked EXPIRED and the payout ends at EXPIRED. It is not regenerated and the rate is not re-locked. A merchant who misses the window creates a new payout.
A payout that is holding money is never expired — not on underpayment, and not while a crypto settlement is still confirming. Those stay in PENDING_PAYMENT for our operations team to resolve. EXPIRED only ever means no funds arrived, which is why it needs no refund.
The default window is 30 minutes on the crypto rail and configurable per account on the bank rail. Read expires_at off the instruction rather than assuming a duration.

When a payout fails

If a payout fails after your settlement was confirmed, the money is not lost. We raise a refund and send it to the destination you registered for that settlement currency, minus the cost of sending it back. The payout is marked is_refunded: true with a refund_reference as soon as the refund is raised. There is no wallet and no balance to withdraw — see Refunds. A payout that failed before any money arrived has nothing to return and raises no refund.

No cancellation

There is no cancel endpoint. A payout you no longer want simply goes unpaid and lapses to EXPIRED at the instruction’s expiry. Once you have settled it, it is committed.

The status timeline

GET /v1/payouts/{id} returns a status_timeline: every transition in order, each with the reason it happened, what triggered it, and when.
Use this for support and reconciliation rather than inferring history from webhook arrival times, which reflect delivery rather than the transition itself.

Reason codes

Status values are uppercase everywhere they appear — on the payout, in status_timeline, and inside webhook payloads. Webhook event types are the lowercase dotted form (payout.pending_payment), so the two are easy to mix up when you branch on them.