Inbound event catalog
Inbound message statuses (delivered, failed, read, received, opt-out) come from every carrier Orbit integrates — Telnyx, the Devotel softswitch, DIDWW, and Meta — and each carrier reports its own status strings. Orbit folds all of them onto the same canonical webhook events. The Inbound event catalog is the dashboard view of that folding: one row per canonical event, listing every raw upstream status that arrives as it. Use it before you write a receiver branch — the catalog answers “which canonical event do I subscribe to, and which raw provider statuses will arrive as it?”Open the catalog
In the dashboard, go to Developer → Webhooks → Inbound event catalog (/developer/webhooks/inbound-catalog). The page is available to members with the owner, admin, or developer role.
The catalog is static platform metadata with no tenant data, so every member with one of those roles sees the same table.
The catalog endpoint
The same table is served machine-readably:GET /api/v1/webhooks/inbound-eventskind, and the full list of upstream carrier statuses (grouped by carrier) that normalize to it. See Normalized inbound event envelope for the response shape.
Read an entry
The page has two panes: a searchable list of canonical events on the left, and the selected event’s detail on the right. Each entry shows:
The list’s search matches canonical event names, statuses, kinds, and provider vocabularies, so typing
delivrd finds the same entry as typing delivered.
A folding entry you can read end-to-end
Take the SMPP failure codeUNDLV and follow it from the carrier’s receipt to the webhook your endpoint receives.
The carrier reports a delivery receipt with the raw status UNDLV (the SMPP delivery-failure code the Devotel softswitch reports). Orbit folds it into the canonical failure pair:
The signed envelope your receiver gets then reads:
data.provider_status echoes the status exactly as it arrived ("UNDLV" here), while data.status stays a closed canonical set (delivered, failed, sent, read, opted_out) you can switch on. Branch on the canonical pair; log the raw string.
The same two-step fold works for every carrier — Telnyx message.delivered lands as message.delivered with data.status of delivered and data.provider_status of message.delivered; a Meta read status lands as message.read; a DIDWW undelivered lands as message.failed.
Which carriers report which vocabulary
The catalog covers four upstream providers. Their status families:
Every left-column term arrives at your endpoint as an equivalent (provider, raw status) pair on the catalog entry for the canonical event it folds into. Matching is case-insensitive: a
UNDLV receipt and an undlv catalog row are the same entry.
When to use normalized.inbound vs subscribing per event
Two subscription styles cover the inbound family:
- One share subscription — set the endpoint’s event list to
["normalized.inbound"]and it receives the whole family (message.received,message.delivered,message.failed,message.read,contact.opted_out) without enumerating events. Choose this when your handler keys offdata.normalized.kind(delivery/failure/opt_out/received) and you never want to miss a status family. - Per-event subscriptions — list the specific events (
["message.delivered", "message.failed"]). Choose this when separate teams or pipelines own separate outcomes — for example a deliverability dashboard subscribed tomessage.failedonly — or when a success pipeline should not have to filter out opt-outs.
data.normalized block anatomy.
Receiver validation with the SDK
The same mapping the platform normalizes with ships in the SDK asnormalizeInboundEvent, so your receiver validates against the identical table instead of hand-rolled per-carrier parsing. Pass a raw carrier status (the provider name is optional) and it returns the canonical pair:
undefined for a raw status the catalog does not cover — treat undefined as “log it and keep data.status”, never as a silent drop. Omit provider and every provider’s vocabulary is searched, so a carrier-agnostic receiver validates with one import.
Reading provider_status in a handler
On the delivery envelope, two fields carry status: the canonical data.status and the carrier-verbatim data.provider_status. Switch on the first; keep the second for per-carrier detail:
Put it to work
Use the catalog when your handler sees a raw status that does not match any branch:- Search the raw status (for example
UNDLV) in the catalog. - Read off the canonical event it resolves to (for example
message.failed) and the canonicaldata.status(for examplefailed). - Check that your handler’s switch covers that canonical event — SMPP
UNDLV-style codes, Telnyx failure strings, and DIDWW statuses can all fold into the same event.
normalizeInboundEvent: pass it a raw carrier status (with or without the carrier name) and it returns the canonical event and status pair, so receiver-side validation never drifts from the platform’s mapping.
One subscription can skip the enumeration entirely: set an endpoint’s events to normalized.inbound and it receives the whole inbound family (message.received, message.delivered, message.failed, message.read, and contact.opted_out). See Normalized inbound event envelope.
Common misreads to avoid
The same misunderstanding recurs in receivers: a carrier reports one thing, Orbit normalizes to another. These are the folds that catch people:- “The carrier said delivered, but Orbit reports failed.” Normalization collapses carrier nuance into a closed set. An SMPP
UNDLVreceipt and a DIDWWundeliveredboth land asmessage.failedwithdata.statusoffailed— the original string survives indata.provider_status, so a handler that greps the raw string and ignores the canonical field misbranches. Conversely, Telnyxqueuedandsendingfold tomessage.sent(kinddelivery), notdelivered: onlymessage.delivered,delivered, ordelivery_successmean delivered. - Treating
readas a delivery outcome. Metareadis its own canonical event (message.read); subscribe to it explicitly or it looks like a missingmessage.deliveredbranch. - Expecting one canonical event per provider. The event list on an endpoint says which canonical events to receive; the provider that produced them is data on the envelope (
data.normalized.provider), not part of the event name. SMPPUNDLV, Telnyxrejected, and DIDWWundeliveredall arrive asmessage.failed. - Assuming unknown statuses are dropped. A raw status the catalog does not cover returns
undefinedfromnormalizeInboundEvent; the platform logs it and keeps the carrier-verbatimdata.provider_statuson the delivery — it is never silently swallowed.
When you want the schema instead
The Inbound event catalog answers “which raw status arrives under which event” — a status-folding view. For the full schema of what an endpoint can subscribe to (every event type, with sample payloads and failure payload shapes), use the schema-level Event catalog at Developer → Webhooks → Event catalog (/developer/webhooks/event-catalog).
See also
- Webhook Events catalog — every event type you can subscribe to
- Webhook Event Payloads — the full envelope and header anatomy
- Normalized inbound event envelope — the
data.normalizedblock and thenormalized.inboundshare subscription - Webhook Security — signature verification