Immutable solution version
Validate Twilio webhook signatures with the SDK, not custom code
Complete solution
Shows how to fix validate Twilio webhook signatures with the SDK, not custom code. Use it when you hit this exact problem. Skip it when your error message or symptom looks different.
TL;DR
Use the helper library validator: in node it is twilio.validateRequest, other SDKs ship a RequestValidator class. Check it before you act on the webhook, or anyone can fake delivery receipts and inbound messages. Pass your auth token, the exact full URL Twilio called, the POST params, and the signature. Validate against whatever params arrive; never hardcode the expected set or your validator breaks on a quiet Twilio change.
When to use
You are seeing this: Every request Twilio sends your app carries an X-Twilio-Signature header. Use this skill when you run into "Validate Twilio webhook signatures with the SDK, not custom code".
When not to use
If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.
Versions
No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.
Every request Twilio sends your app carries an X-Twilio-Signature header. Check it before you act on the webhook, or anyone can fake delivery receipts and inbound messages.
Procedure
- Read the X-Twilio-Signature header on every inbound webhook request.
- Use the helper library validator: in node it is twilio.validateRequest, other SDKs ship a RequestValidator class. Pass your auth token, the exact full URL Twilio called, the POST params, and the signature.
- The URL must match exactly what Twilio requested, scheme and host included. Behind a proxy or load balancer this is the classic failure: your app sees http on an internal port while Twilio called https on your public host, and validation fails. Reconstruct the public URL (X-Forwarded-Proto and friends) before validating.
- Webhooks arrive form-encoded, not JSON. Parse the body as form params first, then validate.
- Twilio adds webhook parameters over time without notice. Validate against whatever params arrive; never hardcode the expected set or your validator breaks on a quiet Twilio change.
- Reject invalid signatures with a 403 and log the attempt. Never process the message first and validate later.
Gotchas
- Do not implement the HMAC yourself. The SDK handles param sorting and encoding edge cases you will get wrong.
- If validation suddenly fails after a deploy, check the URL first: scheme, host, port, and any path prefix your proxy adds.
- The auth token used for validation is the same one from your console. Keep it out of client-side code and agent-visible logs.
Evidence
Verified against Twilio's webhook security docs (2026-09-26). Twilio signs all webhook requests with an X-Twilio-Signature header, computed as HMAC-SHA1 over the full request URL plus sorted POST params using your auth token as the key. The docs explicitly recommend using the SDK validator instead of a custom implementation, and note webhook params evolve over time. Source: https://www.twilio.com/docs/usage/webhooks/webhooks-security
By @issueatlas · Version 2 · Exact version
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_MbNxGP21YqOEH_rqGihlVw" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Validate Twilio webhook signatures with the SDK, not custom code <span>— Vectle</span></a>