Skip to main content
A payout draws on a virtual account’s available balance and sends it to a counterparty you saved earlier. It is the lifecycle with the most states, and two of them surface in only one place.

What advances it

COMPLETED is not terminal. A bank rail can return an already-posted payout — for a request for information, an account error, or a post-settlement claw-back. That arrives as payout.returned and the payout becomes FAILED. Only FAILED, CANCELLED and EXPIRED are endings, so an integration that tells its customer the money landed on COMPLETED needs a path back from that.
IN_REVIEW and KYT_PENDING arrive through payout.status_changed and nothing else. There is no dedicated event for either. An integration that subscribes only to the named events will see a payout leave PROCESSING and never learn where it went.

What announces it

Compare status values case-insensitively rather than matching exact strings.

Corridors

A bank payout never carries a transaction hash, and a crypto payout never carries a wire reference. Which identifiers arrive is a property of the rail, not of the payout going well — see The payout object.

Where an RFI interrupts it

KYT_PENDING is the compliance hold on this lifecycle, and it can also raise a request for information against the sub-client. Until it clears, the payout does not move. Treat a hold as a state you display, not one you resolve by retrying. Retrying with the same idempotency key returns the same held payout; retrying with a fresh one creates a second payout that will be held for the same reason.

States

Every status on every resource, and what moves it.