Payment states end up in support tickets, finance exports and customer emails. If a state cannot be explained in one sentence, it will be misunderstood — usually at the worst moment.
One authority for transitions
Every transition is decided in one place: the gateway’s state machine. Background workers never write a status directly. They record evidence (an observation, a new chain tip, an expiry) and ask the state machine to re-evaluate. The machine locks the payment row, computes the target state from the evidence and applies the transition only if it is allowed. Each change writes a state event and an outbox message in the same database transaction.
The happy path
created → awaiting_payment → detected → confirming → confirmed
Most payments only ever touch these five states. Each has a plain-language description that appears in the dashboard, the checkout and the API documentation.
The honest exceptions
The remaining states exist because reality is messy:
| State | Plain meaning |
|---|---|
underpaid |
Less than the quoted amount arrived and confirmed. |
overpaid |
More arrived than was quoted. The order can be fulfilled; the excess needs a decision. |
expired |
The quote ran out before anything was observed. |
late_payment |
Something arrived after expiry. It is recorded, never silently credited. |
reorged |
A block with this payment was replaced. Do not fulfil until it confirms again. |
manual_review |
Held for a documented decision. |
resolved |
A person resolved it, with a reason that stays on record. |
failed / canceled |
Ended for a validated reason, or by the merchant before payment. |
No colour-only meaning
Each state has a label, an icon and a sentence of explanation, so it reads the same with or without colour, animation or sight. The same vocabulary is shared by every GRYPHEM interface, so a status means one thing everywhere.