Skip to main content

How signatures work

Every webhook delivery includes two headers for signature verification: The signing payload is constructed as:
The HMAC is computed using your webhook endpoint secret as the key.

Verification steps

  1. Extract X-Signature-Timestamp and X-Signature from the request headers
  2. Construct the signing payload: {timestamp}.{raw_body}
  3. Compute HMAC-SHA256 of the signing payload using your webhook secret
  4. Compare the computed signature with X-Signature using constant-time comparison
  5. Optionally, reject requests with a timestamp more than 5 minutes old to prevent replay attacks

Code examples

Common mistakes

Always verify the signature against the raw request body, not a parsed-and-re-serialized version. JSON serialization may reorder keys or change formatting, producing a different signature.
Use hmac.compare_digest (Python), crypto.timingSafeEqual (Node.js), or hmac.Equal (Go). Regular string comparison (==) is vulnerable to timing attacks.
Without timestamp validation, an attacker who intercepts a valid webhook can replay it indefinitely. Reject timestamps older than 5 minutes.