Payments and their lifecycle
A payment is one attempt to collect money from a customer. It moves through a fixed state machine — no transition outside this table ever happens, and every transition is recorded in a timeline you can read back.
The statuses
| Status | Meaning | Terminal? |
|---|---|---|
created | The payment exists; no customer number yet (links and hosted checkout start here) | no |
initiated | We are contacting the provider | no |
awaiting_customer | The PIN prompt is on the customer’s phone | no |
awaiting_otp | The provider asked for a one-time code | no |
awaiting_code_use | The customer received a code to use at a till | no |
completed | The provider confirmed the money moved. The only status that credits your balance | yes* |
failed | The provider definitively said no (declined, insufficient funds) | yes |
expired | The customer never acted and the window closed | yes |
unknown | We asked, the network didn’t answer. Not a failure. We keep asking | no |
unresolved | Still unknown after 24 hours of retries; a human takes over. Your balance is not credited | yes* |
settled | Completed and paid out to your bank in a settlement batch | yes |
refunded | Completed, then refunded in full | yes |
* completed later becomes settled or refunded; unresolved can be manually resolved.
What you should key on
- Fulfil on
payment.succeeded(the webhook) or on readingcompleted/settled— never on anything else. - Tell the customer “payment failed” only on
failedorexpired. Treatunknownas “still confirming” — here’s why. - A payment’s full history is in the dashboard timeline: every state, when, and what caused it.
Amounts on the wire
All amounts are integers in minor units (cents). USD 100.00 is 10000. There are no
floats anywhere in Lango, and there should be none in your integration either.
| Field | Meaning |
|---|---|
amount | The order amount — what the sale is worth |
charged_amount | What the customer actually pays (order + their fees) |
merchant_net | What lands in your balance |
fees[] | Every fee, itemised, with its bearer |
charged_amount − merchant_net is always exactly the commission. To the cent, every time — the
invariant is enforced in our ledger, not just documented here.