Skip to main content

DLR and MO gateway pipeline

Two kinds of carrier traffic enter Orbit at the SMPP edge:
  • Delivery receipts (DLRs) — the carrier’s acknowledgement of where an outbound message ended up. DLRs drive the status machine behind every message you send.
  • Mobile-originated (MO) SMS — inbound messages a handset sends to one of your numbers.
Both arrive over the same class of gateway connection, and once inside they fan out into different pipelines. This page explains the gateway-level model — how raw carrier traffic crosses into Orbit, and the reconciliation loop that keeps the gateway consistent with your SMPP configuration. Delivery lifecycle covers the status states a DLR can drive; Inbound message resolution covers the tenant-ownership lookup that runs on every inbound message. This page sits underneath both.

The DLR path: carrier to webhook

An outbound send hands off to the carrier at the gateway and returns a message id. From that moment, the carrier emits delivery receipts, and each receipt crosses the same chain on its way into your account:
  1. The carrier — generates the receipt (delivered, undelivered, failed, a read receipt, and so on) against the message id from the original submission.
  2. The SMPP gateway — receives the receipt delivered by the carrier and forwards it to Orbit’s DLR endpoint over a callback.
  3. The DLR pipeline — verifies the callback, deduplicates replays, maps the carrier’s receipt codes onto Orbit’s status vocabulary, and commits a status update on the message row. If the update cannot be committed at that moment, the receipt goes into an internal retry queue and is applied later — the gateway is always given an acknowledgement so it does not re-fire the same receipt indefinitely.
  4. Status fan-out — once the update commits, the matching webhook event is dispatched to your subscribers.
What a delivered receipt leaves behind is a normal lifecycle event; what a receipt code means and which states it can drive (delivered, undelivered, failed, read, and the rest) is defined in Delivery lifecycle. The same chain applies to every SMS-bind provider that returns receipts through the gateway. A DLR is also how terminal-failure fallback gets its trigger: if you stamped fallback_channels on the send, a terminal receipt commits and a new send on the next channel fires automatically. See Fallback on terminal DLR.

The MO path: deliver_sm to inbound message

An inbound (mobile-originated) SMS enters Orbit at the same gateway used for DLRs. The chain is pure ingress — the message moves from the carrier to your tenant’s pipeline without ever touching an outbound path:
  1. The carrier — a handset sends a message to one of your numbers and the carrier pushes it onto a receive bind it holds with the gateway.
  2. The gateway — receives the inbound PDU and forwards it to Orbit’s dedicated MO bridge endpoint over an authenticated callback.
  3. The MO bridge — validates the sender, decodes the body (handling non-Latin encodings and multi-part reassembly), and publishes a normalized inbound event idempotently — a replayed delivery of the same message is dropped as a duplicate rather than processed twice.
  4. Tenant resolution — the normalized event is handed to inbound resolution, which answers the ownership question — which tenant owns the destination number — and routes it accordingly.
What happens from that point (reverse-ownership lookup, per-number route override, webhook/agent/auto-reply dispatch) is covered in Inbound message resolution. The MO bridge’s job is the edge: it receives the inbound PDU, normalizes it, and puts it on the resolution path in an idempotent way.

The gateway reconciliation loop

The SMPP gateway’s view of your account — your SMPP bind credentials and any upstream carrier connectors you bring — is not configured directly on the gateway. It lives in your account configuration, and a background reconciliation loop keeps the gateway consistent with it at all times. The loop runs continuously, roughly twice per minute, and does three things on every pass:
  1. Reads the desired state. Your active SMPP credentials and configured upstream carriers — the configuration you manage in the dashboard or via API.
  2. Compares against the gateway. It lists what the gateway currently holds and computes the difference.
  3. Applies the difference. New credentials are provisioned, revoked or suspended ones are disabled or removed, and changed configurations are re-applied. The loop is idempotent: the same pass running again with no difference is a no-op, so a pass interrupted mid-way is simply redone on the next tick.
One safety property is built into the loop: it only ever manages the credentials that came from your account configuration. Binds and connectors provisioned by the platform itself — the inbound carrier trunks that receive your MOs, for example — are explicitly protected so a reconciliation pass can never remove them.

Bind health, surfaced to your dashboard

On every pass the loop also reads the gateway’s view of each bind — how many live sessions your SMPP credential currently has, and whether an upstream carrier connector is bound — and stamps that back onto your account configuration. That is what powers the bind-count and bind-status fields the dashboard renders. The practical effect: a credential your SMPP client just connected flips from unbound to bound within about half a minute of the loop noticing, and an upstream carrier that silently lost its bind is flagged on the next pass. If a bound upstream connector drops without a status change making it obvious, the loop nudges a restart so the bind re-establishes — that rebind also shows up quickly in the dashboard status.

Provider scope: receive-only inbound providers

Orbit’s provider model draws a hard line for inbound-only providers (such as DIDWW): they receive inbound SMS and nothing else. The connector a receive-only provider holds with the gateway is used only for accepting inbound MO traffic; no outbound submission is ever routed onto it. For you, this means the set of providers you can receive inbound from is not the same question as which exit carries your outbound traffic. Outbound sending always goes over Orbit’s designated termination path. A purchased DIDWW number says it can receive SMS and it means exactly that — inbound; that capability never depends on, and never routes through, an outbound path on the same provider.

Where you observe it

Two surfaces let you see this pipeline without reading gateway internals at all:
  • Delivery webhooks. On the DLR side, every status transition that arrives from a carrier receipt fans out to your webhook subscribers. The webhook payload semantics, event types, and retry rules are covered in Webhook delivery semantics.
  • SMPP-edge bind accounting in the dashboard. On the gateway side, every registration of an SMPP credential you hold, and the status of any upstream carrier connector you configured, is stamped back by the reconciliation loop. When “my SMPP bind shows bound” or “my carrier connector says it’s connected” is the question, this is how the dashboard knows.
Together those two views tell you what the gateway thought happened, without needing to inspect it directly.