Verify every POST to your webhook URL before you process the body.

Requirements

  1. Read the raw request body bytes (do not re-serialize JSON).
  2. Read signature headers from the delivery (typically webhook-id / svix-id, webhook-timestamp / svix-timestamp, and webhook-signature / svix-signature).
  3. Use the endpoint signing secret from Wazapin (format whsec_…). Store it as a server secret, not in client code.
  4. Reject requests outside the allowed timestamp window (replay protection).
  5. Compare expected and received signatures with a constant-time comparison.
The signing scheme matches the Svix standard used for outbound deliveries. You can use the official Svix libraries or implement the same HMAC steps below.

Node.js

Python

Go

Use github.com/svix/svix-webhooks with your endpoint whsec_ secret, or implement the same signed content: msgID + "." + timestamp + "." + string(body) with HMAC-SHA256 and base64, matching v1 entries in the signature header.

Failure handling

  • Return 403 when the signature is invalid.
  • Return 400 for malformed JSON after verification succeeds.
  • Return 200 for duplicate events after your idempotency check.
Never verify signatures on re-encoded JSON. Always use the raw HTTP body.