Twilio Webhooks — Complete Guide to Event-Driven Communication
In this tutorial, you will learn about Twilio Webhooks. We cover key concepts, practical examples, and best practices to help you master this topic.
Twilio webhooks notify your application of incoming messages, call events, and status changes via HTTP callbacks, enabling event-driven communication workflows without polling Twilio for updates.
What You'll Learn
- Configuring Webhook URLs for Twilio services
- Receiving and validating incoming webhook requests
- Handling message status callbacks and error scenarios
Why It Matters
Without webhooks, you would need to poll Twilio for incoming messages or status changes. Webhooks push events to your application in real time, enabling responsive communication flows.
Real-World Use
When a customer sends an SMS to Durga Antivirus Pro support number, Twilio sends a webhook to the support backend with the message body and sender number. The system auto-replies with the ticket number and routes to an available agent.
flowchart LR
U["User SMS"] --> T["Twilio"]
T -->|"Webhook POST"| W["Your Server"]
W -->|"200 TwiML Response"| T
T -->|"Reply SMS"| U
W --> P["Process Message"]
style W fill:#dbeafe,stroke:#2563eb
Code Examples
from flask import Flask, request, Response
from twilio.twiml.messaging_response import MessagingResponse
app = Flask(__name__)
@app.route('/sms', methods=['POST'])
def incoming_sms():
sender = request.form['From']
body = request.form['Body']
message_sid = request.form['MessageSid']
print(f"Received from {sender}: {body}")
# Auto-reply
resp = MessagingResponse()
resp.message(f"Thanks for reaching out! Your message ({message_sid}) has been received.")
return Response(str(resp), mimetype='text/xml')
app.run(port=5000)
Expected output: Incoming SMS triggers webhook; server replies with confirmation message.
// Express webhook handler with validation
const express = require('express');
const twilio = require('twilio');
const app = express();
app.use(express.urlencoded({ extended: false }));
app.post('/voice', (req, res) => {
// Validate Twilio signature
const isValid = twilio.validateRequest(
authToken,
req.headers['x-twilio-signature'],
'https://yourdomain.com/voice',
req.body
);
if (!isValid) {
return res.status(403).send('Invalid signature');
}
const callSid = req.body.CallSid;
const from = req.body.From;
console.log(`Incoming call from ${from} (SID: ${callSid})`);
// Respond with TwiML
const VoiceResponse = twilio.twiml.VoiceResponse;
const response = new VoiceResponse();
response.say('Thank you for calling Durga Antivirus support.');
response.record({ maxLength: 30, action: '/recording-complete' });
res.type('text/xml');
res.send(response.toString());
});
app.listen(5000);
Expected output: Incoming call triggers signature-validated webhook; caller hears a recorded message.
# Status callback webhook for delivery tracking
from flask import Flask, request
app = Flask(__name__)
@app.route('/status', methods=['POST'])
def message_status():
message_sid = request.form['MessageSid']
status = request.form['MessageStatus']
error_code = request.form.get('ErrorCode', None)
print(f"Message {message_sid}: {status}")
if error_code:
print(f"Error: {error_code}")
if status == 'delivered':
update_delivery_status(message_sid, 'delivered')
elif status == 'failed':
handle_failure(message_sid, error_code)
return '', 200
Expected output: Delivery status updates sent via webhook as the message progresses from queued to sent to delivered.
Common Mistakes
1. Not Validating Twilio Signatures
Without signature validation, anyone can fake Twilio webhooks. Always validate x-twilio-signature headers.
2. Returning Non-200 Status Codes
Twilio retries non-200 responses. Return 200 immediately and Process asynchronously to avoid duplicates.
3. Hardcoding Webhook URLs
Webhook URLs must be publicly accessible and use HTTPS. Use environment variables for configuration.
4. Not Responding to TwiML Prompt
For voice webhooks, Twilio expects a TwiML response within 15 seconds. Respond promptly or the call drops.
5. Ignoring Status Callbacks
Message status callbacks provide delivery confirmation. Always implement them to detect undelivered messages.
Practice Questions
- How does Twilio validate webhook authenticity?
- Why should webhooks return a 200 response immediately?
- What is TwiML and when is it required?
- How do message status callbacks work?
- What happens if your webhook endpoint takes too long to respond?
Answers:
- Twilio signs each request with your auth token; validate using the x-twilio-signature header.
- Non-200 responses cause Twilio to retry, potentially creating duplicate processing.
- TwiML is XML markup that tells Twilio what to do next (for voice/SMS responses).
- Twilio sends POST requests to your status URL as the message transitions through states (queued, sent, delivered, failed).
- For voice, the call times out after 15 seconds. For SMS, the webhook may be retried.
Challenge: Build an SMS support system with Twilio webhooks: incoming messages create tickets, auto-reply with acknowledgment, track delivery status via status callbacks, and escalate if delivery fails.
FAQ
Mini Project
Build a webhook receiver that handles incoming SMS, voice, and status callbacks. Validate each request using Twilio's signature validator, process each event type differently, and log all events to a database with delivery status tracking.
What's Next
Learn about Sending SMS with Twilio for outbound messaging, or explore Receiving SMS with Twilio for inbound message handling.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro