Payment lifecycle
Every state a collection or payout passes through, which ones are final, and which send a webhook.
Collections
stateDiagram-v2 direction LR [*] --> created created --> processing created --> failed processing --> succeeded processing --> partial processing --> failed processing --> expired expired --> succeeded expired --> partial succeeded --> [*] failed --> [*] partial --> [*]
created→ accepted. Lasts a moment.processing→ waiting for the customer.next_actionis live.expired→ customer didn't pay in time.- A late payment can revive
expired→succeeded/partial, with the usual event. Don't make expiry irreversible.
Payouts
stateDiagram-v2 direction LR [*] --> created created --> processing created --> cancelled created --> failed processing --> succeeded processing --> partial processing --> failed processing --> expired succeeded --> [*] failed --> [*] partial --> [*] cancelled --> [*] expired --> [*]
- Cancellable only while
created. See Sending a payout.
Every state
| State | Final | Webhook | Meaning |
|---|---|---|---|
created |
No | — | Accepted, not started |
processing |
No | — | In flight |
succeeded |
Yes | payment.succeeded |
Done in full |
partial |
Yes | payment.partial |
Done for less; see settled_total |
failed |
Yes | payment.failed |
Nothing moved |
expired |
Payouts: yes. Collections: see above | — | Timed out |
cancelled |
Yes | — | Payout cancelled before sending |
reversed |
Yes | — | Reserved, not produced today |
routing |
No | — | Reserved, not produced today |
authorizing |
No | — | Reserved, not produced today |
authorized |
No | — | Reserved, not produced today |
sending |
No | — | Reserved, not produced today |
- Unknown state → treat as in flight, not as an error.
When to act
flowchart TD
e["Webhook or timer"] --> r["GET /payments/{id}"]
r --> s{"state?"}
s -- "succeeded" --> ok["Fulfil"]
s -- "partial" --> p["Handle shortfall"]
s -- "failed / cancelled" --> f["Mark unpaid"]
s -- "expired" --> x["Mark unpaid,<br/>allow late success"]
s -- "anything else" --> w["Keep waiting"]
History
GET /payments/{id}/timeline→ every state change, oldest first.
Next: Accepting a payment.