Delivery Reports
Track every message in real-time. Our delivery reports give you full visibility into message status from submission to final delivery — with industry-standard SMPP status codes.
How Delivery Reports Work
Message submitted ACCEPTD
Your message is accepted via API or SMPP and queued for delivery.
Sent to carrier ENROUTE
Message forwarded to the destination mobile network via our direct routes.
Delivered to handset DELIVRD
The recipient's phone confirms receipt. DLR sent to your webhook.
Or: delivery failed UNDELIV / REJECTD / EXPIRED
The carrier reports a permanent failure, rejection, or timeout.
SMPP Status Codes Explained
DELIVRDDeliveredMessage successfully delivered to the handset.
UNDELIVUndeliverablePermanent failure — number doesn't exist, is disconnected, or the carrier rejected the message.
EXPIREDExpiredMessage TTL exceeded. The handset was unreachable for the entire validity period (default 48h).
REJECTDRejectedMessage rejected by the carrier — spam filter, invalid sender ID, or blocked content.
ACCEPTDAcceptedMessage accepted by the SMSC but not yet delivered. Intermediate status.
UNKNOWNUnknownNo delivery receipt received from the carrier within the timeout window.
DELETEDDeletedMessage was deleted by the carrier before delivery (e.g. cancel request).
ENROUTEEn RouteMessage is in transit to the destination network. Will resolve to DELIVRD or UNDELIV.
Webhook Setup
Configure a webhook URL to receive delivery reports as HTTP POST requests. You can set this up via the dashboard or the API:
// Create a webhook
POST /v1/webhooks
{
"url": "https://yourapp.com/dlr-webhook",
"events": ["delivered", "failed", "expired", "rejected"],
"secret": "your_webhook_secret" // for HMAC signature verification
}// Webhook payload (POST to your URL)
{
"event": "delivery_report",
"message_id": "msg_abc123",
"to": "+447700900000",
"from": "MyBrand",
"status": "DELIVRD",
"status_code": 0,
"error_code": null,
"error_message": null,
"segments": 1,
"submitted_at": "2024-01-15T10:29:55Z",
"delivered_at": "2024-01-15T10:30:00Z",
"network": "EE",
"country": "GB"
}
// Signature header for verification:
// X-BSR-Signature: sha256=<HMAC of body using your webhook secret>Real-time vs Batched Reports
| Feature | Real-time | Batched |
|---|---|---|
| Delivery | Instant (< 1 second) | Every 1/5/15/60 minutes |
| Format | Single JSON per event | Array of events |
| Best for | Transactional SMS, OTPs | Bulk campaigns, reporting |
| Webhook load | Higher (many small POSTs) | Lower (fewer large POSTs) |
| Retry on failure | 3 retries with backoff | 3 retries with backoff |
| Setup | Default — no config needed | Set batch_interval in webhook config |
Troubleshooting Common Issues
Not receiving webhooks
Verify your URL is publicly accessible, returns 200 OK, and responds within 10 seconds. Check firewall rules. Test with the dashboard webhook tester.
High UNDELIV rate
Clean your number list — remove invalid, disconnected, and landline numbers. Use our number validation API to verify numbers before sending.
Many EXPIRED messages
Recipients' phones may be off. Consider time-of-day scheduling. Check if you're sending to prepaid numbers that may be out of credit.
UNKNOWN status
Some carriers don't return final DLRs. This is more common on indirect routes. Upgrade to direct routes for better DLR rates.
REJECTD messages
Check your sender ID is registered for the destination country. Verify message content doesn't contain blocked keywords. Review carrier-specific content policies.