Statuses and failures
A message moves forward through its statuses until it reaches a final one.
text
queued → submitted → sent → delivered → read
│ │
│ └──────→ failed / expired
└──→ rejected| Status | Final | Webhook | Meaning |
|---|---|---|---|
accepted | — | Accepted by the API. Only seen in the history: the answer of POST /messages is already queued. | |
queued | — | Waiting in the ACE SEND queue to go to the provider. | |
submitted | — | Handed to the provider. | |
sent | message.sent | The provider sent it to the network. | |
delivered | message.delivered | Delivered to the phone. A WhatsApp message can still become read. | |
read | yes | message.read | Opened by the recipient. WhatsApp only: SMS never report reads. |
rejected | yes | message.failed | Refused by the provider or the network before it was sent; error says why. |
failed | yes | message.failed | Sent but not delivered; error says why. |
expired | yes | message.failed | Not delivered in time (the phone stayed offline). |
cancelled | yes | message.failed | Campaign messages only: the campaign was stopped before the message went to the provider. |
What to rely on
- Final statuses never change:
read,rejected,failed,expired,cancelled. deliveredis not final for WhatsApp: it becomesreadwhen the recipient opens the message (if they share read receipts — many do not). For SMSdeliveredis the last status.- Steps can be skipped. Some networks report
deliveredwithoutsent; then nomessage.sentcomes. Treat any later status as including the earlier ones. - Statuses never go back. A late
failedafterdeliveredis kept in the history but does not change the status. - Webhooks can arrive out of order. Compare the order of statuses above, not the order of arrival: a
message.sentthat comes aftermessage.deliveredchanges nothing.
The history of a message — every status with its time and error — is in events of GET /v1/messages/{id}.
Failure codes
When a message does not reach the recipient, error tells why: a stable code and a text for people in the language of Accept-Language (in English in webhooks).
json
"error": { "code": "no_whatsapp", "text": "The number does not use WhatsApp" }error.code | error.text (English) | Meaning |
|---|---|---|
no_whatsapp | The number does not use WhatsApp | The number has no WhatsApp account. Send an SMS instead. |
invalid_number | The number is invalid | The network does not know the number. |
blocked | The recipient blocked the messages | The recipient or the operator blocked the messages. |
template_paused | The template is paused by WhatsApp | WhatsApp paused the template, usually after negative feedback. Use another template. |
template_rejected | The template is rejected by WhatsApp | WhatsApp no longer allows the template. |
rate_limited | Too many messages to the recipient | The recipient got too many messages recently. Try later. |
expired | The message was not delivered in time | The phone stayed unreachable. |
provider_error | Delivery error | The provider failed to deliver the message. |
not_sent | The message did not go out | The message did not leave ACE SEND. |
sender_rejected | The operator or the provider did not accept the sender name | SMS: the sender name is not registered or not allowed for the operator. |
other | Not delivered | Another reason; text carries the words of the provider. |
New codes may appear: treat an unknown one as other.
Message text
text is the text as sent. After 90 days it is erased: text becomes null and text_masked is true. The number, template, statuses and price stay.