The funding account and headroom
Each Business holds one Cleff Account per environment, and payouts draw from it. Creation does not reserve funds. The check you make before committing volume is the treasury view, which partitions the balance into the fee earmark (reserved for your next invoice), the working balance left after it, the committed outflow of payouts not yet debited, and the headroom a new payout can safely draw on. Negative headroom means committed payouts will fail at dispatch unless funds arrive first; a shortfall surfaces at dispatch, not at creation. In sandbox the wallet is provisioned with test money when your business profile is completed, and the sandbox top-up adjusts it at will; sandbox payout creation only requires the wallet to be non-empty. In production the account is funded through the real funding path, never by API call.The life of a payout
A payout is a single instruction: pay this beneficiary, on this bank account, this amount. It moves through an explicit state machine; the full state table is on the Payouts reference. Creation.POST /v1/payouts creates the payout in pending_approval.
Creation validates the participants up front: the beneficiary must be
compliant and the named bank account must be payout_usable. The
caller-supplied idempotency_key makes creation safe to retry for 24 hours.
The approval gate. Nothing disburses without a Decision. A Decision is an
approve/reject verdict recorded by a validator: your own risk system calling
the API, or an automated policy. approve and reject are conveniences over
the canonical
POST /v1/payouts/{payoutId}/decisions;
all three share the same idempotency and state-machine guarantees. Rejection is
terminal.
Dispatch and disbursement. Approval enqueues the disbursement; the
dispatch to the payout provider runs asynchronously, so the payout stays
approved while the attempt is in flight. When the provider confirms the
funds have left, the payout reaches disbursed. Along the way the provider
may report an acknowledgment, an estimated arrival date, and a rail_ref
(the provider’s opaque reference for the disbursement), all surfaced on the
payout and as webhook events.
After disbursement. disbursed is provisional: on rails like ACH the
receiving bank can still return the funds. Once the return window closes
without a return, the payout is promoted to settled. A return moves it to
returned instead, and a late return can still overtake settled.
When things go wrong. A failed disbursement lands the payout in failed,
terminally. The recovery is a replacement: author a new payout with
corrected details, linking it to the predecessor via replaces_payout_id. A
payout the provider places under AML/sanctions review pauses in
compliance_hold and resumes its previous state when cleared. A payout
canceled before send ends in canceled.
Tracking without polling
Every in-flight transition emits a signed webhook event:payout.disbursement_submitted, payout.acknowledged,
payout.estimated_arrival_at, payout.disbursed. For reconciliation, the
Reporting surface exposes the transactions ledger
(with CSV export) and windowed payout analytics.