01 · Definition
What is an SMS delivery report?
An SMS delivery report (DLR) is the receipt an operator's SMSC sends back after it tries to deliver a text message: it says whether the message reached the handset, failed, expired or was rejected, with timestamps and usually an error code. Over SMPP it arrives as a deliver_sm PDU with esm_class 0x04 and a text body such as id:4126779610 sub:001 dlvrd:001 submit date:2610191402 done date:2610191402 stat:DELIVRD err:000; an SMS gateway with an HTTP API turns the same information into a JSON callback to the URL you registered.
The final states are standard across operators: DELIVRD (delivered to the handset), UNDELIV (undeliverable — an invalid, barred or inactive number, or the network gave up), EXPIRED (the validity period ran out, usually because the phone stayed off), REJECTD (refused by the network — in India often a DLT scrubbing failure), DELETED and UNKNOWN. ENROUTE and ACCEPTD are intermediate. The err field carries the operator's own reason code, which is not standardised, so gateways map it to their own codes.
A DLR is much coarser than WhatsApp's message status. It has no read state at all — the closest WhatsApp equivalent is the delivery receipt, never the read receipt — it does not always prove the handset itself answered rather than a network along the way, and on cheap grey routes receipts can even be faked. It is still the only evidence SMS gives you, and fallback logic, billing reconciliation and route-quality monitoring all run on it. An HLR lookup answers a different question: whether a number is valid before you send.
Key takeaways
- An SMS delivery report (DLR) is the operator's receipt saying whether a text reached the handset, failed, expired or was rejected.
- Final states are DELIVRD, UNDELIV, EXPIRED, REJECTD, DELETED and UNKNOWN; ENROUTE and ACCEPTD are intermediate.
- Over SMPP a DLR arrives as deliver_sm with esm_class 0x04, but only if you set registered_delivery when submitting.
- The err code inside a DLR is operator-specific, so map it to your own small set of reasons.
- DLRs never report reads, and on low-quality routes they can be faked — check them against real outcomes such as OTP completions.
02 · Specifications
An SMS delivery report: key facts and limits
| SMPP carrier | deliver_sm with esm_class 0x04 |
|---|---|
| Request flag | registered_delivery 1 (final) or 2 (failures only) |
| Final states | DELIVRD, UNDELIV, EXPIRED, REJECTD, DELETED, UNKNOWN |
| Intermediate states | ENROUTE, ACCEPTD |
| Matching key | message_id / receipted_message_id |
| Date format | YYMMDDhhmm in the receipt text |
| Read signal | None — SMS has no read receipt |
03 · Code samples
An SMS delivery report in code
esm_class 0x04 (this deliver_sm is a delivery receipt)source_addr 919812345678 (the handset the SMS went to)short_message id:4126779610 sub:001 dlvrd:001 submit date:2610191402 done date:2610191402 stat:DELIVRD err:000 text:482913 is your OTPreceipted_message_id F5F9A8DA (TLV 0x001E: the same ID in hex)message_state 2 (TLV 0x0427: 2 = DELIVERED)# stat values: DELIVRD UNDELIV EXPIRED REJECTD DELETED UNKNOWN (final)# ENROUTE ACCEPTD (intermediate)# dates are YYMMDDhhmm; err is operator-specific
The same message ID appears as decimal 4126779610 in the text and as hex F5F9A8DA in the TLV — normalise before matching.
04Playground
A working model of DLR. Use its controls to replay it step by step.
Where can an SMS end up? Trace every DLR state
- Submitted to ENROUTE: accepted
- ENROUTE to DELIVRD: handset ack
- ENROUTE to EXPIRED: validity ends
- ENROUTE to UNDELIV: permanent error
- Submitted to REJECTD: scrubbing fails
- ENROUTE to No final DLR: no receipt
- Submitted
- ENROUTE
- DELIVRD
Step 3 of 3 · end of walk
DELIVRD
Final: the handset acknowledged the message. It does not mean the message was read.
Arrived from ENROUTE via handset ack.
Can move to
Nothing — this is a final state.
Happy path, step 3 of 3: DELIVRD (via handset ack). Final: the handset acknowledged the message. It does not mean the message was read.
05 · Operation
How does an SMS delivery report work?
Ask for a report
Set
registered_deliveryto 1 insubmit_smfor a final receipt on success or failure (2 asks for failures only), or pass the gateway's DLR flag and callback URL.Store the message ID
Save the
message_idfromsubmit_sm_respor the API response next to your own reference, the destination and the time sent.Receive and acknowledge
The receipt arrives as
deliver_smor an HTTP callback. Acknowledge it at once withdeliver_sm_respor a 200, then process it from a queue.Match and update
Match the receipt's
id(or thereceipted_message_idTLV) to the stored ID, move the message to its final state and recorderranddone date. Never let a late intermediate state overwrite a final one.Act on the outcome
DELIVRD: stop. UNDELIV or REJECTD: do not retry blindly — fix the number, header or template. EXPIRED, UNKNOWN or no report by your timer: fall back to WhatsApp or a voice call for anything urgent.
06 · Cautions
Common mistakes with an SMS delivery report
Treating no report as delivered
Some messages never get a final receipt. Give every message a timer; if no final state arrives, mark it unknown and trigger the fallback for anything that matters.
Matching on mismatched IDs
Many SMSCs return the ID in hex in one place and decimal in another, or with leading zeros. Normalise both sides, or unmatched receipts will pile up as "pending" forever.
Retrying REJECTD and UNDELIV blindly
A rejected template or an invalid number fails again on retry, and you pay each time. Read the error, fix the DLT registration or the number, and retry only temporary failures.
Trusting a perfect delivered rate
Grey routes can return fake DELIVRD receipts. Cross-check DLRs against outcomes you control — OTPs entered, links clicked — per route and operator.
Comparing DLRs with WhatsApp read rates
SMS has delivered and failed states only, while WhatsApp also reports reads. Compare SMS delivered with WhatsApp delivered, and judge engagement by clicks or replies.
07 · Rationale
Why does an SMS delivery report matter?
Without delivery reports you are sending blind: you cannot tell a wrong number from a switched-off phone, you cannot switch an OTP that never arrived to a fallback channel such as WhatsApp or voice, and you cannot show a client or an auditor what happened to a message. DLR data per operator and route is also the fastest way to spot a degrading route — or a route faking success, where a 99% delivered rate sits next to OTPs nobody enters.
08 · Worked example: OTP fallback for a Jaipur travel app
Example: OTP fallback for a Jaipur travel app
A Jaipur travel app sends login OTPs by SMS and waits 30 seconds for a final DLR. DELIVRD does nothing; EXPIRED, UNDELIV or silence shows a "Get the code on WhatsApp" button that sends an authentication template. One Monday, receipts from one operator turn into a wall of REJECTD within a second of submission. The raw err codes and the timing point to DLT scrubbing rather than handsets, and the cause is a marketing teammate's edit to the OTP wording, which no longer matched the registered content template. Restoring the registered text clears the rejections, and the team adds an alert on any operator whose REJECTD share jumps above its usual level.
09 · Recommended practice
Best practices for an SMS delivery report
- Acknowledge DLRs before processing them; slow acknowledgements make the SMSC resend or throttle.
- Store raw receipt text for a few days for support and audits.
- Track time-to-DELIVRD as well as the outcome — rising latency is an early sign of route trouble.
- Map operator err codes to a short list of your own: invalid number, DLT rejection, network, unknown.
10 · Questions and answers
DLR FAQs
- Does an SMS delivery report mean the message was read?
- No. A DLR only says the message reached the handset, failed, expired or was rejected; SMS has no read receipts. If you need engagement, measure replies, clicks or OTP completions.
- Why does the DLR say DELIVRD when the customer never got the OTP?
- The receipt may come from a network along the way rather than the handset, the route may be faking receipts, or the text arrived but was filtered or overlooked. Compare delivered rates with OTP completions per route to find out.
- How long does an SMS delivery report take to arrive?
- Usually a few seconds for a reachable phone. For a phone that is off, the final report comes only when it reconnects or when the validity period expires, which can be hours or days later.
- What does REJECTD mean for SMS in India?
- Usually that the operator refused the message before delivery, most often in DLT scrubbing. Check that the header, content template, variables and entity ID match the DLT registration and that any link is whitelisted.
- How is an SMS DLR different from WhatsApp delivery status?
- WhatsApp reports sent, delivered, read and failed through status webhooks for every message, with structured error codes. An SMS DLR reports only delivery or failure, with operator-specific codes and no read state.