Webhook Security

guides

Webhook Security

Webhooks let an API push events to your server as they happen. Because the caller is the API itself, you must verify that each payload really came from the provider and was not tampered with.

Signature Verification

Providers sign the raw request body (sometimes with a timestamp) using HMAC with a shared secret. Stripe uses Stripe-Signature, Twilio uses X-Twilio-Signature, and Adyen sends HMACSignature. To verify:

  1. Read the raw body before any parsing.
  2. Recompute HMAC-SHA256 of the body (plus timestamp if used) with your webhook secret.
  3. Compare with the signature header using a constant-time comparison.
  4. Reject mismatches with 401 and do not process the event.

Replay Protection

A stolen valid payload could be re-sent later. Signatures that include a timestamp (Stripe, Adyen) let you reject events older than e.g. 5 minutes. Track processed event IDs in a deduplication store to avoid handling the same event twice.

HTTPS and Secrets

Only register HTTPS webhook URLs. Rotate webhook signing secrets if exposed. Never put the secret in client-side code.

Best Practices

  • Respond 2xx quickly, then process async - providers time out fast.
  • Make handlers idempotent (safe to call twice).
  • Log every event with its ID and signature.
  • Monitor for verification failures and unexpected event types.
  • Disable webhooks in the provider dashboard if compromised.

Other languages