123eworld Knowledge Hub → Transactional SMS API → Page 276
Transactional SMS API Delivery Receipts: DLR Architecture, Status Mapping and Reliable Processing
A practical developer reference designed to solve real implementation, integration and production problems around transactional sms api delivery receipts: dlr architecture, status mapping and reliable processing.
Why delivery receipts matter
A transactional SMS API has two very different moments: the platform accepts a message and the downstream network reports what happened to it. Delivery receipts bridge that gap. A reliable design treats delivery receipts as asynchronous events, not as a simple extension of the original HTTP response.
DLR lifecycle
A typical lifecycle moves from accepted to queued, submitted, delivered, failed or expired. Provider-specific states may be more detailed, so the platform needs a normalized internal state machine.
Provider status mapping
Providers use different codes and descriptions. Build a mapping layer that converts raw provider statuses into stable platform statuses while retaining the original provider code for diagnostics.
Duplicate receipts
The same receipt can arrive more than once. Event IDs, provider message IDs and idempotent state transitions prevent duplicate business processing.
Late receipts
A delivery receipt can arrive after an application has already marked a message as failed due to timeout. The state model should define which later events are allowed to improve the final state.
Unknown receipts
Do not discard a receipt simply because its code is unknown. Store the raw event and classify it as unknown so the mapping can be updated later.
Webhook processing
Receipt ingestion should authenticate the provider, validate the event, persist it and acknowledge quickly. Heavy business processing should happen asynchronously.
Reconciliation
If receipts are missing, a reconciliation process can query provider status where supported or flag messages for operational investigation.
Customer reporting
Expose a stable status vocabulary to developers while providing detailed failure information where appropriate.
Testing
Test duplicate, late, malformed, unknown and out-of-order receipts, plus provider retries and webhook endpoint failures.
Reference flow
Provider receipt → authentication → validation → raw event storage → normalized status → idempotent state transition → customer webhook/reporting.
Operational checklist
Monitor receipt delay, unknown status rate, webhook failures, duplicate events and reconciliation backlog.
Architecture principle
Keep synchronous API handling small and deterministic. Authenticate, authorize, validate and persist the logical message before handing delivery work to asynchronous processing. This keeps provider latency out of the customer request path and creates a stable foundation for retries and reconciliation.
Security principle
Tenant isolation, least privilege, encrypted transport, protected credentials and careful logging apply to every layer. Operational convenience should never become a reason to expose phone numbers, message content or secrets unnecessarily.
Developer experience
Documentation should explain the exact difference between accepted, submitted and delivered. Provide stable identifiers, canonical statuses, retry guidance, examples and failure scenarios so developers can build correct integrations without reverse-engineering provider behaviour.
Production testing
Test the unhappy paths deliberately: timeouts, duplicates, provider outages, throttling, worker crashes, delayed receipts, malformed callbacks and configuration changes. Reliability is demonstrated by controlled failure testing, not only by successful sends.
Operational checklist
Before production, verify durable storage, idempotency, queue behaviour, provider capacity, receipt processing, monitoring, alerting, data protection, reconciliation and recovery procedures.
Related knowledge
For additional implementation guidance, use the 123eworld SMS & WhatsApp Knowledge Hub and the related pages in this master project.
Receipt state machine design
Treat status as a state machine rather than a field that can be overwritten by any incoming event. Define which transitions are valid and which are terminal. For example, a delivered event should not later turn the logical message into a temporary provider failure merely because an old callback arrived late. Store event timestamp and provider timestamp separately so ordering can be evaluated using evidence rather than arrival time. A state transition should be idempotent and preferably transactional with the stored event. This design is especially important when multiple workers process callbacks concurrently.
DLR polling and push
Some providers offer push receipts, status queries or both. Push events are efficient but can be delayed or lost, while polling can create provider load. A mature platform can use push as the primary source and targeted polling for messages that remain unresolved beyond a threshold. Polling should be bounded and should never create a query storm during a provider incident. The reconciliation process should use provider message IDs and logical message IDs to correlate results.
Final status semantics
Define exactly what delivered means. In many SMS systems it represents a downstream delivery report rather than proof that a person read the message. Failed can represent a permanent network or recipient problem, while expired may indicate that delivery was not completed within the provider's validity period. Clear semantics prevent developers from treating delivery as application-level confirmation.
Receipt retention
Keep enough receipt evidence to troubleshoot delivery disputes and reconcile asynchronous events. Raw provider codes, timestamps and provider IDs are useful operational evidence, but retention should follow the platform's data-minimization policy. Separate customer-facing status from internal diagnostic detail.
Failure isolation
A broken customer webhook should not stop receipt processing. Persist the receipt first, acknowledge the provider and deliver customer callbacks asynchronously. This protects the core delivery state even when an external customer system is unavailable.
Operational runbook
When delivery rates suddenly fall, compare submission acceptance, receipt delay, provider error codes and destination distribution. If submissions are healthy but receipts stop arriving, investigate the receipt channel separately from the send path. This distinction can shorten incident diagnosis substantially.
Deep production guidance
A delivery-receipt system should also distinguish provider submission evidence from handset-network evidence. A provider may accept a submit operation and later report a delivery outcome, but the semantics of that report depend on the provider and destination network. Do not convert every provider-specific 'success' response into delivered. Store timestamps for API acceptance, provider submission, receipt arrival and final state transition. This lets operations calculate where delay occurred. If provider submission is fast but receipts are consistently late, the receipt channel or downstream network may be the bottleneck. If submission itself is slow, the provider route may be constrained. These measurements are useful for routing decisions and customer support. For high-volume systems, receipt ingestion should be horizontally scalable and partitionable by provider or event key. The receipt processor should acknowledge events quickly after durable persistence and perform expensive enrichment asynchronously. This protects the provider callback endpoint from backpressure caused by a slow database or reporting service. Finally, receipt processing should be replayable from stored raw events. A mapping bug discovered later should allow the platform to reprocess historical events without asking the provider to resend them.
Implementation and troubleshooting note
A practical implementation should separate receipt ingestion from customer notification. First persist and normalize the provider event; then publish an internal event for reports, webhooks and analytics. This prevents a slow customer endpoint from blocking the core receipt path. It also allows replay after a software defect. The state machine should use monotonic business semantics where appropriate, but retain every raw event so a later investigation can understand contradictory evidence. For example, an old failed event arriving after a delivered event should not automatically downgrade the logical message. Instead, the platform can retain the event as late evidence and keep the final state based on its documented transition policy. This is a subtle but important distinction between event history and current state.
Production validation
Production validation should include a complete synthetic message from API request through provider submission and receipt processing. Verify that the message ID remains unchanged, the provider ID is correlated correctly, duplicate receipts are ignored and the customer webhook is delivered once according to the documented event semantics. Test a deliberately delayed receipt and an unknown provider code. These tests prove that the receipt architecture is resilient to the exact conditions that occur in distributed telecom systems. The result should be recorded as part of the production-readiness evidence.
Quick troubleshooting checklist
Check receipt delay, raw provider status, message correlation, duplicate event handling, final-state rules and customer webhook health.
Advanced design consideration
For enterprise integrations, delivery receipts should be treated as a source of operational truth that is separate from the business transaction itself. A banking system may initiate an alert and record its own transaction status, while the messaging platform records delivery evidence. Neither system should overwrite the other's state. Use message IDs to correlate them. If the SMS delivery fails, the bank may decide whether another channel is needed, but the SMS platform should accurately report the failure rather than inventing a business outcome. This separation keeps the API reusable across industries and prevents messaging-specific semantics from leaking into core applications.