> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Delivery Logs console: trace one message end to end

> Open a failing message in the dashboard's Developer → Delivery Logs surface, read its lifecycle step by step, and carry the carrier rejection reason straight into a support ticket.

# Trace a message through Delivery Logs

The Developer → **Delivery Logs** page in the dashboard is the console-first way to answer "what happened to this message?" — without writing an API call or waiting on a support response. It searches every outbound and inbound message across channels, then opens one message's lifecycle so you can read it step by step.

Use it alongside the [Request Logs](/guides/developer-portal) (HTTP ingress) — delivery logs cover the downstream message lifecycle; request logs cover the HTTP shape of your API traffic.

The page and its drill-down require an `owner`, `admin`, or `developer` role on your dashboard session — the recipient numbers and message body fragments in the rows are the same PII tier as API keys and webhooks.

## What the page shows

Every row is one message — inbound or outbound, on any channel — with its channel, direction, recipient, sender, current status, and timestamp. A message moves through the lifecycle as:

1. **Accepted** — Orbit received your send request and queued the message.
2. **Routed** — a route and carrier were selected for the recipient.
3. **Submitted** — the message was handed to the carrier or provider.
4. **Terminal** — `delivered`, `read`, `failed`, `rejected`, or `submitted` with no receipt after the window closes.

The status filter narrows the list to one terminal state (`queued`, `sent`, `delivered`, `read`, `failed`, or `rejected`), and the channel and direction filters narrow it further. The free-text box matches recipients, senders, and body fragments — or paste a full `msg_…` id to jump straight to that one delivery.

## When to use it

* **"A message didn't arrive."** Filter to the recipient, read the terminal status, then drill into the steps to see where the lifecycle stopped.
* **"The DLR says submitted, no receipt."** The terminal step names the carrier-rejection reason when the carrier returned one — start there before touching your code.
* **"Did the WhatsApp send after the SMS failed?"** One cross-channel list instead of four channel tabs — filter by the recipient and compare rows.

For the same lookups over the API (a support script, an on-call runbook), the page's queries map one-to-one onto `GET /api/v1/messages` — see the [Delivery log API guide](/guides/delivery-log).

## Open a failing message

1. Open **Developer → Delivery Logs** in the dashboard.
2. Paste the message id into the search box. Paste it however you have it — the `msg_…` id the send API returned, or the id shown on a message page. A fully-typed id resolves to a direct lookup: one row, regardless of the date filter.
3. Or, with no id in hand, narrow the list — pick a channel and a status (say, `failed`), set the date range, and click the row for the failing message.

Rows rendered from a direct id lookup carry a *Message id match* strip above the results. Widen or clear the filters afterward to pivot to related deliveries — the id lookup freezes the list while it's active so the row you're on is exactly the id you pasted.

## Drill into the steps

Click a row. The detail drawer opens the same per-message surface every channel workspace uses — a status timeline of the lifecycle steps in order, each with its timestamp, and the carrier or provider rejection reason whenever the terminal step carries one:

* A **submitted-no-receipt SMS** shows the lifecycle up to the carrier-submission step, with the carrier-side reason (an unreachable handset, a routing refusal) on the failed step when the carrier returned one.
* A **rejected WhatsApp template send** ends at the rejection step, with Meta's template-rejection reason inline — fix the template, then retry.

The drawer also shows the error code and error message fields that travel with the row, and a copy button on the message id — drop the id into a support ticket and whoever picks it up can retrace the same lifecycle.

## Share a pre-filtered view

The page reads its initial filters from the URL, so a bookmarks bar, a runbook, or a chat message can carry a ready-made view:

```text theme={null}
# Jump straight to one message id
/developer/delivery-logs?q=msg_9f8e7d6c5b4a3921

# Failed outbound SMS from the last 30 days
/developer/delivery-logs?channel=sms&status=failed&direction=outbound

# Everything to one recipient across channels
/developer/delivery-logs?q=%2B14155552671
```

Supported parameters: `q` (free text or a `msg_…` id), `channel`, `status` (`queued`, `sent`, `delivered`, `read`, `failed`, `rejected`), and `direction` (`outbound`, `inbound`). Values outside those sets are ignored rather than applied, so a hand-built URL cannot seed the page into a state its own filters cannot represent. The same maps one-to-one onto the `GET /api/v1/messages` filter vocabulary — a link built against the API works in the page and vice versa.

## Request Logs vs Delivery Logs

The two developer debugging surfaces answer different questions:

| Surface                                     | Answers                                                                                |
| ------------------------------------------- | -------------------------------------------------------------------------------------- |
| **Delivery Logs**                           | "Did the message move downstream — routing, submission, carrier acceptance, delivery?" |
| **Request Logs** (Developer → Request Logs) | "Did my HTTP request arrive in a valid shape — status code, latency, error class?"     |

A `202 Accepted` in Request Logs with no delivery in Delivery Logs means the API took the send but the lifecycle stopped downstream — routing, carrier submission, or the carrier itself. A `4xx` in Request Logs means the request never became a message at all, and Delivery Logs has nothing to show for it.

## When a log looks incomplete

Two cases to recognize:

* **The lifecycle is still running.** A message within its delivery window can sit in a non-terminal status (`queued`, `sent`) until the carrier responds or the window closes. The page's timestamp filters snapshot the moment — a refresh is the update.
* **You built against an hourly-aggregated surface.** The analytics-style usage surfaces roll up by the hour and buffer the most recent window. The per-message reads on this page and on `GET /api/v1/messages` are immediate — when the aggregate looks stale, read the individual delivery rather than waiting for the aggregation to catch up.

## Examples

**SMS shows `submitted` but never `delivered`.** Open Developer → Delivery Logs, paste the `msg_…` id into the search, click the row, and read the steps in the drawer. The submitted-no-receipt lifecycle ends at the carrier-submission step; if the carrier reported a reason, the failed step carries it. Take that reason into [troubleshooting "submitted, no receipt"](/troubleshooting/submitted-no-receipt) — the page branches by carrier-side cause.

**WhatsApp template send rejected at send time.** Filter to channel `whatsapp` + status `rejected`, click the row, and read the Meta rejection reason off the terminal step. Fix the template or the variable shape, then resend from your normal send path — the row's lifecycle tells you why, not retrying it tells you when.

## Frequently asked questions

### Why does my pasted id show one row even though the date filter should exclude it?

A fully-typed `msg_…` id resolves as a direct by-id lookup, which intentionally ignores the date range and channel filters — the promise of the paste target is "jump straight to that delivery," and a default 30-day window would break it for older messages. Clear the search to return to the filtered list.

### The status filter shows `rejected` but my row says `failed` — which is it?

Both are terminal, but they differ in intent. `rejected` means the carrier or provider refused the message outright (a template rejection, a routing refusal); `failed` means the message was accepted for transport and the delivery then failed. The drill-in drawer's terminal step carries the reason either way.

### Can viewers or billing roles open this page?

No. The rows contain recipient numbers, message body fragments, and per-channel error detail — the same PII tier as API keys and webhooks, so the page is gated to `owner`, `admin`, and `developer` roles.

## See also

* [Developer Portal guide](/guides/developer-portal) — try-it console, usage stats, key governance, webhook debugging, event sinks
* [Delivery log API guide](/guides/delivery-log) — the same lookups over `GET /api/v1/messages`, plus shareable filtered URLs
* [Troubleshooting: message undelivered or failed](/troubleshooting/message-undelivered-failed) — turn a failing lifecycle into a fix
* [Troubleshooting: submitted, no receipt](/troubleshooting/submitted-no-receipt) — the carrier-side branches of a stuck SMS
