The word doing the damage is "accepted". It reads like a delivery confirmation and it is a receipt from Bird: we have taken the send and started preparing it. Nothing has reached a person, a handset or a mail server at that point.

So a message sitting at accepted is not stuck between two places. It is at the beginning.

## What actually happens between accepted and delivered?

There is at least one step in between, and it is the one worth instrumenting.

On **email**, `email.accepted` fires once per requested recipient and is the first event in every stream. Then `email.processed` means the message is built and queued for delivery to the recipient's mail server. Only `email.delivered` means the receiving server took responsibility for it.

On **SMS**, the same shape with different words: `sms.accepted`, then `sms.sent` when the message has been handed to the carrier, then `sms.delivered` when the carrier's receipt says it arrived.

The useful consequence is that these two boundaries let you separate whose time is whose. **Comparing `processed` against `accepted` gives you our own processing time**; comparing delivery against the handover gives you the carrier's or the mailbox provider's. If a message is slow, that pair of subtractions tells you which half to chase, and one of them is ours to answer for.

## Why is it still not delivered?

Because "not delivered yet" and "will never be delivered" look identical from a single event, and there are four different endings.

On email the send either lands, gets **deferred** and retried, which resolves later to delivered or bounced, is **bounced** by the receiving server, or is **rejected** with no delivery attempt made at all. That last one is the case people misread most: a rejection is not a failed attempt, it is the absence of one, and its reason lives on our side rather than the recipient's.

On SMS the endings are **undelivered** for a non-permanent failure, **failed** for a permanent one, **rejected** when the message was refused rather than attempted, and **expired** when the carrier stopped trying. Which error code rides along is what identifies the cause, and [why carriers filter SMS](/explained/sms/why-are-my-sms-messages-being-filtered-by-carriers) covers reading those.

## Is there one lifecycle I can learn?

No, and that is the honest answer rather than a gap in the documentation.

Each channel has its own vocabulary because each has its own delivery reality. Email has deferrals because mail servers ask you to come back later; SMS has expiry because a carrier gives up on its own schedule; WhatsApp and voice have their own terminal states again. A single flattened model would be wrong for all four.

What does transfer is the shape: an acceptance from us, a handover, a delivery confirmation from whatever is downstream, and a set of endings where the code rather than the event names the cause. Learn that, then read the guide for the channel you are actually debugging: [email events](/docs/guides/email/events), [SMS events](/docs/guides/sms/events), [WhatsApp events](/docs/guides/whatsapp/events) and [voice events](/docs/guides/voice/events).

## Can a delivered message stop being delivered?

Yes, and it is worth knowing before you treat delivered as terminal in your own data.

A receiving mail server can accept a message at SMTP time and send a bounce report afterwards, which arrives as an out-of-band bounce. When that report classifies as a bounce, **the server has retracted its earlier acceptance and the recipient moves from delivered to bounced.** A hard one also suppresses the address.

Reports that do not classify as a bounce, an auto-reply for instance, are recorded on the timeline and leave the status alone.

The practical rule is the one that follows from events being unordered anyway: store the status as something that can move, keyed on the latest event by its own timestamp, rather than as a value you write once when the happy path finishes.