Skip to Content
DocumentationError Handling

Error Handling

StatusMeaningWhat to do
400Invalid requestFix the request before retrying
401Missing or invalid credentialsCheck the server-side API key
402Insufficient creditsTop up before retrying
403Account or route not allowedReview account permissions
404Resource not foundCheck the URL or resource ID
409Conflict (e.g. idempotency key already in flight)Wait and retry, or reuse the stored result
429Rate limitedBack off and retry with jitter
5xxTemporary service failureRetry safely with exponential backoff

Error responses include a structured code, a human message, and a request_id for support investigations.

{ "success": false, "error": { "code": "rate_limit_exceeded", "message": "Rate limit exceeded" }, "request_id": "dfffa252-4781-43ff-8e1a-bf01a754d66a" }

Principles

  • Do not blindly retry a send request. A send is not inherently idempotent — reuse an Idempotency-Key (max 128 chars) for the single and bulk endpoints so a retry replays the stored result instead of sending twice.
  • Treat 429 and 5xx as safe to retry. Everything else usually needs a code fix, not a retry.
  • Log the request_id. When you open a support ticket, include it so the team can trace the exact request.
  • Match with typed SDK errors rather than string-matching code values:
SDKHow to catch
Goerrors.As(err, *sendafrica.APIError); apiErr.IsRateLimited()
Pythonexcept InsufficientCreditsError etc. from sendafrica
TypeScripterr instanceof SendAfricaError; err.isRateLimited
Last updated on