eSMS AfricaeSMS Africa
API ReferenceSMS API

Errors

The error envelope, the X-Request-Id header, and common SMS API error codes.

Error envelope

Every error response carries a structured envelope. The detail field is kept for backward compatibility, and error gives a stable machine-readable shape:

{
  "error": {
    "code": "insufficient_balance",
    "message": "Insufficient balance. Required USD 0.0192, available USD 0.01",
    "request_id": "3f9a1c2b4d5e6f708192a3b4c5d6e7f8",
    "details": {
      "required": 0.0192,
      "available": 0.01,
      "segments": 2,
      "recipients": 2
    }
  },
  "detail": { "code": "insufficient_balance", "...": "..." }
}
FieldDescription
error.codeStable code to branch on (see the table below).
error.messageHuman-readable explanation.
error.request_idCorrelation ID, also returned in the X-Request-Id header.
error.detailsOptional extra context for the error (e.g. required/available).

X-Request-Id

Every response - success or error - includes an X-Request-Id header. If you send your own X-Request-Id, it is echoed back; otherwise one is generated. Include this value when contacting support so a failed call can be matched to a log line.

X-Request-Id: 3f9a1c2b4d5e6f708192a3b4c5d6e7f8

Common error codes

HTTPcodeWhen it happens
400bad_requestMalformed request - bad phone number, unroutable country, missing/invalid fields.
401unauthorizedMissing, invalid, or expired API key / token.
402payment_required / insufficient_balanceWallet balance does not cover the send (required, available in details).
403forbiddenNot allowed for this account.
403insufficient_scopeAPI key lacks the required scope (e.g. send).
403account_suspendedThe account is suspended and cannot send.
403recipient_opted_outThe recipient is on your STOP list.
404not_foundMessage, batch, template or verification does not exist (or is not yours).
409conflict / duplicate_messageIdentical message to the same number within 5 minutes.
413message_too_longA rendered message exceeds the segment cap (max_segments in details).
422validation_errorRequest body failed schema validation (details.errors lists the fields).
429rate_limited / too_many_requestsPer-credential rate limit exceeded (single send 20/second, bulk 10/minute), or too many OTP starts for one number.
500internal_errorUnexpected server error - retry, and quote the request_id if it persists.

Handling errors

  • Branch on error.code, not on error.message (messages may change).
  • Treat 429 and 5xx as retryable, ideally with backoff; treat 4xx (except 429) as caller errors to fix.
  • Log error.request_id / the X-Request-Id header on failures so support can trace them.

On this page