Skip to main content

Error response format

All errors return a JSON body with an error code and a human-readable message:
Use the error field for programmatic handling. Use message for logging and debugging — it is not guaranteed to be stable across releases.

Error codes

Handling errors in TypeScript

Retrying on 429 and 5xx

429 Too Many Requests — the response includes a Retry-After header (in seconds) and a retryAfter field in the JSON body. Wait at least that long before retrying. 500 Internal Error — these are transient. Use exponential backoff with jitter: wait 1s, then 2s, then 4s, up to a reasonable cap. Do not retry indefinitely. Example exponential backoff in TypeScript:

Idempotency

The /v1/messages/send and /v1/sms/send endpoints are not automatically idempotent. If you retry a send operation, you may deliver the message twice. To avoid duplicate sends:
  • Track delivery state on your side before retrying
  • Only retry on 5xx errors, not on 429s for sends — instead, queue and respect the Retry-After window
  • For transactional sends, use a unique identifier in your request body that you check before resending
Next: Rate limits →
Last modified on March 19, 2026