There are two error shapes, not one
This is the single thing most integrations get wrong on day one.422 is a decline: your request was fine, but the payment cannot proceed for a specific
business reason. It is the only status that returns application/json and the only one carrying a
machine-readable code.
Everything else — 400, 401, 403, 404, 409, 500 — returns
text/plain; charset=utf-8: one line of English with a trailing newline, no JSON, no code.
Decline codes
All ten arrive as422. Branch on code; never on the English error text, which is written for
your logs and can be reworded.
The customer’s money
The employer’s spend rules
Employers decide when and how their benefit may be spent. These are not errors — they are the policy working.Days and times are evaluated in Asia/Ulaanbaatar, and the daily limit resets at Mongolian
midnight — not UTC midnight and not your server’s local midnight. A charge at 00:30 in
Ulaanbaatar is on the new day’s allowance.
The card or wallet
The scanned code
Both are recoverable at the till. Offer a Rescan action rather than failing the sale.
Plain-text errors
400 — your request is wrong
These are integration bugs. Retrying will not change the answer.
401 — credentials dead
Always the bodyunauthorized, whatever the cause. Stop the sale and re-pair the terminal. See
Authentication.
403 — not yours
forbidden. On a reversal this means either the transaction belongs to another merchant, or it is
not a charge. The two are deliberately indistinguishable.
404 — not found
wallet not found on a charge means the code verified but the card behind it no longer exists.
transaction not found on a reversal means the id is unknown — check you saved the id from the
charge response and not something else.
409 — already done
This is the one to handle carefully.429 and 5xx — outcome unknown
{"message":"Too Many Requests"} and internal error respectively. Neither tells you whether the
charge committed. Retry with the same Idempotency-Key, or reconcile against
GET /v1/transactions. See Environments and limits.
A decision table for your POS
Do not match on message text
Theerror string and the plain-text bodies are for humans reading logs. They may be reworded at
any time. The contract you can rely on is the HTTP status and, on a 422, the code.
If you need Mongolian text for a cashier, map the code to your own strings — the codes are
stable and the English is not.
