Payout lifecycle
The states a payout moves through, and which webhook events they emit.
Every payout moves through a small state machine. Each transition emits a webhook event named after it, with the payout as GET /payouts/{id} returns it in data.
created ──approve──▶ approved ──send-claim-link, then the claim──▶ requested ──▶ completed
│ ──pay────────────────────────────▶ │
│ └──▶ failed ──pay──▶ requested
└──▶ expiredStates
| Status | Meaning | Event |
|---|---|---|
created | The payout exists and waits for approval by the sending team. | payout.created |
approved | The sending team approved the payout. The amount is reserved against the team balance. The payout waits for the next step: a claim link and the recipient's claim, or pay. approvedAt says when. | payout.approved |
requested | The transfer was requested from the payment provider, by the recipient's claim or by POST /payouts/{id}/pay. | payout.requested |
completed | The transfer settled. If the provider later returns it to a recipient with an account, the payout goes back to requested with a retry object. | payout.completed |
failed | The provider rejected the transfer. failureCode and failureReason say why. Fix the counterparty, then call pay again. | payout.failed |
expired | The payout expired unclaimed. Terminal. While a payout is created or approved, expiresAt says when this happens. | payout.expired |
The happy path is created → approved → requested → completed. status is an open enum: treat a value you do not know as a fallback case.
Retrying a failed payout
failed is the status that asks the sender to act. A push payout to a counterparty you entered that the provider returns becomes failed as soon as Talentir Operations has reviewed the return. The payout keeps its approval, so no second approval is needed. Correct the counterparty with PATCH /counterparties/{id} and call POST /payouts/{id}/pay again; the payout returns to requested, and payout.completed or another payout.failed follows.
A claimed payout that the provider returns stays requested, and completedAt stays null. Talentir Operations reviews each return first; until the review ends, retry is null. After the review, Talentir emails the recipient a retry link to enter new payment details. Until a new attempt delivers the payout, retry gives url, code, and reason. url is the retry link: show it in your app while it is set, so the recipient finds it outside the email. It is null while the new attempt runs. code has the same values as failureCode, and reason is the same as text. After delivery, retry is null again.
After the retry completes, the payout becomes completed and emits payout.completed. paymentMethod, requestedAt, and completedAt use the successful delivery. The public payout ID and requested amount stay the same.
Notes
PATCH /payouts/{id}is allowed only while the status iscreated. Alockedpayout refusesPATCHaltogether.DELETE /payouts/{id}is allowed while the status iscreated,approved, orexpired. Arequested,completed, orfailedpayout cannot be deleted (409PAYOUT_NOT_DELETABLE). The money of afailedpayout waits forpay. A deleted payout is gone from the API: every endpoint answers 404PAYOUT_NOT_FOUNDfor it, and lists do not include it. Thepayout.deletedevent carries whatDELETEreturns:{ object, id, deleted: true }.availableOndelays the claim and the payment, not creation: the payout exists immediately but cannot be claimed or paid before that UTC day.- A counterparty change (
PATCH /counterparties/{id}on the address, payment method, or tax identity) moves everyapprovedpayout to that counterparty back tocreated, because the sender now pays a different destination. Each such payout emitspayout.updated. - From
requestedon,paymentMethodnames the rail and settlement currency, andrecipientInvoiceSourcesays who wrote the document behindrecipientInvoiceUrl:self_billing(Talentir issued it in the recipient's name) orrecipient_upload(the recipient uploaded their own invoice while claiming).