Skip to main content

Reading machine-sent transactional traffic

Machine triggers — a storefront webhook, an order-management system, an OTP sender, a flow’s timer — account for a large share of a tenant’s outbound volume. This walkthrough pulls the whole arc into one page: which sends count as machine-triggered transactional traffic, the two rules that decide whether one mints an Inbox conversation, the ledger you read it back from, the metrics the ledger computes, and how to export or stream what you filtered. The Order notifications ledger describes one emitter (commerce stages); the no-inbox gate describes one rule (the conversation-suppression mechanics). This page is the bridge: how machine-triggered traffic enters, and how you should read it in the ledger.

1. When the ledger view matters

A machine-triggered transactional send is one fired by an event, not by a campaign composer: your commerce system posts an order stage, your OTP endpoint fires a code, your flow’s schedule emits a reminder. The recipient’s purchase or signup establishes the consent, so the send classifies as transactional — and because each message references that event rather than a human conversation, it should not pollute Inbox threads. When that classification holds, the send still lands on a reading surface: the Insights → Order notifications ledger (or, if you have not adopted the ledger yet, the per-channel Messages list with the same rows). The ledger exists precisely so that machine traffic gets a first-class operational view — delivery health, attempt lag, failure breakdown — while conversational traffic stays in the Inbox and campaign traffic stays in campaign reports. The three classes (machine transactional, conversational, campaign promotional) read on three different surfaces on purpose. Use the ledger when the question is “is my event-driven traffic healthy and fast?” — not “how did a promotion perform” and not “what do agents owe answers on.”

2. The classes of entry: the two arrival rules

Every candidate send gets a classification at dispatch time from two independent rules — one explicit, one inferred:
  1. Explicit inbox: "none" on the termination hop. A deliver hop can stamp inbox: 'none' (or a send’s metadata can carry the same stamp) — the route itself declares “this is machine traffic.” When that stamp resolves, the send skips the Inbox conversation regardless of template category. See the rule-JSON walkthrough in Keep one-time codes out of the Inbox.
  2. Inferred AUTHENTICATION category. When the resolved WhatsApp template’s category is AUTHENTICATION (Meta’s OTP category), the platform treats the send as transactional even with no rule saying so — a one-time code is, by definition, not a conversation.
An explicit inbox: 'thread' beats the inference: an AUTHENTICATION template delivered with a thread stamp still opens a conversation. The precedence order in full, with the counter-examples that matter when signals disagree, is the trigger table in the no-inbox gate guide. The ledger reads the same classification: a send either counted as machine-triggered transactional (and appears) or it did not (and does not). Commerce flows arrived tagged as machine traffic at their stage event — commerce emitter or direct fulfillment POST — which is why order-stage rows fill the ledger while campaign rows are absent by design.

3. The reading surface: Insights → Order notifications

Open Insights → Order notifications ledger in the dashboard. The page scopes itself to a window — the standard Insights date filter (24h, 7d, 30d, 90d, 12m, or a custom calendar range) — and everything on the page computes against that window. Below the header metrics, the page aggregates per stage: order.confirmation, order.shipped, order.out-for-delivery, order.delivered, and the exception bucket order.exception (delayed, failed delivery attempt, refunded, cancelled). A stage that silently stops firing shows up as a missing series, so the per-stage grouping is the first place a broken webhook integration becomes visible.

4. The four metrics

The ledger header computes four metrics over the window you picked; each answers a distinct operational question:
  • Delivery rate — delivered (plus read, where the channel returns it) over terminal sends, in-flight rows excluded. The “is it arriving” number.
  • Time-to-first-attempt — send-to-first-delivery-signal lag, per stage and channel. Separates a sender-config delay from a carrier-side delay.
  • Channel mix — which channel (SMS, WhatsApp, email) actually carried each stage’s sends, against the intended first-choice channel from your flow.
  • Failure breakdown — rejected, undelivered, and failed rows grouped by rejection code, splitting recipient-side hygiene (undelivered) from dispatch/configuration faults (rejected).
Deeper definitions and the exception-stage interpretation are on the Order notifications ledger page itself.

5. CSV export and the filter surface

The page carries one channel filter that narrows the whole view to SMS, WhatsApp, or email; filters persist in the URL, so a teammate opening your link sees the same range and channel. Export flattens every visible section into a CSV from the Export button — same pattern as the Analytics console. For scheduled BI pulls, the /api/v1/analytics/messages family streams the same rows with the same channel and status filters; a full curl sample and response envelope are in the ledger guide’s streaming section.

6. The no-inbox gate mechanics

The gate behind classification is deliberately narrow, and the three guarantees are worth stating together because “conversation suppressed” is easy to misread as “message lost”:
  • Conversation upsert is suppressed. No Inbox conversation object is created or appended for the stamped send, and no inbox_new_conversation notification fires. Agents see nothing until the recipient replies.
  • The Messages row is complete. The per-channel Messages list records the send with its full status trail and cost attribution. Analytics, compliance receipts, and the DLR trail are untouched — suppression removes the conversation object, not the message record.
  • An inbound reply still threads. The gate sits on the outbound upsert only; a reply from the recipient opens a real conversation on the normal inbound path, when there is something to answer.
The full mechanics — the trigger table, rule JSON, metadata stamping via POST /api/v1/messages, and the “I still see one conversation per OTP” runbook — live in Keep one-time codes out of the Inbox.

See also