Skip to main content

SMS Delivery Reports

Delivery reports (DLRs) provide real-time feedback on the status of every SMS you send through Exotel. This guide covers how to configure, receive, and interpret delivery reports.

What Are Delivery Reports?​

A delivery report is a status notification that tells you whether an SMS was successfully delivered to the recipient's handset, is still in transit, or has failed. Exotel supports two methods for receiving delivery reports:

MethodDescriptionBest For
Webhook CallbacksExotel pushes status updates to your serverReal-time processing, production systems
API PollingYou query the SMS Details API for statusAd-hoc checks, debugging
DashboardView reports in the Exotel web consoleManual review, reporting
tip

Webhook callbacks are the recommended approach for production systems. They provide near-instant status updates without the overhead of polling. See SMS Webhooks for detailed setup instructions.

Delivery Report Flow​

Your App → Exotel API → Operator → Handset
↓
Status Callback ← Operator DLR
↓
Your Webhook Endpoint
  1. Message Submitted -- Your app sends an SMS via the Exotel API.
  2. Queued -- Exotel accepts the message and queues it for delivery.
  3. Sent to Operator -- Exotel transmits the message to the telecom operator.
  4. Delivered / Failed -- The operator confirms delivery to the handset or reports a failure.
  5. Callback Sent -- Exotel forwards the delivery status to your configured webhook URL.

Configuring Delivery Report Callbacks​

Per-Message Callback​

Set the StatusCallback parameter when sending an SMS to receive the delivery report at a specific URL:

curl -u '<api_key>:<api_token>' -X POST "https://api.exotel.com/v1/Accounts/<account_sid>/Sms/send" \
-d "From=EXOTL" \
-d "To=+919876543210" \
-d "Body=Your OTP is 123456" \
-d "DltEntityId=1234567890123" \
-d "DltTemplateId=1107160000000012345" \
-d "StatusCallback=https://your-server.com/sms/status"

Account-Level Callback​

Configure a default callback URL for all SMS in your Exotel dashboard:

  1. Log in to the Exotel Dashboard.
  2. Navigate to Settings > SMS Settings.
  3. Enter your default Status Callback URL.
  4. Save the settings.
note

Per-message callbacks override the account-level callback URL. If you set StatusCallback in the API request, it takes precedence.

Delivery Report Payload​

When Exotel sends a delivery report to your webhook, the payload includes the following fields:

FieldDescriptionExample
SmsSidUnique identifier for the SMSsms_sid_value
ToRecipient phone number+919876543210
FromSender IDEXOTL
StatusCurrent delivery statusdelivered
DetailedStatusDetailed status descriptionDELIVERED_TO_HANDSET
DetailedStatusCodeNumeric status code20000
SentAtTimestamp when SMS was sent2025-01-15 10:30:00
UpdatedAtTimestamp of the status update2025-01-15 10:30:05

Sample Callback Payload​

{
"SmsSid": "a1b2c3d4e5f6",
"AccountSid": "your_account_sid",
"From": "EXOTL",
"To": "+919876543210",
"Body": "Your OTP is 123456",
"Status": "delivered",
"DetailedStatus": "DELIVERED_TO_HANDSET",
"DetailedStatusCode": 20000,
"SentAt": "2025-01-15T10:30:00+05:30",
"UpdatedAt": "2025-01-15T10:30:05+05:30"
}

Delivery Statuses​

StatusDetailedStatusDescription
queuedQUEUEDMessage accepted and queued for sending
sendingSENDINGMessage is being transmitted to the operator
submittedSUBMITTED_TO_CARRIERMessage submitted to the telecom operator
sentSENTMessage sent by the operator (awaiting handset confirmation)
deliveredDELIVERED_TO_HANDSETMessage delivered to the recipient's phone
failedVarious (see below)Message delivery failed
expiredEXPIREDOperator could not deliver within the validity period

Failed Status Codes​

DetailedStatusCodeCauseResolution
FAILED_DLT_TEMPLATE30001Message does not match DLT templateEnsure message body matches the approved template exactly
FAILED_DLT_ENTITY30002Invalid DLT entity IDVerify your entity ID in your DLT portal account
FAILED_INVALID_SENDER30003Sender ID not registeredRegister and approve your sender ID on the DLT portal
FAILED_DND30004Recipient on DND registryUse transactional SMS for critical messages
FAILED_INVALID_NUMBER30005Invalid or unreachable phone numberVerify the recipient's phone number
FAILED_OPERATOR30010Operator-side delivery failureRetry after some time; contact support for persistent failures
FAILED_EXPIRED30011Message validity period expiredRecipient may have been out of coverage; resend if needed
FAILED_UNKNOWN30099Unknown failureContact Exotel support with the SmsSid

For the complete list of status codes, see SMS Status Codes.

Polling via API​

If you prefer to check delivery status on demand, use the SMS Details API:

curl -u '<api_key>:<api_token>' "https://api.exotel.com/v1/Accounts/<account_sid>/Sms/Messages/<sms_sid>"

Response:

{
"SMSMessage": {
"Sid": "a1b2c3d4e5f6",
"Status": "delivered",
"DetailedStatus": "DELIVERED_TO_HANDSET",
"DetailedStatusCode": 20000,
"DateCreated": "2025-01-15T10:30:00+05:30",
"DateUpdated": "2025-01-15T10:30:05+05:30",
"From": "EXOTL",
"To": "+919876543210",
"Body": "Your OTP is 123456",
"Direction": "outbound-api",
"Price": "0.20"
}
}

Delivery Report Timing​

Delivery reports are typically received within seconds, but timing depends on the telecom operator:

ScenarioExpected Time
Successful delivery1-15 seconds
Handset off / out of coverageUp to 24-72 hours (then expires)
DLT validation failureImmediate (within seconds)
DND rejectionImmediate (within seconds)
Operator failure1-60 minutes
warning

Do not assume a message has failed if you have not received a delivery report within a few seconds. Some operators may take several minutes to return a DLR, especially during high-traffic periods.

Best Practices​

  1. Always configure status callbacks -- Do not rely solely on manual checks. Automate delivery tracking with webhooks.
  2. Handle retries gracefully -- If your webhook endpoint is down, Exotel retries the callback. Ensure your endpoint is idempotent.
  3. Log all delivery reports -- Store delivery reports with the SmsSid for audit trails and debugging.
  4. Monitor failed statuses -- Set up alerts for elevated failure rates, which may indicate DLT configuration issues.
  5. Use detailed status codes -- The DetailedStatus field provides more granular information than the top-level Status field.

Next Steps​