How to Test Twilio Webhooks
Inspect Twilio SMS, voice, and status callback payloads in real time — catch every field Twilio sends before your handler touches it.
TL;DR: Twilio webhooks are form-encoded POST requests (not JSON). Generate a Requex URL, paste it as the webhook URL in your Twilio number settings, send a test SMS or make a call, and inspect the form fields in Requex.
What Twilio Sends
This is the most important thing to know about Twilio webhooks: Twilio sends application/x-www-form-urlencoded POST requests — not JSON. Many developers get tripped up by this when writing handlers, because they reach for req.body.MessageSid and get undefined because their body parser is expecting JSON.
A typical incoming SMS webhook from Twilio sends form fields like these:
MessageSid=SMxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx AccountSid=ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx From=+14155551234 To=+14155559876 Body=Hello from the test NumMedia=0 NumSegments=1 SmsStatus=received ApiVersion=2010-04-01
When you view this in Requex, the Body tab will show the raw URL-encoded string and the parsed form fields will appear in the query section. The Content-Type header will read application/x-www-form-urlencoded.
Types of Twilio Webhooks
| Type | When It Fires | Key Fields |
|---|---|---|
| SMS Incoming | Someone sends an SMS to your Twilio number | From, Body, MessageSid |
| SMS Status Callback | Outbound SMS status changes (sent, delivered, failed) | MessageStatus, MessageSid |
| Voice Incoming | Someone calls your Twilio number | CallSid, From, CallStatus |
| Voice Status Callback | Call status updates (ringing, in-progress, completed) | CallStatus, Duration, CallSid |
Step 1: Generate Requex Endpoint
Open requex.me in your browser. A unique public URL is created immediately — no sign-up needed. Copy it. It looks like:
https://requex.me/hook/a1b2c3d4-e5f6-7890-abcd-ef1234567890
Keep this tab open. Incoming requests appear in real time, so you can watch Twilio hit your endpoint live.
Step 2: Set Your Twilio Webhook URL
In the Twilio Console, navigate to Phone Numbers → Manage → Active numbers and click the number you want to test. Scroll down to the Messaging or Voice section and paste your Requex URL into the relevant webhook field:
- SMS: Set "A message comes in" → Webhook → paste Requex URL.
- SMS status callbacks: Set "Message status changes" → Webhook → paste Requex URL.
- Voice: Set "A call comes in" → Webhook → paste Requex URL.
Make sure the HTTP method dropdown next to each field is set to HTTP POST. Click Save configuration.
Step 3: Send a Test SMS
Send an SMS to your Twilio number from any phone. Twilio will immediately POST the request to your Requex URL. You can also use the Twilio API to send a test message programmatically:
# Send a test SMS via Twilio API (triggers status callback) curl -X POST https://api.twilio.com/2010-04-01/Accounts/ACxxx/Messages.json \ --data-urlencode "Body=Test message" \ --data-urlencode "From=+14155551234" \ --data-urlencode "To=+14155559876" \ --data-urlencode "StatusCallback=https://requex.me/hook/YOUR-ID" \ -u ACxxx:your_auth_token
Twilio will fire the status callback to your Requex URL as the message moves through sent → delivered states.
Step 4: Inspect in Requex
Open the Requex tab and click the incoming request. Key things to verify:
- Content-Type header: Confirm it is
application/x-www-form-urlencoded— this tells you to use a form body parser in your handler, not JSON. - X-Twilio-Signature header: Twilio includes a signature on every request — copy this value for signature verification testing.
- Form fields: Expand the body to see all key-value pairs Twilio sent, including
MessageSid,From,Body, andNumMedia.
Use this exact field list to build your handler — you will know precisely which fields are always present versus conditionally included.
Twilio Signature Verification
Twilio signs every webhook request with the X-Twilio-Signature header. The signature is an HMAC-SHA1 of the full request URL plus sorted POST parameters, signed with your Twilio Auth Token. Verify it in production to prevent spoofed requests:
// Node.js / Express — Twilio signature verification
const twilio = require('twilio');
app.post('/api/webhooks/twilio/sms', (req, res) => {
const twilioSignature = req.headers['x-twilio-signature'];
const url = 'https://yourdomain.com/api/webhooks/twilio/sms';
const params = req.body; // must be parsed as urlencoded
const isValid = twilio.validateRequest(
process.env.TWILIO_AUTH_TOKEN,
twilioSignature,
url,
params
);
if (!isValid) {
return res.status(403).send('Forbidden');
}
// Handle the SMS
const twiml = new twilio.twiml.MessagingResponse();
twiml.message('Got your message!');
res.type('text/xml');
res.send(twiml.toString());
});Note that the URL used for validation must exactly match what Twilio posted to — including the scheme, domain, path, and any query parameters. A mismatch in URL is the most common cause of signature verification failures.
Common Twilio Webhook Issues
| Issue | Cause | Fix |
|---|---|---|
| Signature verification fails | URL used for signing does not match the actual request URL (e.g., http vs https, missing port) | Log the full request URL in your handler and compare it exactly to what you pass to validateRequest |
Body fields are undefined | Body parser is configured for JSON only; form-encoded bodies are not parsed | Add express.urlencoded({ extended: false }) middleware before your webhook route |
| Webhook URL returns a non-200 status | Your handler is crashing or returning an error; Twilio expects 200 with valid TwiML for voice/SMS | Return a minimal TwiML response (<Response/>) even for webhooks you do not act on |
Inspect Your Twilio Payloads Live
Generate a free Requex endpoint and see every field Twilio sends — before writing a single line of handler code.
Open Requex →Related guides
Start Testing Webhooks Now
Generate your unique URL and test webhooks instantly. Free, no signup.
Open Webhook Tester →