Skip to content

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.

CodeHTTPRetryWhenWhat to do
INVALID_API_KEY401noNo key, a malformed key, or one we don't know.Check the Authorization header is Bearer apk_… with the whole key.
KEY_REVOKED401noThe key was revoked, or a rolled key's grace period ended.Use the replacement key, or create a new one.
KEY_EXPIRED401noPast the key's expiry date.Roll or create a key. We email before expiry.
KEY_SUSPENDED401noOur team paused the key.Check your security contact's email, or contact support.
KEY_PENDING_APPROVAL401noA new live key we haven't approved yet.Wait for the approval email; keep using your current key.
KEY_REJECTED401noWe didn't approve this live key.Read the reason in the Console and create a key that fits it.
KEY_WRONG_ENVIRONMENT401noA key used against the other environment's host.Use test keys for testing and live keys for live.
INSUFFICIENT_SCOPE403after fixingThe 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_ALLOWED403after fixingThe request came from an IP outside the key's allowlist.Call from an allowlisted server, or add the address to a new key.
WORKSPACE_SUSPENDED403noAPI access for the workspace is suspended.Contact support.
LIVE_ACCESS_REQUIRED403after fixingA live key in a workspace without live access.Apply for live access.
VALIDATION_ERROR422after fixingThe body or a parameter is invalid.error names the field; details.issues lists every problem.
NOT_FOUND404noNo such object in this environment.Check the id and that you're using the right environment's key.
IDEMPOTENCY_KEY_REQUIRED400after fixingA money-moving POST without Idempotency-Key.Send one. See Idempotency.
IDEMPOTENCY_KEY_REUSED409noThe key was used with a different body.Use a new key for a different payout.
IDEMPOTENCY_IN_PROGRESS409yesThe first request with this key is still running.Retry in a second with the same key.
RECIPIENT_INVALID422after fixingThe number or account can't receive this payout.Ask the recipient for different details.
METHOD_UNAVAILABLE503yesThe payout method is down or not enabled for you.Retry later, or use another method.
LIMIT_PER_TX_EXCEEDED422after fixingAbove your per-payout limit.Send less, or ask us to review your limits.
LIMIT_DAILY_EXCEEDED422yesToday's total would pass your daily limit.Wait until midnight Nairobi time.
LIMIT_MONTHLY_EXCEEDED422yesThis month's total would pass your monthly limit.Wait for the 1st, or ask us to review your limits.
INSUFFICIENT_BALANCE402after fixingYour balance doesn't cover the payout and its fees.details.required_usdc says how much. Fund your balance.
CAPABILITY_PAUSED503yesWe paused payouts, a method, or writes for maintenance or an incident.Retry later with backoff.
RATE_LIMITED429yesToo many requests a second for the key, or too many recipient checks a minute.Wait for Retry-After seconds.
RECIPIENT_NAME_MISMATCH422after fixingReserved: not returned today.Use recipients/verify and name_match instead.
QUOTE_EXPIRED410after fixingReserved: not returned today; creating a payout reprices it.-
PAYOUT_IN_REVIEW202noReserved: 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

CodeHTTPMeaningWhat to do
VALIDATION_ERROR422A parameter is missing or invalid.Fix the request; error says which field and why.
AUTH_ERROR401No token, or it has expired or been revoked.Refresh the access token and retry once.
FORBIDDEN403The account isn't allowed to do this.Don't retry. Check the account's role or verification.
NOT_FOUND404The resource or route doesn't exist, or isn't this account's.Check the id and the path.
CONFLICT409The request clashes with the current state.Re-read the resource, then decide.
QUOTE_EXPIRED410The exchange rate you confirmed has expired.Get a new quote and confirm again.
INSUFFICIENT_FUNDS402The balance can't cover the amount and fees.Top up or lower the amount.
RATE_LIMIT429Too many requests from this address.Wait and retry with backoff. See Rate limits.
NOT_SUPPORTED405The operation is deliberately not offered.Use the alternative the error describes.
RAIL_ERROR502A payment network refused or failed the request.Retry later; the money hasn't moved.
BLOCKCHAIN_ERROR502Avalanche didn't accept the transaction.Retry later.
SERVICE_PAUSED503Payments are briefly paused; money is safe.Retry in a few minutes.
INTERNAL_ERROR500Something 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&currency=USDC"
# HTTP/1.1 422
# {"ok":false,"error":"amount must be a positive decimal in major units","code":"VALIDATION_ERROR"}

Retrying

  • Retry 429, 502, 503 and 500 with exponential backoff: 1s, 2s, 4s, 8s, then give up.
  • Always retry money-moving calls with the same idempotency key.
  • Never retry 4xx errors other than 429 without changing the request.