Rate this page:

Best Practices for Messaging Delivery Status Logging

Financial regulations require some companies to maintain a record of all communications, including unsuccessful attempts.

This best practices documentation focuses on logging for mobile terminated/outbound messaging, but the process is similar for inbound messaging. "Messaging" here applies to each of the following channels: SMS, MMS, WhatsApp, Facebook Messenger (in public beta), and Google Business Messages (in private beta).

How Twilio Message delivery status works

When you first make a request to the Twilio Messaging API, Twilio responds synchronously with either success (200) or failure (400) HTTP status code. If the request was successful, Twilio returns the Message SID in the response.

The Message SID is your record that a message was created and has been accepted by Twilio for processing. Twilio recommends that you store this Message SID along with the current state of the message at the time Twilio returned the Message SID to you. The initial state of the message will be either Accepted or Queued.

Twilio's response to your outbound Message request

  "api_version": "2010-04-01",
  "body": "Join Earth's mightiest heroes. Like Kevin Bacon.",
  "date_created": "Thu, 30 Jul 2015 20:12:31 +0000",
  "date_sent": "Thu, 30 Jul 2015 20:12:33 +0000",
  "date_updated": "Thu, 30 Jul 2015 20:12:33 +0000",
  "direction": "outbound-api",
  "error_code": null,
  "error_message": null,
  "from": "+15017122661",
  "num_media": "0",
  "num_segments": "1",
  "price": null,
  "price_unit": null,
  "status": "sent",
  "subresource_uris": {
  "to": "+15558675310",

Message statuses

Your message goes through multiple stages while Twilio processes it. See the Message Resource reference for all possible Message status values.

Message Status

There are two ways for a user to get status updates on a message:

  • poll the API
  • receive a Status Callback.

Poll the API

At any point after the Message Resource has been created, you can make a GET request to the Twilio Messaging API using the Message SID to determine the status of the message. Twilio returns the message record including the message status.

See the API Documentation for a Message Resource on how to GET the message status and other attributes. This works fine for small-volume use cases and ad hoc analysis, but for large-scale logging, you should use status callbacks.

Receive a status callback

For detailed information on receiving and reading Message status callbacks, please see the relevant section of the Message Resource documentation.

Sample status callback

Example Callback for Status 'Delivered'

MessageStatus: delivered
MessageSid: SM4262411b90e5464b98a4f66a49c57a97
MessagingServiceSid: MG4d9d720b38f7892254869fabdca51e69
AccountSid: AC0db966d80e9f1662da09c61287f8bba1
From: +16232320112
ApiVersion: 2010-04-01
To: +15622089096
SmsStatus: delivered
SmsSid: SM4262411b90e5464b98a4f66a49c57a97

High-volume callback data storage using Twilio Functions

For customers sending millions of messages in a given day, handling a high volume of callbacks can present an operational risk. Imagine sending 10 million messages and receiving 20 million callbacks. Using Twilio Functions, you can configure your status callback endpoint to write proactively to an external location such as AWS for post processing later.

Twilio Functions have the same reliability as other Twilio platform capabilities. The following guide describes how to use functions to handle callbacks at scale: Twilio Serverless Status Callback Handler built in AWS

Recommendations for maintaining messaging records

When sending a message request, record the relevant message details in persistent storage. Then, whether using polling or status callbacks (Twilio recommend Status Callbacks), update messages with the status and associated Message SID once known. This persistent data store becomes the record of whether a message sent successfully or not.

If for some reason a message status hasn’t been updated to delivered or undelivered within 12 hours, it is possible that the status callback was not received. In this case, we recommend making a polling request to the Messaging API to retrieve the status of the message based on the Message SID.

It is always best practice to reconcile message statuses at least once a day to verify that no status events have been missed.

Additionally, as part of the reconciliation process Twilio can return a list of all messages SIDs for a given time frame. (See this Support article for details on Exporting SMS Logs in bulk.)

This list of SIDs can be used to determine if any messages got created during the sync phase for which no Message SID was returned. You can use the message envelope details like the message timestamp and recipient PN (To) to find matching messages in your store that are missing these SIDs. (If you’re redacting data, the last 4 digits of the recipient phone number may be removed, but the remaining digits may be enough to match the SIDs appropriately).

Additional questions

Q: Can a user send a customer identifier for a message, or is only the Twilio-defined SID available?

A: Only the Twilio-defined SID will be populated by default, however for reporting purposes you may add additional identifiers as URL query parameters if setting your status callback programmatically.

For debugging purposes, it is also possible to subscribe to the Twilio debugger webhook and find out immediately when errors with your messages occur.

References & additional tools

  1. Help Center article on Exporting SMS and Call Logs
  2. API Guide for the Message Resource
  3. Help Center article on Twilio Serverless Status Callback Handler built in AWS
Rate this page:

Need some help?

We all do sometimes; code is hard. Get help now from our support team, or lean on the wisdom of the crowd by visiting Twilio's Stack Overflow Collective or browsing the Twilio tag on Stack Overflow.

Loading Code Sample...

        Thank you for your feedback!

        Please select the reason(s) for your feedback. The additional information you provide helps us improve our documentation:

        Sending your feedback...
        🎉 Thank you for your feedback!
        Something went wrong. Please try again.

        Thanks for your feedback!