BroadNet
The JournalEngineering
Engineering

SMS delivery receipts (DLR) and error codes explained.

A delivery receipt (DLR) is the operator's final verdict on your SMS. What DELIVRD, UNDELIV, EXPIRED and REJECTD mean, and how to read the stat and err fields.

BroadNet Engineering
10 min read
Engineering · Issue 23
10 min read

delivery receipt (DLR) is a status message, returned after you submit an SMS, that reports its final state — DELIVRD, UNDELIV, EXPIRED, DELETED, ACCEPTD, UNKNOWN or REJECTD — as defined by SMPP. A genuine DLR originates from the terminating operator, not the gateway, so it tells you whether the handset received the message and, via its err field, why it did not.

What a delivery receipt is — and what it is not

The moment you submit a message you get two different signals, and confusing them is the most common source of phantom outages. The first is the submission acknowledgement: on SMPP the SMSC returns a submit_sm_resp with command_status ESME_ROK (0x00000000); on an HTTP API you get a 202 and a message ID. That only means the platform accepted the message for processing. The second signal, which arrives later, is the delivery receipt — an out-of-band report of what the network ultimately did with the message. On SMPP it comes back as a deliver_sm PDU whose esm_class flags it as a receipt; on a REST API it is delivered to your webhook. Wire your system against the DLR, not the submission response — see the SMPP developer guide for the bind and receipt-request flags.

Gateway ack versus a real operator DLR

Not every DLR is created at the same place on the wire, and this is where route quality hides. A real operator-level DLR is generated by the terminating network after the handset acknowledges the short message at the SS7/MAP or Diameter layer; the operator SMSC maps that network-layer report into the SMPP receipt you receive. An intermediate or gateway DLR, by contrast, is synthesised by an aggregator when it hands the message to the next hop — before the terminating operator has confirmed anything. On a clean direct route the two coincide; on a grey route they do not.

This is why "fake DLRs" are dangerous. A grey-route aggregator that cannot obtain a genuine operator receipt will often fabricate a DELIVRD at handoff so its dashboards look healthy — even when the message was silently dropped downstream, filtered, or SIM-box terminated. The tell is a suspiciously perfect delivery rate paired with real users who never received the message, or a route that returns UNKNOWN in bulk (the SMSC has no valid state because a downstream hop never returned a real report). Paste any receipt string into the DLR decoder to see exactly what a route is claiming versus what a genuine operator receipt looks like.

How DLRs flow back to you

There are two transports and one underlying source. Over SMPP, the receipt returns asynchronously as a deliver_sm PDU on your bound session, with the final state carried in the short_message body (the classic id:… stat:… err:… string) and, on v5.0 and many v3.4 implementations, in the message_state and network_error_code TLVs. Over an HTTP API, the same information is POSTed to a webhook you register, usually as JSON. Both are ultimately derived from the network's own status report: 3GPP TS 23.040 defines the SMS-STATUS-REPORT and its TP-Status field, which the terminating SMSC translates into the SMPP message state you read. The SMPP layer is a faithful carrier for a report that is really born on the mobile network.

Whatever the transport, log the same fields for every receipt so you can diagnose by pattern rather than anecdote:

  • The message ID, so you can join the DLR to the original submit_sm.
  • The stat value (the final message state) and the err value (the network/operator error code).
  • The destination operator (MCC/MNC), the sender ID, and the route or bind used.
  • The submit-date and done-date timestamps, so you can measure end-to-end latency and spot EXPIRED patterns.
snippet
id:1a2b3c4d5e sub:001 dlvrd:001 submit date:2608031200 done date:2608031201 stat:DELIVRD err:000 text:Your BroadNet code
id:9f8e7d6c5b sub:001 dlvrd:000 submit date:2608031200 done date:2608031205 stat:UNDELIV err:062 text:Your BroadNet code

Two fields carry the diagnosis. The stat field is the standardised final message state (below). The err field is a network/operator-specific code — the same UNDELIV can arrive with different err values on different operators, so err is only meaningful in the context of its terminating network. Note that this err code is distinct from the SMPP command_status you get on submit_sm_resp (ESME_RINVDSTADR, ESME_RTHROTTLED and friends); the two are decoded differently. Use the SMPP error-code lookup for command_status values and the DLR decoder for the receipt string.

The SMPP message states, decoded

SMPP defines a small, closed set of final states plus the transient ENROUTE state you may see before a message settles. The seven states below are the ones that end a message's life, with the typical cause and the action each should trigger. Read them as a distribution across operator, sender ID and route — a single UNDELIV is noise; a route that is 40% UNDELIV on one operator is a route problem.

DLR state (stat)What it meansTypical causeWhat to do
DELIVRDThe handset confirmed receiptMessage reached the deviceNothing — this is success; spot-check against real user reports to catch fabricated DELIVRDs
ACCEPTDAccepted on the subscriber's behalf (e.g. read by customer care)Operator marked it accepted without a true handset acknowledgementTreat as soft-success; investigate any route that returns ACCEPTD in bulk — it often masks non-delivery
EXPIREDValidity period elapsed before deliveryHandset off or out of coverage for the whole window, or SMSC retries exhaustedRetry later or fall back to another channel; confirm your validity period is not too short
DELETEDMessage removed at the SMSC before deliveryManual/admin deletion, or spam-filter removalCheck operator content filtering and your sender-ID/content policy
UNDELIVThe message is undeliverableInvalid or unallocated MSISDN, no route, network-layer reject, or firewall blockValidate the number (HLR lookup), then check route quality and sender-ID registration
REJECTDThe operator refused the messageUnregistered sender ID, content filter, spam classification, or DND/consent listRegister the sender ID, fix the template, and confirm opt-in for the destination
UNKNOWNThe SMSC has no valid state for the messageA downstream hop never returned a real report — often a grey-route black holeQuestion the route; a healthy direct route rarely returns UNKNOWN

Reading DLRs as a route-quality signal

Once you accept that only an operator-level DLR is trustworthy, the receipt feed becomes your best route-quality instrument — better than any coverage map or sales deck. Direct routes return specific, consistent err codes and a stable DELIVRD rate; grey routes return generic failures, a scatter of UNKNOWN, and a delivery rate that swings week to week as operator firewalls catch the traffic and the aggregator silently re-routes. Slice the DLR distribution by terminating operator and sender ID over time: the operators where you see rising UNDELIV/UNKNOWN or vanishing err detail are the ones riding a degrading route. For regulated GCC markets — UAE under the TDRA, Saudi Arabia under the CST — REJECTD concentrated on one sender ID almost always means a registration or template-approval gap rather than a network fault.

BroadNet returns real operator-level DLRs — not gateway acks — across 1,000+ operator connections in 200+ countries, with the stat and err fields exposed per message so route quality is visible in real time, backed by a 99.99% platform SLA and direct A2P routes maintained since 2003. Explore the SMS API or the SMPP developer guide.

Frequently asked questions

What is a delivery receipt in SMS?

A delivery receipt (DLR) is a status report returned after you submit an SMS, telling you the message's final outcome — delivered, undeliverable, expired, rejected and so on. It arrives after the submission acknowledgement, either as an SMPP deliver_sm receipt PDU or an HTTP webhook. A genuine one originates from the terminating operator, not the gateway, so it confirms whether the handset actually received the message.

What does DLR mean?

DLR stands for delivery receipt (sometimes "delivery report"). In SMPP it is the message-state report the SMSC returns for a submitted message, carrying a stat field (DELIVRD, UNDELIV, EXPIRED, DELETED, ACCEPTD, UNKNOWN, REJECTD) and an operator-specific err code. It is the difference between knowing a message was accepted for processing and knowing it was actually delivered to a device.

Why does my SMS show UNDELIV / REJECTD?

UNDELIV usually means the message could not reach the handset — an invalid or unallocated MSISDN, no route, or a network-layer or firewall block. REJECTD means the operator refused it outright, typically for an unregistered sender ID, a content-filter hit, spam classification, or a DND/consent list. Read the err field and correlate failures by sender ID, operator and route to isolate the real cause.

How is a gateway ack different from an operator DLR?

A gateway acknowledgement (submit_sm_resp with ESME_ROK, or an HTTP 202) only confirms the platform accepted your message for processing. An operator DLR confirms what the terminating network actually did with it. Aggregators on grey routes sometimes fabricate DELIVRD receipts at handoff, so an operator-sourced DLR is the only trustworthy signal that the handset received the message.

References

Was this useful?

How we write and review content

Written by

BroadNet Engineering

Engineering operates the wire: SMPP binds, SS7 stacks, routing engines, the boring infrastructure that makes one-billion-message months possible. They write here when something is worth writing down.

The Journal, by email

One essay a month. Nothing else.

Subscribe and we'll send the next piece — engineering, regulation, or industry — the day it ships. No drip campaigns, no product pitches, no third-party sharing. Unsubscribe in one click.

We send one email a month. Unsubscribe anytime. See our privacy policy.

What you'll get
  • Long-form, not link bait
    Six to eleven minutes of focused writing on a single topic.
  • Written by operators
    Engineers, regulatory leads, and product writing in-house.
  • Region-aware
    MENA-grounded view on regulators, operators, and channel mix.
  • Once a month
    No drip campaign. One essay when there is one to share.
Stop reading. Start shipping.

Most of what we write we learned in production.

If this piece made you nod, we should probably talk. Bring the use case, the volumes, the markets — we'll come back with routing, pricing, and a reference customer you can call.

$ curl -X POST https://api.broadnet.me/sms/sendSms