Skip to content

Payment states

State What it means What you do
submitted The payment network accepted the transfer and is settling. This is the normal outcome Do not retry. Wait for the webhook
settled Settled: the beneficiary has their money Nothing
failed No payment network accepted it. The entry has already been reversed: you are not charged anything Fix it and retry with another quote
unknown The payment network did not confirm: it may or may not have paid NEVER retry. It resolves on its own
reversed The bank returned an already settled payment. The funds go back to your balance Let your user know

Intermediate states that appear in the history and are not outcomes: created, pending, returned.

┌──────────► settled ──────► reversed
│ ▲ ▲
created ─► submitted ─────────► │ │
│ │ │ │
│ └──► unknown ──┤ │
│ │ │ │
└─────────┴──► failed returned
(terminal) │
└──► reversed

Allowed transitions, as the server validates them:

created → pending · submitted · failed
pending → submitted · settled · failed
submitted → settled · failed · unknown · returned
unknown → settled · failed · returned
settled → returned · reversed
returned → reversed
failed → (terminal)
reversed → (terminal)

An out-of-order event from the bank cannot revive a failed payment or settle an already settled one again: a forbidden transition returns 409 invalid_state_transition, with meta saying from where, to where and what was allowed.

submitted already carries the payment id. The outcome arrives by webhook (payment.settled or payment.failed) only once.

An unknown payment responds 200, not an error. In the meantime nothing is compensated, the payment network is re-checked with our reference and it is resolved according to what it says; we notify you by webhook. The details: when something fails.

The accounting entry is already reversed: compensated: true and fee_amount: "0". The cause is in reason (in the POST response) and in status_reason (on the payment). See when something fails.

GET /v1/payments/{id} returns events: each transition, with its actor and its reason.

A payment that was in doubt and got resolved
"events": [
{ "to_status": "submitted", "reason": "ledger_committed", "actor": "api" },
{ "to_status": "unknown", "reason": "payout_timeout", "actor": "api" },
{ "to_status": "settled", "reason": "resolved_by_reaper", "actor": "reaper" }
]
actor Who moved the payment
api Your own call
network The payment network notified us
reaper Our resolution process, re-checking with the payment network
system Internal maintenance

Common reasons: ledger_committed, payout_accepted, payout_accepted_async, resolved_by_reaper, payout_failed, payout_returned, payout_reported_failure.