123eworld Knowledge Hub → SMS API → Page 307

SMS API Delivery Receipts: DLR Mapping, Status Codes and Reconciliation

A practical developer reference designed to solve real implementation and production problems around sms api delivery receipts: dlr mapping, status codes and reconciliation.

What a DLR is

A delivery receipt is provider or carrier evidence about the state of a submitted message. DLRs may indicate delivery, temporary failure, permanent failure or an intermediate state. They are not always identical to the final business outcome.

Canonical status mapping

Create a stable internal status vocabulary such as accepted, submitted, delivered, failed, expired and unknown. Map provider-specific codes into this vocabulary while retaining the original code.

Unknown codes

Providers can introduce new codes. Never silently map an unknown code to delivered or failed. Store it as unknown or unclassified and alert operations so the mapping can be reviewed.

Duplicate receipts

The same receipt can arrive more than once. Use a provider event ID where available or create a deterministic deduplication strategy using provider message ID, status and event timestamp.

Out-of-order receipts

An older receipt can arrive after a newer receipt. Define allowed state transitions and compare event timestamps before changing the current status.

Provider migration

A message may be attempted through one provider and later another. Attempt IDs make this traceable. The customer-facing message should remain one logical object.

DLR polling

Some providers offer polling instead of callbacks. Treat polling results as another evidence source feeding the same normalization pipeline.

Reconciliation

A submitted message with no receipt after the expected window should enter an operational investigation state rather than being assumed delivered.

Testing

Build fixtures for every supported provider code and test unknown, duplicate and out-of-order receipts.

Reporting

Expose both normalized status and appropriate delivery timestamps. Avoid presenting a provider acknowledgement as proof of handset delivery.

Audit trail

Keep the original provider payload or protected diagnostic representation according to retention policy.

Reference flow

Provider receipt → authentication/validation → deduplication → normalization → state transition → event history → customer webhook/report.

Practical implementation guidance

Design the public API around a stable logical message ID and keep provider-specific complexity behind internal adapters. Every asynchronous step should be durable, observable and safe to retry.

Security and privacy

Treat phone numbers, message content, credentials and delivery evidence as sensitive. Apply tenant authorization before data access and avoid unnecessary values in logs, traces and reports.

Developer-first principle

A useful reference page should tell developers not only what a feature is, but how to implement it safely, how to troubleshoot it and what failure cases to expect.

Related 123eworld guides

Explore the 123eworld SMS & WhatsApp Knowledge Hub for related API, routing, reliability and developer guides.

DLR normalization table

Maintain a versioned mapping table from provider code to canonical status, failure category, retryability and description. Configuration changes should be auditable. If a provider changes a code's meaning, the mapping version helps explain historical reports.

Receipt authenticity

Validate that a DLR belongs to a known provider attempt before applying it. Do not update a message merely because a payload contains a message ID. The receipt should pass provider authentication and correlation checks.

Receipt timestamps

Keep provider event time, platform receipt time and customer delivery time separately when available. These timestamps answer different operational questions and help diagnose delayed callbacks.

Polling reconciliation

When a provider supports both callbacks and polling, deduplicate the evidence sources. A polling result should not create a second delivery event if the callback has already produced the same state.

Carrier detail

Carrier-level data can help identify destination-specific problems, but it should be treated as diagnostic information. Avoid making the public API dependent on a carrier field that is unavailable for every route.

DLR storage

Store the original provider evidence in an immutable event record. Normalize it into the current message state separately. This makes later mapping corrections possible without losing evidence.

State precedence

Define whether a terminal delivered state can be replaced by a later failed receipt. In many systems, this requires investigation rather than an automatic reversal because out-of-order or conflicting evidence may be involved.

Unknown receipt handling

Unknown codes should be visible in an operational queue for classification. Automatically treating them as failure can understate delivery; automatically treating them as success can overstate it.

Provider migration

If a message is retried through another provider, associate each receipt with its attempt ID. The logical message status should be derived from the complete attempt history.

Testing matrix

Maintain test fixtures for delivered, failed, expired, duplicate, delayed, unknown and conflicting receipts for each provider adapter.

Provider code lifecycle

Treat provider code mappings as configuration with review ownership. When a new code appears, record when it was first observed, affected provider, traffic volume and provisional interpretation. This is safer than silently adding an ad hoc mapping in application code.

Conflicting evidence

If two receipts disagree, retain both and mark the logical state as requiring reconciliation according to the documented state rules. Do not discard the second receipt simply because the message already has a terminal state.

Receipt security

Provider callback endpoints should verify authentication before accepting receipt data. An unauthenticated callback can corrupt delivery reporting and create false customer notifications.

DLR retention

Detailed receipt evidence can have a shorter or longer retention period than current message state depending on operational and contractual requirements. Document the relationship so historical reports remain explainable.

DLR state machine

Receipt processing should call the same state-transition component used by polling and reconciliation. Having separate transition logic in three places is a common source of inconsistent status.

Provider adapter tests

Each provider adapter should have fixtures for its most common success and failure codes. Include malformed payloads and missing identifiers so the callback parser fails safely.

Receipt latency

Track time from provider event timestamp to platform receipt time. A sudden increase may indicate callback infrastructure problems even when SMS delivery itself remains healthy.

Operational reconciliation

For high-volume providers, reconcile statistically as well as individually. Sample successful records and fully inspect exceptions such as missing receipts, duplicate events and unknown codes.

DLR troubleshooting checklist

When a delivery status looks wrong, first locate the logical message, then its provider attempt, then the raw or protected receipt evidence, then the normalization mapping version and finally the state transition. This sequence identifies whether the problem is provider data, parsing, mapping or state logic.

Reference principle

Never throw away provider evidence simply because a normalized status has already been produced. Evidence and interpretation serve different purposes and should remain separately traceable.

Advanced production guidance

A production DLR pipeline should also support controlled replay of a receipt when an ingestion outage occurs. Replay must use the original provider event identity so it cannot create duplicate customer events. Operators should see when the receipt was originally received, when it was replayed and what state transition resulted. This is especially important when receipt processing is separated from the provider callback endpoint by a queue. The callback can remain fast while the durable event is processed later. If the processing service is unavailable, the event should remain safely queued rather than being lost. Once processing resumes, the same normalization and state-transition rules should apply. This makes recovery deterministic and keeps the DLR architecture consistent with the at-least-once delivery model used elsewhere in the SMS platform.

Reference architecture detail

A useful reconciliation report can group DLR anomalies into missing receipt, unknown code, duplicate receipt, out-of-order receipt and conflicting terminal state. Each group should have a count, sample identifiers and an owner. This turns DLR processing into a measurable operational system. When the unknown-code count rises, the provider adapter can be reviewed. When missing receipts rise only for one route, routing or provider health can be investigated. When duplicates rise across every provider, the callback ingestion layer may be the cause. These categories make troubleshooting faster and help prevent a recurring issue from being hidden inside a generic 'DLR processing error'.

Final production checklist

Finally, make DLR mappings testable outside production. A provider adapter should be able to process recorded fixtures and produce the expected canonical status without contacting a live provider. This makes upgrades safer and allows engineers to review a new provider code before enabling it for customer traffic.