Skip to contentSkip to navigationSkip to topbar
Page toolsOn this page
Looking for more inspiration?Visit the

Webhooks Security


Ensuring secure communication between your application and Twilio is essential. There are several layers of security and validation that you can build into your web application for handling Twilio webhooks - let's review each of these.


HTTPS/TLS

httpstls page anchor

The first step you should take to secure your web application is to ensure that you are using HTTPS for your web application's endpoint. Twilio will not connect to an HTTPS URL with a self-signed certificate, so use a certificate from a provider such as Let's Encrypt(link takes you to an external page).

Twilio can use the HTTP protocol for callbacks - for instance, if you are working on a development environment that does not have SSL certificates installed. On your Twilio project's Settings page in the Console, the SSL Certificate Validation setting enforces validation on webhooks.

(warning)

Warning

Be aware Twilio strongly recommends against pinning certificates. This is an outdated practice as certificates can be rotated at any time.

Here is the list of supported TLS ciphers for callbacks.(link takes you to an external page)


Validating Signatures from Twilio

validating-signatures-from-twilio page anchor

Your web application should verify that Twilio is the service that sent a webhook before responding to that request. This is important for securing sensitive data, and to protect your application and servers from abuse.

Twilio will sign all inbound requests to your application with an X-Twilio-Signature HTTP header. Twilio uses the parameters sent in the webhook (either GET or POST) and the exact URL your application supplied to Twilio to create this signature. The signature uses the HMAC-SHA1 hashing algorithm with your Twilio account's auth token as the secret key.

Your application can verify that this signature is correct using the server-side Twilio SDKs (see examples below). You will need your account's auth token, the value of the X-Twilio-Signature HTTP header Twilio passed to you, the URL Twilio sent the webhook to and all parameters sent by Twilio.

(error)

Danger

The parameters included in webhook events vary by channel and event type and are subject to change in the future. Twilio will occasionally add new parameters without advance notice. When integrating with webhooks, your implementation must be able to accept and correctly run signature validation on an evolving set of parameters. We strongly recommend using the provided signature validation library from a Twilio SDK and not implementing your own signature validation.

(information)

Info

When validating the signature on a WebSocket request, note that the header parameter name will be all lowercase: x-twilio-signature.

Validate Signature of Request (x-www-form-urlencoded body)Link to code sample: Validate Signature of Request (x-www-form-urlencoded body)
1
// Get twilio-node from twilio.com/docs/libraries/node
2
const client = require('twilio');
3
4
// Your Auth Token from twilio.com/console
5
const authToken = process.env.TWILIO_AUTH_TOKEN;
6
7
// Store Twilio's request URL (the url of your webhook) as a variable
8
const url = 'https://mycompany.com/myapp';
9
10
// Store the application/x-www-form-urlencoded parameters from Twilio's request as a variable
11
// In practice, this MUST include all received parameters, not a
12
// hardcoded list of parameters that you receive today. New parameters
13
// may be added without notice.
14
const params = {
15
CallSid: 'CA1234567890ABCDE',
16
Caller: '+12349013030',
17
Digits: '1234',
18
From: '+12349013030',
19
To: '+18005551212',
20
};
21
22
// Store the X-Twilio-Signature header attached to the request as a variable
23
const twilioSignature = 'Np1nax6uFoY6qpfT5l9jWwJeit0=';
24
25
// Check if the incoming signature is valid for your application URL and the incoming parameters
26
console.log(client.validateRequest(authToken, twilioSignature, url, params));
Validate Signature of Request (application/json body)Link to code sample: Validate Signature of Request (application/json body)
1
// Get twilio-node from twilio.com/docs/libraries/node
2
const client = require('twilio');
3
4
// Your Auth Token from twilio.com/console
5
const authToken = process.env.TWILIO_AUTH_TOKEN;
6
7
// Store Twilio's request URL (the url of your webhook) as a variable
8
// including all query parameters
9
const url = 'https://example.com/myapp?bodySHA256=5ccde7145dfb8f56479710896586cb9d5911809d83afbe34627818790db0aec9';
10
11
// Store the application/json body from Twilio's request as a variable
12
// In practice, this MUST include all received parameters, not a
13
// hardcoded list of parameters that you receive today. New parameters
14
// may be added without notice.
15
const body = "{\"CallSid\":\"CA1234567890ABCDE\",\"Caller\":\"+12349013030\"}";
16
17
// Store the X-Twilio-Signature header attached to the request as a variable
18
const twilioSignature = 'hqeF3G9Hrnv6/R0jOhoYDD2PPUs=';
19
20
// Check if the incoming signature is valid for your application URL and the incoming body
21
console.log(client.validateRequestWithBody(authToken, twilioSignature, url, body));

For more, including code samples and a description of how Twilio signs requests to your web application see this page on how to validate Twilio requests. The exact algorithm that Twilio uses to calculate the signature header (including whether or not the port number is used) is described in detail.


Understand parameters in signature validation

understand-parameters-in-signature-validation page anchor

Twilio webhooks deliver data to your application in different ways, depending on the request's content type. To validate webhook signatures correctly, you need to know where each type of parameter originates.

Query parameters

query-parameters page anchor

Query parameters appear in the webhook URL after the ? character. Example: https://example.com/webhook?foo=1&bar=2 contains two query parameters—foo and bar.

Because query parameters are already part of the full URL string, they are included automatically when you pass the URL to your validation function. Don't extract query parameters and pass them separately to the function's params argument.

URL encoding in query parameters

url-encoding-in-query-parameters page anchor

Always use the exact URL Twilio used to make the request, including any URL-encoded characters. If you decode or re-encode the URL, signature validation fails.

Query parameters must remain URL-encoded:

https://example.com/webhook?message=hello%20world&type=test%2Bvalue

In this example, %20 (space) and %2B (plus sign) must stay encoded in the URL string that you pass to the validation function.

Form parameters are sent in the POST request body with the content type application/x-www-form-urlencoded. These parameters include webhook-specific fields such as CallSid, From, To, and Body.

You must extract form parameters from the request body and pass them directly to the validation function as key-value pairs. Twilio sorts these parameters alphabetically and appends them to the URL when calculating the signature.

Twilio can also send JSON payloads with the content type application/json. For these requests, Twilio appends a bodySHA256 query parameter to your webhook URL. The parameter value is a SHA-256 hash of the raw JSON request body.

When validating JSON webhooks:

  • Don't extract individual JSON properties or treat them as form parameters.
  • Use your SDK's JSON-specific validation method (for example, validateRequestWithBody) and pass the raw request body string.

The SDK performs two checks:

  1. It verifies that the SHA-256 hash of the raw body matches the bodySHA256 query parameter.
  2. It validates the request signature by including the bodySHA256 value during the calculation.

Tutorials for Validating Incoming Twilio Requests

tutorials-for-validating-incoming-twilio-requests page anchor

Once you've decided to add Twilio request validation to your application, you can follow one of our handy tutorials for your chosen language and web application framework. Do you use something we don't have on this list? Let us know, and we'll try and point you in the right direction.


Webhooks and IP Addresses

webhooks-and-ip-addresses page anchor

Twilio uses a cloud architecture to provide services, and as such, does not have a fixed range of IP addresses that issue webhooks.

When designing your network architecture, you may wish to have one set of servers and a load balancer in a DMZ that receive webhook requests from Twilio, and then proxy those requests to your private network.

For more about Twilio and IP Addresses, please see this support Article: All About Twilio IP Addresses(link takes you to an external page)


Twilio supports HTTP Basic and Digest Authentication. This allows you to password-protect the TwiML URLs on your web server so that only you and Twilio can access them. You may provide a username and password via the following URL format.

https://username:password@www.myserver.com/my_secure_document

For more about how Twilio uses HTTP Authentication for webhook requests, please visit the Security documentation.