Reference
Error format and the full list of error codes.
Errors
Errors always use this shape:
json
1{ "error": "invalid_amount", "message": "amount must be a positive number." }Some errors include extra fields (for example reference and ussd_code on otp_required, or transaction_id on provider errors).
HTTP status codes
| Status | Meaning | Action |
|---|---|---|
200 | OK / final result / idempotent replay | Read status |
201 | Resource created (payment link) | — |
202 | Accepted, pending | Wait for webhook |
400 | Invalid request | Fix the request |
401 | Missing/invalid/revoked key | Check your key |
403 | Not allowed (activation, KYC, suspended) | See error |
404 | Not found | Check the id |
409 | Reference conflict | Use a unique reference |
429 | Rate limit | Back off and retry |
5xx | Provider or server problem | Check the status before retrying |
Error codes
error | HTTP | Description |
|---|---|---|
unauthorized | 401 | Bad key |
key_not_activated | 403 | Key awaiting admin activation |
kyc_required | 403 | Live access needs approved KYC |
account_suspended | 403 | Account suspended |
sandbox_only | 403 | Endpoint requires a sandbox key |
method_disabled | 403 | Method disabled by an administrator |
invalid_json | 400 | Body is not valid JSON |
invalid_amount / amount_too_low / amount_too_high | 400 | Amount rules |
invalid_currency | 400 | Currency doesn't match the country |
invalid_country / country_not_supported | 400 | Unknown or disabled country |
invalid_operator / operator_not_supported | 400 | Unknown or disabled operator |
invalid_phone | 400 | Phone number invalid |
invalid_customer | 400 | Crypto customer fields missing |
asset_not_supported | 400 | Crypto asset inactive |
invalid_title / invalid_url | 400 | Payment link validation |
otp_required | 400 | OTP flow — see Payment flows |
invalid_otp / invalid_reference | 400 | Wrong OTP or unknown session reference |
reference_conflict | 409 | Reference reused with different data |
not_found | 404 | Unknown resource or endpoint |
rate_limited | 429 | Too many requests |
maintenance | 503 | Live API in maintenance |
provider_unavailable / provider_error | 502 | Payment provider issue |
upstream_timeout | 504 | Provider timeout — verify before retrying |
internal_error | 500 | Unexpected error |
Retrying safely
Do not blindly retry payment creation after a timeout. Save your reference, then call GET /transaction/{reference}. Retrying POST /collect with the same reference is safe: you get the original payment back.