Errors

Every error has the same shape and a stable code you can branch on.

JSON
{
  "success": false,
  "error": {
    "code": "INSUFFICIENT_BALANCE",
    "message": "Your SMS balance is insufficient."
  }
}

Branch on error.code, never on error.message — messages get reworded for clarity, codes do not change once published.

Reference

CodeStatusWhat to do
VALIDATION_ERROR400Check error.details.fieldErrors for the offending field.
INVALID_API_KEY401Key missing, malformed, revoked, or not matching the org header.
ACCOUNT_SUSPENDED403Account suspended, or a live key used before approval. Contact support.
FORBIDDEN403Usually the IP allowlist. Add the sending server's address.
SENDER_NOT_APPROVED403Wait for approval, or use a different approved sender ID.
INVALID_SENDER400Register the sender ID on your account first.
INSUFFICIENT_BALANCE402Not enough SMS credits for the send — buy a bundle. Wallet money is never charged per message, so a funded wallet does not prevent this. Also returned when you try to buy a bundle your wallet cannot afford; the message says which.
INVALID_PHONE_NUMBER400No valid recipients. Check rejected_recipients for why.
RECIPIENT_SUPPRESSED400Every recipient opted out. Use a transactional type if appropriate.
INVALID_MESSAGE400Body empty or over 10 segments.
DUPLICATE_REQUEST422Idempotency key reused with a different body. Use a new key.
REQUEST_IN_PROGRESS409The same key is still processing. Retry in a moment.
RATE_LIMITED429Back off and retry. The message says how long.
PROVIDER_ERROR502Upstream network problem. Safe to retry with the same idempotency key.
NOT_FOUND404The resource does not exist, or belongs to another account.
INTERNAL500Our fault. Retry; if it persists, contact support with the time.

Validation detail

A VALIDATION_ERROR names the fields that failed, so you can surface the problem rather than a generic message.

JSON
{
  "success": false,
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Invalid request",
    "details": {
      "formErrors": [],
      "fieldErrors": {
        "sender": ["Sender ID cannot exceed 11 characters"],
        "recipients": ["At least one recipient is required"]
      }
    }
  }
}

What to retry

StatusRetry?
400, 403, 404, 422No — the request will never succeed unchanged.
401No — fix the credentials first.
402After topping up.
409, 429Yes, after a delay.
500, 502, 503Yes, with backoff and the same idempotency key.