# Message delivery status

Delivery status is a ladder — accepted, sent, delivered, read, failed — and each rung is evidence of something narrower than its name suggests. Sent means a provider took it. Delivered means something acknowledged it. Read is optional and often disabled. Connect records the provider's own acknowledgement as the evidence and treats anything short of it as uncertain rather than successful.

- **Status:** Reference
- **Audience:** both, developer
- **Last verified:** 2026-09-10
- **Canonical:** https://connectbyjbrh.com/docs/technology/message-status/

## What each rung is evidence of

| State | What it proves | What it does not prove |
|---|---|---|
| Accepted / queued | Your own system took the request | That anything left your network |
| Sent | The provider accepted it and passed it on | That it reached the recipient's network, let alone the person |
| Delivered | Something on the far side acknowledged receipt — a handset, a server, an operator | That a human saw it, or that it landed anywhere they look |
| Read | The client reported it displayed | Much at all: read receipts are optional on most channels and routinely switched off |
| Failed | A terminal refusal was reported | The reason, unless the provider gave one worth trusting |

The gap between *sent* and *delivered* is where most confident dashboards are wrong. A high sent count with no delivery reporting configured is not evidence of delivery; it is evidence of an API call that returned 200.

## Every channel's ladder is a different length

**Email** — There is no delivered state. An accepting server returns success at the SMTP conversation, and a rejection can arrive minutes or hours later as a bounce. Opens are inferred from a tracking pixel and are unreliable — prefetchers and image proxies fire them, privacy settings suppress them.
**WhatsApp** — The fullest ladder, including read — but delivery reporting is a provider capability, and a number whose provider does not report will simply never advance past sent.
**SMS** — Delivery receipts come from the operator chain and vary in meaning: some mean the handset acknowledged, some mean the message reached the operator. They arrive late, arrive out of order, or never arrive.
**Voice** — Not a ladder at all — a call has provider status, ring and answer times, and an outcome. *Delivered* has no meaning; *answered* does.

Comparing rates across channels is therefore mostly a category error. A 95% delivery figure on one channel and on another are measuring different events reported by different parties under different obligations.

## Status arrives late, out of order, and sometimes not at all

Status callbacks are asynchronous and unordered. A *delivered* can arrive after a *read*. A duplicate can arrive days later. A retry after a network hiccup can deliver the same event twice within a second. Any code that treats the newest callback as the truth will eventually move a record backwards.

The rule that prevents the worst version of this is to keep machine status and human decision in separate fields. On calls here, the provider's status and the engine's outcome are stored apart from the human `disposition` **precisely so that a late webhook cannot overwrite what somebody decided**. The same discipline belongs on any channel where a person can mark a message resolved.

De-duplication is a storage problem: every normalised provider event is stored once, keyed on the identifier the provider supplied, with the database refusing the second insert. See [webhook signatures](/docs/technology/webhook-signature/) for the mechanism and [idempotency](/docs/technology/idempotency/) for the general pattern.

## Does Connect use delivery status?

**Used, as evidence rather than as decoration, and only as far as the provider actually reports.** A send is recorded with the provider's own acknowledgement attached; until that acknowledgement exists the state is *uncertain*, not *sent*. That distinction is deliberate — an optimistic *sent* on a message nobody accepted is the kind of small lie that costs a customer relationship.

Per channel: WhatsApp delivery reporting is provider-dependent and is shown as far as the configured provider supports it, without simulating the rest. Outbound SMS is **foundation** rather than available — it depends entirely on a provider that carries SMS, and the carrier on the live account carries none, so the Phone screen says so instead of presenting a thread that cannot send. Email has send evidence but no delivery state to report, by design of the protocol.

## Reading a status without fooling yourself

1. Ask which party reported the state.
   - Result: Your own code, the provider, the operator and the recipient's device are four different witnesses with four different interests.
2. Ask whether the state is terminal.
   - Result: A non-terminal state is a snapshot of a journey still in progress, and reporting it as an outcome inflates every number built on it.
3. Check whether the absence of a state means anything.
   - Result: On some channels no news is a configuration gap rather than a failure. Silence is not evidence.
4. Keep the human decision in its own field.
   - Result: A person's judgement survives every late callback, and the audit trail can still answer who decided what and when.

## Questions

### Does delivered mean the customer saw the message?

No. It means something on the far side acknowledged receipt — a handset, a server, an operator. Whether it reached a screen the person looks at is a separate question that no status answers, and read receipts, where they exist at all, are frequently switched off.

### Why does an email have no delivered status?

Because the protocol has no such signal. The receiving server accepts responsibility at the SMTP conversation, and a later refusal comes back asynchronously as a bounce. Anything presented as an email delivery rate is an absence of bounces, not a confirmation.

### Can Connect show SMS delivery status?

Only where a provider that carries SMS is configured and reports it. Outbound SMS is foundation here and the live carrier carries none, so that surface says so rather than showing states that cannot exist.

## Related

- [Delivery and read status](https://connectbyjbrh.com/docs/whatsapp/message-status/)
- [Sending SMS: what is available today](https://connectbyjbrh.com/docs/sms/sms-outbound-status/)
- [Proof that a message was sent](https://connectbyjbrh.com/docs/email/send-evidence/)
- [Bounces](https://connectbyjbrh.com/docs/technology/bounce/)
- [Idempotency](https://connectbyjbrh.com/docs/technology/idempotency/)
- [Provider webhook signatures](https://connectbyjbrh.com/docs/technology/webhook-signature/)
- [The call record](https://connectbyjbrh.com/docs/phone/call-record/)

## What this page is based on

- `docs-source/sources/CHANNELS.md` §2 and §3 — provider-dependent reporting
- `docs-source/sources/PHONE.md` §1 — disposition kept apart from outcome
- Connect capability registry (docs-source/facts.py)
