Secure webhooks
Maintain secure communication between your app and Twilio using encryption and authentication for your webhooks.
To secure your web app, serve your web app using the Secure HyperText Transport Protocol (HTTPS). Twilio won't connect to an HTTPS URL with a self-signed certificate. Use a certificate from a provider such as Let's Encrypt.
The Twilio Console always validates SSL certificates.
Twilio signs all HTTP requests to your app with an X-Twilio-Signature HTTP header.
Before responding to a webhook request, your web app should check for this HTTP header.
To create this signature, Twilio combines, then hashes, the following data:
- Your account auth token
- The
x-twilio-signatureheader value from Twilio - The Webhook URL set in Twilio
- All request parameters
Twilio hashes the signature with the HMAC-SHA1 hashing algorithm using your account auth token as the secret key.
Webhook parameters can change
The parameters included in webhook events vary by channel and event type and might change in the future. Twilio occasionally adds parameters without advance notice. Your integration with Twilio webhooks must support evolving parameter sets for signature validation. Twilio recommends using the provided signature validation library from a Twilio SDK. Don't implement your own signature validation.
1// Get twilio-node from twilio.com/docs/libraries/node2const client = require('twilio');34// Your Auth Token from twilio.com/console5const authToken = process.env.TWILIO_AUTH_TOKEN;67// Store Twilio's request URL (the url of your webhook) as a variable8const url = 'https://mycompany.com/myapp';910// Store the application/x-www-form-urlencoded parameters from Twilio's request as a variable11// In practice, this MUST include all received parameters, not a12// hardcoded list of parameters that you receive today. New parameters13// may be added without notice.14const params = {15CallSid: 'CA1234567890ABCDE',16Caller: '+12349013030',17Digits: '1234',18From: '+12349013030',19To: '+18005551212',20};2122// Store the X-Twilio-Signature header attached to the request as a variable23const twilioSignature = 'Np1nax6uFoY6qpfT5l9jWwJeit0=';2425// Check if the incoming signature is valid for your application URL and the incoming parameters26console.log(client.validateRequest(authToken, twilioSignature, url, params));
1// Get twilio-node from twilio.com/docs/libraries/node2const client = require('twilio');34// Your Auth Token from twilio.com/console5const authToken = process.env.TWILIO_AUTH_TOKEN;67// Store Twilio's request URL (the url of your webhook) as a variable8// including all query parameters9const url =10'https://example.com/myapp?bodySHA256=5ccde7145dfb8f56479710896586cb9d5911809d83afbe34627818790db0aec9';1112// Store the application/json body from Twilio's request as a variable13// In practice, this MUST include all received parameters, not a14// hardcoded list of parameters that you receive today. New parameters15// may be added without notice.16const body = '{"CallSid":"CA1234567890ABCDE","Caller":"+12349013030"}';1718// Store the X-Twilio-Signature header attached to the request as a variable19const twilioSignature = 'hqeF3G9Hrnv6/R0jOhoYDD2PPUs=';2021// Check if the incoming signature is valid for your application URL and the incoming body22console.log(23client.validateRequestWithBody(authToken, twilioSignature, url, body)24);
To learn more about how Twilio signs requests to your app, see Validating Requests.
Twilio webhooks deliver data to your app based on the content type of the request. To validate webhook signatures, prepare to ingest all three parameter types: query, form, and body.
Query parameters appear in the webhook URL after the ? character.
For example: The URL https://example.com/webhook?foo=1&bar=2 contains two query parameters: foo and bar.
As query parameters comprise part of the full URL, they get passed your validation function URL. Never extract query parameters and pass them separately to the function's params argument.
When making a webhook request, use the exact URL from Twilio including any URL-encoded characters. If you decode or re-encode the URL, signature validation fails.
The POST request body includes form parameters using the content-type application/x-www-form-urlencoded. These parameters include webhook-specific fields such as CallSid, From, To, and Body.
Extract the form parameters from the request body and pass them to the validation function as a collection of name and value pairs, such as a dictionary or hash map. Twilio sorts these parameters alphabetically and appends them to the URL when calculating the signature. For a working example in your language, see the signature validation code samples.
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:
- It verifies that the SHA-256 hash of the raw body matches the
bodySHA256query parameter. - It validates the request signature by including the
bodySHA256value during the calculation.
To add Twilio request validation to your app, follow one of the following tutorials for your preferred language and framework.
- Node.js / Express
- C# / ASP.NET Core
- C# / ASP.NET
- C# / ASP.NET WEB API
- Java / Servlets
- Python / Django
- Python / Flask
- Python / Amazon Web Services Lambda
- PHP / Lumen
- Ruby / Sinatra
- Go / Gin
Twilio provides services through cloud architecture. This results in Twilio not having a fixed range of IP addresses that issue webhooks.
When designing your network architecture, you may want to have one set of servers and a load balancer in a DMZ that receive webhook requests from Twilio. You can then proxy those requests to your private network.
To learn more about Twilio and IP addresses, see All About Twilio IP Addresses.
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
To learn more about how Twilio uses HTTP authentication for webhook requests, see the Security guide.