Sending
Message lifecycle and failures
The statuses a message moves through, why it can wait, and what every failure code means and what to do.
Statuses#
An outbound message starts as queued and ends in one of five final states.
queued ──> leased ──> sent ──> delivered ──> read
│ │ │
│ └─────────┴──> failed (see failure.code)
├──────────────────────> expired (not sent before expires_at)
└──────────────────────> cancelled (you cancelled it)
| Status | Meaning | Final |
|---|---|---|
queued |
Accepted. It may be waiting; if so, hold_reason says why. |
No |
leased |
A phone has taken the message and is sending it. | No |
sent |
The phone handed it to the network. | No |
delivered |
The recipient's phone confirmed it, where the network reports that. | Yes (read can follow on channels that report reads) |
read |
The recipient opened it (channels that report reads only). | Yes |
failed |
It could not be sent. failure has a code and a message. |
Yes |
expired |
It was not sent before expires_at. |
Yes |
cancelled |
You cancelled it before it was sent. | Yes |
received |
An inbound message from a contact. | Yes |
A carrier does not always report delivery. A message can stay sent and never become delivered; do not treat sent as a
failure.
Every change is recorded: GET /v1/messages/{id}/events returns the timeline, and the message.* webhook events tell you as
it happens (event catalogue).
Why a queued message waits#
Accepting a message (202) does not mean it goes out now. MyComm holds a message when sending it would hurt the SIM or break a
rule, and releases it when that stops being true. A hold delays a message; it never rejects one. The reason is in hold_reason:
hold_reason |
Why the message waits | What you can do |
|---|---|---|
scheduled |
You set send_after and the time has not come. |
Nothing; or cancel. |
quiet_hours |
A marketing message would arrive outside the sending window of the recipient's local time (default 08:00 to 20:00, when the account has quiet hours on). |
Wait; the message goes out when the window opens. A transactional message is not held for this. |
frequency_cap |
A marketing message would exceed the most promotions one contact may get in 24 hours (3 by default). |
Wait; it is released when an older one leaves the 24-hour window. |
bulk_hours |
The bulk lane sends only inside the channel's bulk hours, in the SIM's local time. |
Wait, or use a higher lane for urgent messages. |
device_offline |
The phone is not connected. | Check the phone's network and the app. The message waits for it. |
device_paused |
The device is paused. | Resume it. |
device_hot |
The phone is cooling down before it sends more. | Wait. |
no_sender_available |
No number of the line can send now (every sender is offline, paused or out of budget). The message moves to the first number that can. | Bring a number of the line back online, or add one to the line. |
sponsor_quota_exhausted |
The messages a partner pays for on this line are used up for the cycle. It goes when the next cycle starts. | Wait for the next cycle, or ask the partner for a larger allowance. |
unpaid |
The number's sponsorship ended and its grace period is over. It stays connected; nothing is sent from it. | Contact MyComm support. |
channel_paused |
The channel is paused. | Resume it. |
campaign_paused |
The campaign the message belongs to is paused. | Resume the campaign. |
media_processing |
An attached file is still being prepared. | Wait a moment. |
link_restricted |
The message has a link that is not allowed to go out yet. | See Keeping your SIM safe. |
recipient_cap |
The SIM already sent as many messages to this recipient today as is safe, or to as many distinct recipients (or foreign recipients) this period. | Wait; spread the sending. |
new_recipient_cap |
The SIM already messaged as many new people today as is safe. | Wait; the next day frees slots. |
content_cap |
The SIM already sent the same text as many times this hour or day as is safe. | Vary the text, or wait. |
carrier_cooldown |
The SIM is pausing between bursts so the carrier does not flag it. | Wait. |
account_limit |
The account reached its daily sending limit. | The message is released the next day. |
platform_hold |
MyComm is holding this traffic while it is reviewed. | Contact support with the message id. |
hold_reason is null when nothing is holding the message. A dry run predicts compliance and scheduling holds only; it cannot
know that a phone will be offline later.
Failures#
A failed message has failure.code and failure.message. Some failures are temporary and MyComm retries them by itself (the
table says how often); when the attempts run out, the message becomes failed. After that you can retry it yourself with
POST /v1/messages/{id}/retry (up to five times), or fix the cause first.
| Code | MyComm retries it | What happened |
|---|---|---|
GENERIC_FAILURE |
Yes, up to 2 attempts | The phone's network rejected the message. |
RADIO_OFF |
Yes, up to 3 attempts | The phone is in airplane mode or its radio is off. |
NULL_PDU |
No | The phone could not encode this message. |
NO_SERVICE |
Yes, up to 3 attempts | The phone had no mobile signal. |
LIMIT_EXCEEDED |
Yes, up to 3 attempts | Android's SMS limit blocked the send. Sending was slowed down. |
FDN_CHECK_FAILURE |
No | The SIM's fixed-dialing list does not allow this number. |
SHORT_CODE_NOT_ALLOWED |
No | Android does not allow apps to text this short code. |
RADIO_NOT_AVAILABLE |
Yes, up to 3 attempts | The phone's modem was not ready. |
NETWORK_REJECT |
Yes, up to 2 attempts | The mobile network refused the message. |
INVALID_ARGUMENTS |
No | The phone rejected the message format. |
NETWORK_ERROR |
Yes, up to 2 attempts | Temporary network error. |
MODEM_ERROR |
Yes, up to 2 attempts | The phone's modem reported an error. |
INVALID_SMSC_ADDRESS |
No | The SIM's message centre number is wrong. Check the SIM settings. |
OPERATION_NOT_ALLOWED |
No | The SIM or carrier does not allow this send. |
BLOCKED_DURING_EMERGENCY |
Yes, up to 3 attempts | Sending was blocked during an emergency call. |
INVALID_RECIPIENT |
No | The phone rejected the recipient number. |
PERMISSION_DENIED |
Yes, up to 3 attempts | The MyComm app lost permission to send SMS. |
SIM_MISSING |
Re-queued, not counted | The SIM is not in the phone. |
CARRIER_BARRED |
No | Your operator refused to send this. The SIM may be blocked for sending SMS. |
UNKNOWN |
Yes, up to 2 attempts | The phone reported an unknown error. |
MMS_UNSPECIFIED |
Yes, up to 2 attempts | MMS failed. |
MMS_INVALID_APN |
No | The phone's MMS settings (APN) are invalid. |
MMS_CONNECT_FAILED |
Yes, up to 3 attempts | Could not reach the carrier's MMS service. |
MMS_HTTP_FAILURE |
Yes, up to 2 attempts | The carrier's MMS service returned an error. |
MMS_IO_ERROR |
Yes, up to 2 attempts | MMS transfer error. |
MMS_RETRY |
Yes, up to 3 attempts | Temporary MMS error. |
MMS_CONFIGURATION_ERROR |
No | This carrier/phone is not configured for MMS. |
MMS_NO_DATA |
Yes, up to 3 attempts | Mobile data is off on the phone. |
MMS_SUBSCRIPTION_INACTIVE |
Yes, up to 3 attempts | The SIM was not active for MMS. |
MMS_TOO_LARGE |
No | The image is too large for this carrier. |
MEDIA_DOWNLOAD_FAILED |
Yes, up to 2 attempts | The phone could not download the image. |
UNCONFIRMED |
No | We could not confirm whether this was sent. It was not retried to avoid a duplicate. |
EXPIRED |
No | Not sent before its expiry time. |
EXPIRED_ON_DEVICE |
No | Expired on the phone before it could be sent. |
CHANNEL_DISCONNECTED |
No | The number was disconnected before this was sent. |
DELIVERY_FAILED |
No | Sent, but the carrier reported it was not delivered. |
OPTED_OUT_BEFORE_SEND |
No | Cancelled: the recipient opted out. |
PROVIDER_UNAVAILABLE |
Yes, up to 3 attempts | The messaging service could not be reached. |
CHANNEL_SESSION_LOST |
Re-queued, not counted | WhatsApp is disconnected on this number. Scan the QR code again. |
CHANNEL_BANNED |
No | WhatsApp has banned this number. |
CHANNEL_AUTH_FAILED |
Re-queued, not counted | The bot token is no longer valid. |
RECIPIENT_NOT_ON_CHANNEL |
No | This number does not use WhatsApp. |
RECIPIENT_BLOCKED_CHANNEL |
No | This person blocked your bot. |
RECIPIENT_NOT_REACHABLE |
No | This person has not started a chat with your bot. |
MEDIA_REJECTED |
No | The service refused this attachment. |
CONVERSATION_WINDOW_CLOSED |
No | The 24-hour reply window closed before this was sent. |
Rules of thumb:
- Fix the cause, then retry:
SIM_MISSINGandCHANNEL_DISCONNECTEDmean the phone or channel needs attention; the message stays queued where it can, or fails with a message that names the cause. - Do not retry the same input:
INVALID_RECIPIENT,SHORT_CODE_NOT_ALLOWED,OPTED_OUT_BEFORE_SENDand the other codes marked "No" will fail the same way again. Fix the number, ask for consent, or choose another channel. - Stop and look when:
CARRIER_BARREDorCHANNEL_BANNEDappear. Sending more can make it worse. UNCONFIRMEDmeans unknown. The phone may have sent the message and lost the report. Retrying can send a duplicate, which is why a retry needsacknowledge_possible_duplicate: true.