Helo.ai marks years of building enterprise communicationExplore our Journey

Automate bulk messaging for promotions, alerts, and updates - Explore

SMS API delivery reports: what "delivered" really tells engineering teams

SMS API delivery reports show what happened to a message, but “delivered” does not always mean the customer received or read it. Learn how to interpret DLRs, handle webhooks, diagnose failures, and build reliable delivery tracking.

helo.ai authorSuraj Kori
•Sep 24, 2026•5mins
SMS API delivery reports
Summarise this post with:
ChatGPTPerplexityGeminiGrokClaude

It is 11 p.m., and the dashboard shows a healthy delivery rate for tonight's OTPs. Meanwhile, the support queue fills with "code never arrived." SMS API delivery reports sit right inside that contradiction. Many teams read them as proof. Experienced teams read them as evidence with a confidence level attached.

This guide is for the engineers and product owners who own that gap, especially teams running high-volume OTP SMS delivery. We cover how to read DLR data honestly and how to diagnose missing messages. We also cover webhooks that survive production and how to judge a provider's receipts before signing a contract.


What SMS API delivery reports actually confirm

A delivery report confirms how far a message travelled through the handoff chain, as told by the last hop that answered. That chain runs from our platform to the provider, the operator's SMSC, and finally the handset. "Delivered" usually means the operator or handset acknowledged receipt. It never confirms that a person saw or read the code.

A courier's tracking page is a fair comparison. "Delivered to building" is a useful signal. Nobody would treat it as proof the parcel reached the right desk. The same caution applies to every SMS status field we store.


Reading DLR status codes without fooling ourselves

DLR status codes fall into two tiers, and most production bugs come from mixing them up. Intermediate states include queued, accepted, submitted, and buffered. Final states include delivered, undeliverable, rejected, and expired. A final state should never be overwritten by a later intermediate event.


Normalizing codes across providers

Every vendor uses its own vocabulary. DELIVRD on an SMPP bind, "delivered" in a REST callback, and numeric code 3 elsewhere all describe one outcome. We map each raw value to a small canonical set: queued, submitted, delivered, undeliverable, rejected, expired, and unknown. The raw value stays stored beside it for debugging.

Vendors revise DLR status codes with little notice, so the mapping lives in configuration. A code change then ships as a config push instead of a release.


Inside an SMS delivery receipt: a sample payload

A typical SMS delivery receipt arrives as a JSON POST shaped roughly like this:


JSON10 lines
{
  "message_id": "msg_8f2a",
  "to": "+9198XXXXXX12",
  "status": "DELIVRD",
  "error_code": "000",
  "submitted_at": "2026-09-24T10:30:00Z",
  "done_at": "2026-09-24T10:30:03Z",
  "parts": 1,
  "client_ref": "otp-login-5521"
}


Three fields do most of the work in practice. The gap between submitted_at and done_at shows route latency. The error code explains failures. The client reference joins the receipt back to a specific login attempt or order, which is what product teams actually care about.


SMS delivered but not received: a diagnostic path

When a receipt says delivered and the customer disagrees, the cause usually sits on the sending side. Working through the checks in a fixed order saves hours of back-and-forth with support and the vendor.


Four checks before escalating


Check latency before status

Pull done_at minus submitted_at for the complaint. An OTP that lands after its validity window is technically delivered and commercially useless. If latency spikes cluster on one operator, the route becomes the prime suspect.


Check the route type

Ask whether the traffic ran over direct operator connectivity or through aggregators. Multi-hop and grey routes sometimes return a success receipt the moment a message leaves an intermediary. The dashboard looks clean while the text never reaches a phone.


Check the handset side

Full inboxes, spam filters, blocked sender IDs, and switched-off phones all cause genuine misses. One complaint rarely proves a route is broken. A cluster of complaints from one operator or circle usually does.


Check compliance filtering

For Indian numbers, a template mismatch or wrong header fails during DLT scrubbing. Those rejections are permanent, so retrying the same content only burns credits. The alert belongs with whoever owns DLT template registration, not the on-call engineer at midnight.


Building an SMS delivery status webhook that holds up in production

A dependable SMS delivery status webhook acknowledges fast, processes asynchronously, and assumes every event can arrive twice or out of order.


Acknowledge fast, process later

The handler verifies the signature, writes the raw payload to a durable queue, and returns a 200 within a few hundred milliseconds. Status mapping, CRM updates, and analytics run in workers. Slow handlers trigger provider retries, and those retries pile more load onto the same slow path during peak OTP traffic.


Duplicates, disorder, and reconciliation

The provider message ID plus the status value makes a dependable idempotency key, so repeat events become no-ops. For ordering, final states outrank intermediate ones, and operator timestamps break ties.

Events still go missing during deploys and certificate expiries. A scheduled job that polls records stuck in a non-final state past the expected delivery window catches whatever the SMS delivery status webhook missed.


Connecting receipts to OTP fallback

Many teams miss this step. When a receipt returns a final failure, or a pending message passes its deadline, the original OTP should be invalidated before any fallback fires. Otherwise a late SMS and a WhatsApp OTP fallback code can both be valid at once. That overlap is a genuine authentication gap.


How to judge a provider's delivery reporting

Buyers should test receipts against reality before trusting any dashboard. Ask how SMS API delivery reports are generated on each route, and whether traffic runs on direct connections with Jio, Airtel, Vi, and BSNL. Request per-operator latency data instead of blended averages. Confirm that failure receipts carry granular error codes.

Then run a seeded test on real handsets across every operator. A consistent gap between reported and actual delivery on any route justifies escalation, with the test logs attached.


Governance, cost, and legacy interoperability

DLR pipelines carry personal data, consume budget, and feed older systems. Each of those areas needs a named owner before launch.


Privacy and access controls

Each receipt links a phone number, a timestamp, and often a customer reference. That bundle is personal data under India's Digital Personal Data Protection Act, 2023, and under GDPR for European recipients. Role-based access control should limit full MSISDNs to a small group, with masking in logs by default.

Retention should follow purpose. Raw payloads for troubleshooting need only a short window, while longer audit trails can keep hashed numbers and final states. BFSI teams should also review the provider's SOC 2 Type II report and data residency terms.


Total cost of ownership

Most providers bundle delivery reporting into the per-message price. The running cost lives in our own stack: webhook ingress, queue throughput, event storage, reconciliation API calls, and seeded test devices. These costs scale with message volume, so they belong in the budget from day one.

The return shows up in two places. Suppressing dead numbers promptly reduces wasted sends. Faster failover, triggered by accurate receipts, lifts OTP completion rates.


Legacy interoperability

Many enterprises still run SMPP binds, on-premises CRMs, and ERPs that expect batch files. The canonical status model bridges them. Workers publish normalized events to Kafka or a similar bus, and adapters feed older systems through nightly CSVs or SOAP calls.

SMPP clients receive each SMS delivery receipt as a deliver_sm PDU, so parsers should read both the message text and optional TLV fields.


Conclusion

SMS API delivery reports earn their value when teams treat them as evidence with known limits. The practical order starts with a canonical status model and an idempotent webhook backed by polling. OTP invalidation tied to receipts comes next, followed by seeded handset tests per operator. Governance and cost tracking belong in the first design review, since retrofitting masking and retention later is expensive. Teams unsure about their current routes can start with a DLR route audit against real handsets.


Frequently asked questions


How do we check SMS delivery status via API when a webhook fails?

Query the provider's status endpoint with the stored message ID. Limit the job to non-final records older than the expected delivery window. Batch requests and respect rate limits so reconciliation never slows live OTP traffic.


What is the difference between a carrier vs handset delivery receipt?

A carrier receipt confirms the operator network accepted the message. A handset receipt confirms the device acknowledged it. Availability varies by country and operator, so carrier-only confirmations deserve lower confidence in SLA reporting.


How can teams spot a fake DLR in SMS traffic?

Warning signs include near-perfect delivery rates, identical latencies across thousands of messages, and almost no error variety. Real networks produce messy data. Seeded tests on real handsets should confirm any suspicion before escalating to the vendor.


How should DLT SMS error codes be handled in India?

Treat them as permanent failures and skip retries. Check the header, template ID, entity ID, and variable tagging against the DLT portal. Route these events to the template owner with the raw error attached.


What does the DELIVRD status mean in an SMPP delivery receipt?

DELIVRD is the final success state in SMPP receipt text, usually shown as stat:DELIVRD. It means the operator reported delivery to the handset. It says nothing about whether the recipient opened or read the message.

About Author
helo.ai author
Suraj Kori

Suraj Kori is associated with Helo.ai and focuses on enterprise communication technologies including WhatsApp Business API, SMS, RCS, and CPaaS solutions. He contributes practical insights on AI-driven messaging, customer engagement, and omnichannel communication strategies for modern businesses.

Related Blogs

SMS API for Startups
SMS / All

SMS API for Startups: How to Choose One That Won't Break When You Scale

Choosing an SMS API for a startup is about more than price. Compare delivery visibility, DLT support, pricing, engineering reliability, scalability, and fallback options before you commit.

helo.ai author
Suraj Kori
Sep 23, 2026•5mins
How Does an SMS API Work
SMS / All

How Does an SMS API Work? A Practical Guide for Teams Building at Scale

See what happens after your application sends an SMS API request—from authentication and DLT checks to operator routing, delivery reports, retries, and scale.

helo.ai author
Suraj Kori
Sep 23, 2026•6mins
SMS API Compliance
SMS / All

SMS API Compliance in India: The Complete 2026 Guide

Understand the rules behind compliant business SMS in India, from DLT registration and approved templates to customer consent, API requirements, and the latest regulatory changes.

helo.ai author
Suraj Kori
Sep 23, 2026•6mins
SMS API Delivery Reports: DLR Codes, Webhooks & Fixes