Errors
Every error uses the same JSON shape, with an HTTP status code to match:
{
"error": {
"code": "invalid_phone_number",
"message": "Invalid phone number(s): 12345. Use E.164 format, e.g. +254712345678.",
"status": 400
}
}
codeis stable — use it in your code.messageis for humans and may change wording.
Error codes
| Status | Code | Meaning | What to do |
|---|---|---|---|
| 400 | invalid_request | Body is not JSON, a field is missing or has the wrong type, or a value is out of range | Fix the request; the message names the field |
| 400 | invalid_phone_number | One or more numbers are not valid | Send E.164 (+2547…) or a valid Kenyan format; the message lists up to 10 bad numbers |
| 401 | invalid_api_key | Key missing, unknown, expired, revoked, or the organisation is disabled | Check the Authorization: Bearer … header and the key's status in Developer API |
| 402 | insufficient_units | Not enough SMS units for the whole request | Buy units in the app; nothing was sent |
| 403 | scope_denied | The key lacks the permission for this endpoint | Use a key with the right scope |
| 403 | invalid_sender_id | The sender_id is not approved for your organisation, or you have none | Use an approved sender ID, or apply for one in the app |
| 403 | sms_not_configured | SMS is not set up for your organisation yet (live keys) | Buy SMS units in the app first |
| 403 | module_unavailable | SMS is not enabled for your account | Contact your CloudMetis administrator |
| 403 | forbidden | Access denied | Contact support if unexpected |
| 404 | not_found | Unknown URL, or the message/batch doesn't exist in your organisation | Check the ID and URL |
| 405 | method_not_allowed | Wrong HTTP method (e.g. GET on /send) | Use the documented method |
| 409 | idempotency_conflict | Idempotency-Key reused with a different body, or the first request is still processing | See Idempotency |
| 422 | all_recipients_opted_out | Every number has opted out of your messages | Nothing to send |
| 429 | rate_limit_exceeded | Too many requests for this key | Wait for Retry-After seconds; see Rate limits |
| 500 | server_error | Something went wrong on our side | Retry with backoff; contact support if it persists |
| 502 | send_failed | The SMS network or gateway rejected the request | Retry later; the message explains the cause |
Retrying safely
- Don't retry
400,401,402,403,404,405or422without changing something — the same request will fail again. - Retry with backoff on
429,500,502and network timeouts. - Send an
Idempotency-Keywith everyPOST /v1/sms/send, so a retry can never send the same SMS twice.