Reference
Error Codes
Every error response from Sendexa includes an HTTP status code and a machine-readable code field you can branch on.
Error Response Format
JSON
{"success": false,"message": "The phone number is not valid.","code": "INVALID_PHONE_NUMBER","requestId": "req_abc123","errors": [{ "field": "to", "message": "Must be a valid E.164 or local phone number." }]}
errors[] is only present on 400 validation responses. Include requestId in any support ticket.
HTTP Status Codes
| Code | Status | Meaning |
|---|---|---|
| 200 | OK | Request succeeded. |
| 201 | Created | Resource created successfully. |
| 400 | Bad Request | Validation failed — check the errors array in the response body. |
| 401 | Unauthorized | Missing or invalid Authorization header. |
| 403 | Forbidden | Credentials are valid but the API key lacks permission for this action. |
| 404 | Not Found | The requested resource (message ID, call ID, etc.) does not exist. |
| 409 | Conflict | Action conflicts with current resource state (e.g. OTP already verified). |
| 422 | Unprocessable Entity | Request is well-formed but semantically invalid (e.g. unsupported country). |
| 429 | Too Many Requests | Rate limit exceeded. Respect the Retry-After header. |
| 500 | Internal Server Error | Unexpected server error. Retry with backoff; contact support if persistent. |
| 503 | Service Unavailable | The API or an upstream carrier is temporarily unavailable. |
Error Codes by Category
Auth
| INVALID_CREDENTIALS | 401 | API key or secret is incorrect. |
| MISSING_AUTH_HEADER | 401 | Authorization header is absent. |
| EXPIRED_TOKEN | 401 | The token has expired — rotate your credentials. |
| INSUFFICIENT_PERMISSIONS | 403 | This key is not allowed to perform the requested action. |
Validation
| VALIDATION_ERROR | 400 | One or more fields failed validation. See errors[]. |
| MISSING_REQUIRED_FIELD | 400 | A required field is absent from the request body. |
| INVALID_PHONE_NUMBER | 400 | The phone number is not a valid E.164 or local number. |
| INVALID_EMAIL_ADDRESS | 400 | The email address is malformed. |
| MESSAGE_TOO_LONG | 400 | SMS message exceeds the maximum character limit. |
OTP
| OTP_EXPIRED | 400 | The OTP session has expired. |
| OTP_INVALID_PIN | 400 | The PIN entered does not match. |
| OTP_MAX_RETRIES_REACHED | 400 | Too many failed verification attempts for this session. |
| OTP_ALREADY_VERIFIED | 409 | This OTP session was already successfully verified. |
Messaging
| MESSAGE_FAILED | 422 | The carrier rejected or could not deliver the message. |
| UNSUPPORTED_COUNTRY | 422 | The destination country is not supported on your plan. |
| SENDER_ID_NOT_APPROVED | 422 | The sender ID / from name is not approved for this route. |
| INSUFFICIENT_BALANCE | 402 | Your wallet balance is too low to send this message. |
Resource
| RESOURCE_NOT_FOUND | 404 | The message ID, call ID, or OTP ID does not exist. |
Rate Limit
| RATE_LIMIT_EXCEEDED | 429 | You have exceeded the rate limit for this endpoint. |
Webhooks
| INVALID_WEBHOOK_PAYLOAD | 400 | Webhook body is not valid JSON or is missing event field. |
Server
| INTERNAL_ERROR | 500 | Unexpected server error. Retry with exponential backoff. |
| SERVICE_UNAVAILABLE | 503 | Temporary outage. Check status.sendexa.co. |