Errors
Every error code, its HTTP status, whether to retry and what to do.
Partner API errors
Partner API errors look like every other error, plus a requestId (also in the X-Request-ID header) and sometimes details. Branch on code; error is a sentence for people and may change.
{
"ok": false,
"error": "This payout would take today's total past your daily limit of KES 1,000,000.",
"code": "LIMIT_DAILY_EXCEEDED",
"requestId": "0c1f7a3e-5b2d-4e8f-9a61-7d3c2b1e0f45",
"details": { "used_today": 980000, "daily_limit": 1000000 }
}Retry: yes means retry the same request later with backoff (and the same Idempotency-Key); after fixing means change something first; no means don't retry as is.
| Code | HTTP | Retry | When | What to do |
|---|---|---|---|---|
INVALID_API_KEY | 401 | no | No key, a malformed key, or one we don't know. | Check the Authorization header is Bearer apk_… with the whole key. |
KEY_REVOKED | 401 | no | The key was revoked, or a rolled key's grace period ended. | Use the replacement key, or create a new one. |
KEY_EXPIRED | 401 | no | Past the key's expiry date. | Roll or create a key. We email before expiry. |
KEY_SUSPENDED | 401 | no | Our team paused the key. | Check your security contact's email, or contact support. |
KEY_PENDING_APPROVAL | 401 | no | A new live key we haven't approved yet. | Wait for the approval email; keep using your current key. |
KEY_REJECTED | 401 | no | We didn't approve this live key. | Read the reason in the Console and create a key that fits it. |
KEY_WRONG_ENVIRONMENT | 401 | no | A key used against the other environment's host. | Use test keys for testing and live keys for live. |
INSUFFICIENT_SCOPE | 403 | after fixing | The key lacks the scope the endpoint needs, or the workspace isn't approved for it. | details.scope names it. Use a key with it, or request the capability. |
IP_NOT_ALLOWED | 403 | after fixing | The request came from an IP outside the key's allowlist. | Call from an allowlisted server, or add the address to a new key. |
WORKSPACE_SUSPENDED | 403 | no | API access for the workspace is suspended. | Contact support. |
LIVE_ACCESS_REQUIRED | 403 | after fixing | A live key in a workspace without live access. | Apply for live access. |
VALIDATION_ERROR | 422 | after fixing | The body or a parameter is invalid. | error names the field; details.issues lists every problem. |
NOT_FOUND | 404 | no | No such object in this environment. | Check the id and that you're using the right environment's key. |
IDEMPOTENCY_KEY_REQUIRED | 400 | after fixing | A money-moving POST without Idempotency-Key. | Send one. See Idempotency. |
IDEMPOTENCY_KEY_REUSED | 409 | no | The key was used with a different body. | Use a new key for a different payout. |
IDEMPOTENCY_IN_PROGRESS | 409 | yes | The first request with this key is still running. | Retry in a second with the same key. |
RECIPIENT_INVALID | 422 | after fixing | The number or account can't receive this payout. | Ask the recipient for different details. |
METHOD_UNAVAILABLE | 503 | yes | The payout method is down or not enabled for you. | Retry later, or use another method. |
LIMIT_PER_TX_EXCEEDED | 422 | after fixing | Above your per-payout limit. | Send less, or ask us to review your limits. |
LIMIT_DAILY_EXCEEDED | 422 | yes | Today's total would pass your daily limit. | Wait until midnight Nairobi time. |
LIMIT_MONTHLY_EXCEEDED | 422 | yes | This month's total would pass your monthly limit. | Wait for the 1st, or ask us to review your limits. |
INSUFFICIENT_BALANCE | 402 | after fixing | Your balance doesn't cover the payout and its fees. | details.required_usdc says how much. Fund your balance. |
CAPABILITY_PAUSED | 503 | yes | We paused payouts, a method, or writes for maintenance or an incident. | Retry later with backoff. |
RATE_LIMITED | 429 | yes | Too many requests a second for the key, or too many recipient checks a minute. | Wait for Retry-After seconds. |
RECIPIENT_NAME_MISMATCH | 422 | after fixing | Reserved: not returned today. | Use recipients/verify and name_match instead. |
QUOTE_EXPIRED | 410 | after fixing | Reserved: not returned today; creating a payout reprices it. | - |
PAYOUT_IN_REVIEW | 202 | no | Reserved: held payouts return the payout with status in_review instead. | - |
Failures after the payout was accepted
A payout that was accepted but didn't complete ends as failed with a failure_code on the payout object (not an HTTP error): RECIPIENT_INVALID, METHOD_UNAVAILABLE, FUNDING_FAILED, PAYOUT_FAILED or PAYOUT_RETURNED. See Payouts.
Public and account API errors
Shape
HTTP/1.1 422 Unprocessable Entity
{
"ok": false,
"error": "amount must be a positive decimal in major units",
"code": "VALIDATION_ERROR"
}code is stable: build your logic on it. error can change wording and is safe to show to people.
Codes
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
VALIDATION_ERROR | 422 | A parameter is missing or invalid. | Fix the request; error says which field and why. |
AUTH_ERROR | 401 | No token, or it has expired or been revoked. | Refresh the access token and retry once. |
FORBIDDEN | 403 | The account isn't allowed to do this. | Don't retry. Check the account's role or verification. |
NOT_FOUND | 404 | The resource or route doesn't exist, or isn't this account's. | Check the id and the path. |
CONFLICT | 409 | The request clashes with the current state. | Re-read the resource, then decide. |
QUOTE_EXPIRED | 410 | The exchange rate you confirmed has expired. | Get a new quote and confirm again. |
INSUFFICIENT_FUNDS | 402 | The balance can't cover the amount and fees. | Top up or lower the amount. |
RATE_LIMIT | 429 | Too many requests from this address. | Wait and retry with backoff. See Rate limits. |
NOT_SUPPORTED | 405 | The operation is deliberately not offered. | Use the alternative the error describes. |
RAIL_ERROR | 502 | A payment network refused or failed the request. | Retry later; the money hasn't moved. |
BLOCKCHAIN_ERROR | 502 | Avalanche didn't accept the transaction. | Retry later. |
SERVICE_PAUSED | 503 | Payments are briefly paused; money is safe. | Retry in a few minutes. |
INTERNAL_ERROR | 500 | Something broke on our side. | Retry with the same idempotency key; tell us if it persists. |
Handling errors
curl -i "https://api.autopayke.com/api/v1/fees/quote?product=cashout&amount=-1¤cy=USDC"
# HTTP/1.1 422
# {"ok":false,"error":"amount must be a positive decimal in major units","code":"VALIDATION_ERROR"}Retrying
- Retry
429,502,503and500with exponential backoff: 1s, 2s, 4s, 8s, then give up. - Always retry money-moving calls with the same idempotency key.
- Never retry
4xxerrors other than429without changing the request.