Delivery statuses
Copy page
Every message moves through a lifecycle of statuses, reported by carriers via delivery reports (DLR).
Status table
Section titled “Status table”| Status | Description | Final? |
|---|---|---|
pending | Queued, waiting to send | No |
sent | Submitted to carrier network | No |
DELIVRD | Delivered to recipient’s handset | Yes |
UNDELIV | Delivery failed (invalid number, phone off) | Yes |
REJECTD | Rejected by carrier (filtered, blacklisted) | Yes |
EXPIRED | Delivery timed out | Yes |
UNKNOWN | Final status unknown | Yes |
failed | Internal error (queue/config failure) | Yes |
Typical flows
Section titled “Typical flows”pending → sent → DELIVRD successpending → sent → UNDELIV bad number / phone offpending → sent → REJECTD carrier blockedpending → sent → EXPIRED recipient unreachablepending → failed internal errorWhere statuses appear
Section titled “Where statuses appear”| Place | Field |
|---|---|
| Message status | message.status |
| Message lists | messages[].status (+ filter aliases like delivered) |
| Delivery webhook | status |
| Statistics | Aggregated into delivered / undelivered / pending / expired |
Reconciliation
Section titled “Reconciliation”Messages stuck in sent/ENROUTE without a final DLR for 3+ days are
automatically moved to UNDELIV by an hourly reconciliation job — so
long-running integrations never see permanently “pending” messages.
Interpreting statuses
Section titled “Interpreting statuses”DELIVRDis the only confirmed handset delivery.sentmeans the carrier accepted the message, not that the phone received it.UNDELIVvsREJECTD:UNDELIVis usually a recipient problem (dead number, phone off for days);REJECTDis a carrier policy decision (content filtering, blacklist) — review your content/sender if it spikes.EXPIREDoften means the handset was off or out of coverage for the entire validity period.- Clean your lists: repeatedly
UNDELIVnumbers should be suppressed — they cost money and hurt your sending reputation.