SMS v2 error catalogue
Use the catalogue
Section titled “Use the catalogue”This catalogue describes SMS v2 application codes and HTTP request errors handled by its public views. The shared JSON format explains error.code, error.message, optional details and the optional top-level message_id identifier. Fields, codes and messages remain in English.
In the tables, retry identically means keeping the same path, body and Idempotency-Key for message or batch creation. A new key creates a new operation and can cause a second SMS. A stored response replays its initial outcome, even if the message status has changed since, except after the targeted erasure described below.
Request and validation
Section titled “Request and validation”Scroll horizontally if needed. Keyboard: Tab, then the left and right arrow keys.
| HTTP | Code | Cause | Action or retry |
|---|---|---|---|
400 | validation_error | Missing, unknown or invalid field; invalid number, text, sender, timestamp or recipients. | Read error.details and correct the fields. Check the limits below; do not repeat the same invalid body. |
400 | parse_error | The body cannot be read as valid JSON. | Correct JSON serialization before submitting the request. |
400 | invalid_organization_header | The X-Organization header was supplied. | Remove this header and use a key from the intended organization. |
400 | invalid_idempotency_key | Idempotency-Key is missing or does not contain 1 to 128 visible ASCII characters. | Supply a valid, stable value for the business operation. |
400 | invalid_schedule | send_at is no longer in the future at initial admission. | Choose a future timestamp. Do not change the timestamp of an accepted schedule to replay it. |
400 | invalid_sender_name | Sender name checks reject its value. | Use a valid name of 1 to 11 ASCII letters, digits or internal spaces. Body format errors may also be reported as validation_error. |
400 | invalid_cursor | The pagination cursor is invalid or belongs to another batch. | Pass next_cursor unchanged from the previous page of the same batch, or restart from its first page. |
404 | not_found | Unknown route or resource absent from the key’s organization. | Check the path, identifier and organization. A resource in another organization remains inaccessible. |
405 | method_not_allowed | The HTTP method does not match the route. | Use the method specified in the reference. |
406 | not_acceptable | The Accept header requests an unsupported response type. | Request application/json. |
415 | unsupported_media_type | The body type is unsupported. | Send JSON with Content-Type: application/json. |
Authentication and authorization
Section titled “Authentication and authorization”Scroll horizontally if needed. Keyboard: Tab, then the left and right arrow keys.
| HTTP | Code | Cause | Action or retry |
|---|---|---|---|
401 | invalid_api_key | Incorrect header, legacy key, invalid secret, inactive or revoked key, or invalid key context. | Check Bearer authentication and the organization key. Do not keep retrying a revoked key. |
403 | insufficient_permissions | The key lacks the required capability. | Use a key with the operation’s capability. Checking a message requires delivery.read. |
403 | sms_unavailable | The organization or SMS is inactive or unavailable; the activation required for sending may be missing. | Check the state in Cloud and contact support if necessary. Wait for resolution before retrying. |
403 | sender_name_unavailable | The requested sender is inactive or unauthorized for this organization; it may also have been blocked before the provider call. | Check the name in Cloud. With message_id, read the message: the failure may be stored and a replay will not send it again. See stored failures below. |
The three HTTP 409 conflicts
Section titled “The three HTTP 409 conflicts”Scroll horizontally if needed. Keyboard: Tab, then the left and right arrow keys.
| HTTP | Code | Cause | Action or retry |
|---|---|---|---|
409 | idempotency_conflict | The same idempotency key was already used on this resource with different content. | Retrieve the original request and correct business tracking. Do not automatically change the key to bypass the conflict. |
409 | idempotency_in_progress | The identical request is still being processed. | Wait, then retry identically with spaced, bounded attempts. Read the status if the identifier is already known. |
409 | insufficient_credits | Available credits are insufficient or their validity has expired. | Check available and valid_until, then restore valid credits before retrying. Batch admission is atomic: this error does not leave a partially accepted batch. |
These three codes do not belong in the same retry loop. None justifies automatically creating another idempotency key.
Erased personal data
Section titled “Erased personal data”Scroll horizontally if needed. Keyboard: Tab, then the left and right arrow keys.
| HTTP | Code | Cause | Action or retry |
|---|---|---|---|
410 | personal_data_erased | Replay of POST /api/sms/v2/messages/ with the same key and content after targeted erasure has been reviewed and executed for a completed message. | Stop retrying that operation and retain its key. Do not resubmit the message with a new key. |
{ "error": { "code": "personal_data_erased", "message": "Personal data for this completed message has been erased. Do not resubmit it with a new idempotency key." }}This response replaces the stored creation response without a new send or credit movement. It does not indicate a temporary outage. A different body with the same key remains a 409 idempotency_conflict; changing the content does not bypass the protection. See idempotency after erasure.
Service and provider outcome
Section titled “Service and provider outcome”Scroll horizontally if needed. Keyboard: Tab, then the left and right arrow keys.
| HTTP | Code | Cause | Action or retry |
|---|---|---|---|
500 | internal_error | An internal error prevents completion of the request. Sending may already have started. | Retry identically with a limited number of spaced attempts; read the status if possible. Contact support if the error persists. |
503 | service_unavailable | The service is temporarily unavailable, including during maintenance. | Wait and respect Retry-After when supplied. For a creation with no known identifier, retry with the same path, body and Idempotency-Key. If the message identifier is already known, read its status when the service is available again. |
503 | dispatch_unavailable | Submission could not complete. With message_id, this response represents a stored failure before the provider call. | Without message_id, retry identically. With message_id, read the status; replaying the same key returns the same failure without another send. |
502 | provider_rejected | The provider explicitly rejected the submission. | Retain message_id and diagnose the rejection. The response is stored; do not automatically start a new operation. |
502 | provider_result_unknown | Provider acceptance cannot be determined, including after an interrupted communication. | Read message_id. Never automatically resend with a new key; the provider may already have accepted the SMS. |
This catalogue does not announce a fixed request rate. If an intermediary returns 429, slow down and respect Retry-After when present; this does not establish a published SMS v2 quota.
A service_unavailable response does not call for a new idempotency key. Retain the original intent, space out and limit attempts, and contact support if the outage persists. This response does not announce a restoration time.
Unknown outcomes and stored failures
Section titled “Unknown outcomes and stored failures”Example response after an uncertain provider outcome:
{ "error": { "code": "provider_result_unknown", "message": "The provider outcome is uncertain. Check the message status; do not submit it with a new idempotency key." }, "message_id": "11111111-1111-4111-8111-111111111111"}Use GET /api/sms/v2/messages/{message_id}/ with a key that has delivery.read. An unknown outcome proves neither rejection nor absence of delivery. Credits may remain reserved during verification. Replaying creation retains the initial response; reading the message provides its current state.
provider_rejected, dispatch_unavailable with message_id and sender_name_unavailable with message_id can represent definitive failures of that submission. Fixing the sender or service does not turn their replay into another send. After verifying a definite failure and resolving its cause, a deliberate new business attempt requires a new key. Never make this decision automatically for provider_result_unknown, unknown or a merely lost network response.
For an accepted schedule, follow message statuses. A batch may have different individual outcomes after admission, and replaying its creation does not reschedule failed recipients.
Functional limits
Section titled “Functional limits”Recipients must be Malagasy mobile numbers in E.164 format, for example +261321234567, without spaces. Text is limited to two SMS segments; the possible character count depends on encoding. A schedule uses a future RFC 3339 timestamp with an explicit timezone.
A batch is scheduled only: its recipients are distinct and share the text, sender and timestamp. Its limit is 1,000 recipients, matching the recipients schema in the reference. Read pages contain at most 100 messages. See the batch guide and credits.