01The scheme
The signature joins five values with a single dot: ${timestamp}.${endpoint_id}.${event_id}.${delivery_id}.${body} — where timestamp is the webhook-timestamp header of this attempt, endpoint_id comes from webhook-id, event_id and delivery_id from their same-named headers, and body is the RAW request body byte-for-byte. The digest is HMAC-SHA256 as lowercase hex, sent as v1=<hex>.
02The three verification rules
- Compare in constant time (crypto.timingSafeEqual) — plain string comparison opens timing attacks.
- Try the current secret first, then the previous one during the 24-hour rotation overlap.
- Reject any request whose timestamp differs from your server clock by more than 300 seconds (5 minutes) — the window kills replay attacks. The platform clock is correct UTC; if your server is hours behind, fix your clock.
COMPLETE YOUR INTEGRATION
