error.code.
HTTP status codes
| Code | Meaning |
|---|---|
| 200 | Success. |
| 201 | A resource was created. |
| 400 | Invalid request, failed validation, or business rule (for example insufficient balance). |
| 401 | Missing or invalid secret key or credentials. |
| 403 | Authenticated, but not allowed (live key before verification or live mode, or suspended account). |
| 404 | Resource does not exist for this merchant. |
| 409 | Conflict (duplicate reference, idempotency key reused with a different body, already released). |
| 422 | Semantic validation failed (malformed payload that passed basic checks). |
| 429 | Rate limited (RATE_LIMITED). Back off and retry. See Rate Limits. |
| 502 | Upstream provider error (banks, checkout provider). |
Error envelope
{
"success": false,
"error": {
"code": "INVALID_REQUEST",
"message": "Idempotency-Key header is required for this operation",
"details": {}
},
"meta": {
"requestId": "req_01hxyz"
}
}
| Field | Description |
|---|---|
error.code | Stable machine readable code. Branch on this, not on the message text. |
error.message | Human readable explanation. |
error.details | Optional extra fields (for example available and requested on insufficient balance). |
meta.requestId | Include this when you contact support. |
Common codes
error.code | Typical HTTP | When it happens |
|---|---|---|
UNAUTHORIZED | 401 | No Bearer token, bad JWT, or unknown secret key. |
FORBIDDEN | 403 | Live key used before verification or live mode, or action not allowed for this account. |
NOT_FOUND | 404 | Unknown customer, escrow, wallet, or withdrawal for this merchant. |
INVALID_REQUEST | 400 | Missing idempotency key, bad environment, or other client error. |
INSUFFICIENT_BALANCE | 400 / 422 | Withdrawal larger than available, or debitPayer: true when the payer cannot cover the hold. |
GUEST_REFUND_NO_PAYMENT | 409 | Guest refund when no successful checkout payment exists for the hold. |
GUEST_REFUND_PENDING | 409 | Guest refund, release, or dispute while pendingProviderRefund is set. |
AMOUNT_MISMATCH | 400 | Checkout or payment amount or currency does not match the hold or wallet. |
ESCROW_NOT_PAYABLE | 409 | Checkout or debit against a hold that is not awaiting_funding. |
ESCROW_NOT_CANCELLABLE | 409 | Cancel called after the hold was funded. Use refund. |
ESCROW_INVALID_STATE | 409 | Release or refund while the hold is not held / partially_released (including while disputed). |
INVALID_RELEASE / INVALID_REFUND | 400 | Amount exceeds remaining held funds. |
INVALID_DISPUTE | 409 / 400 | Dispute opened on an unfunded hold, already resolved, or a split that does not equal remaining held. |
DISPUTE_EXISTS | 409 | An open dispute already exists on this hold. |
DUPLICATE_REFERENCE | 409 | Escrow or withdrawal reference already used on this merchant. |
CUSTOMER_HAS_ACCOUNT | 409 | DELETE /customers/{id} when the customer already has a NUBAN. |
CUSTOMER_HAS_ESCROW | 409 | DELETE /customers/{id} when the customer is payer, payee, or party on an escrow. |
BVN_NAME_MISMATCH | 400 | BVN name does not match the customer on POST /wallets. |
PROVIDER_ERROR | 502 | Bank resolve, identity lookup, or checkout could not be started. |
RATE_LIMITED | 429 | Too many requests for this merchant. Back off. |
| Duplicate or named conflicts | 409 | Email already used, or idempotency key reused with a different body. |
Idempotency-Key on money moving POSTs.