The webhook signature headers
The secret is shown on the endpoint’s page in the dashboard and starts with
whsec_. Each endpoint has its own.
Verifying the signature with the Svix library
The simplest route. The library checks the signature, tolerates a five-minute clock skew, and rejects replays outside that window.npm i svix, pip install svix, or go get github.com/svix/svix-webhooks/go.
Verifying the webhook signature by hand
If you would rather not add a dependency, the algorithm is short:- Strip the
whsec_prefix from the secret and base64-decode the rest. That is the HMAC key. - Build the signed content:
${svix-id}.${svix-timestamp}.${raw body}. - Compute HMAC-SHA256 over the signed content with the key and base64-encode the result.
- Compare it, in constant time, against each
v1,...entry insvix-signature. One match is enough. - Reject if
svix-timestampis more than five minutes from now.
Rotating a webhook signing secret
Rotate from the endpoint’s page in the dashboard. For a grace period, deliveries are signed with both the old and the new secret andsvix-signature carries two v1 entries. Deploy the new secret to your handler during that window; a handler that accepts any matching entry keeps working throughout.

