Getting started
Errors
Every TagPay error follows the same envelope. The HTTP status tells you the broad category; the error.code tells you exactly what went wrong; the message is human-readable.
Error envelope
Every non-2xx response uses this exact shape:
{"status": false,"message": "Amount must be a positive integer in kobo.","error": {"code": "INVALID_AMOUNT","details": {}}}
Always branch on error.code, not on the message. Messages may be reworded between releases; codes are stable contract.
HTTP status codes
| Status | Meaning |
|---|---|
200 / 201 | Success. The response body contains the result. |
400 | Client error — malformed body, invalid field, or business-rule violation. |
401 | Missing or invalid API key. |
403 | Key is valid but not permitted for this operation. |
404 | Resource does not exist. |
409 | Conflict — resource is in a state that blocks the operation. |
429 | Rate limited. Slow down and retry with backoff. |
5xx | Server error. Retry idempotently. |
Error codes
The codes you'll hit most often:
| Code | Status | Message | Hint |
|---|---|---|---|
UNAUTHORIZED | 401 | API key missing or invalid. | Check the Authorization header. |
FORBIDDEN | 403 | Key does not have permission for this operation. | — |
NOT_FOUND | 404 | Resource does not exist. | — |
INVALID_AMOUNT | 400 | Amount must be a positive integer in kobo. | — |
INVALID_EMAIL | 400 | Email is missing or malformed. | — |
INVALID_REFERENCE | 400 | Reference is malformed or already used. | — |
IDEMPOTENCY_KEY_MERCHANT_MISMATCH | 409 | Idempotency key was reused against a different endpoint (method + path). | — |
CHARGE_ALREADY_PAID | 409 | Charge has already been paid. | — |
CHARGE_EXPIRED | 410 | Charge expired before payment. | — |
REFUND_EXCEEDS_BALANCE | 400 | Refund amount exceeds the remaining refundable balance. | — |
RATE_LIMITED | 429 | Too many requests. Slow down. | — |
INTERNAL_ERROR | 500 | Unexpected server error. Try again or contact support. | — |
Retry guidance
Retry only on 429 (rate-limited) and 5xx (server error) — never on 4xx below that, which signal a client mistake that retrying won't fix.
Use exponential backoff: start at 500 ms, double each attempt, cap at 16 s, with a small random jitter. Give up after 5 attempts and surface the failure to the customer.