Skip to main content
Usertick signs every delivery the Standard Webhooks way. Three headers carry the signature data: The signature is an HMAC-SHA256 over {webhook-id}.{webhook-timestamp}.{raw body}. The key is your secret without its whsec_ prefix, base64 decoded. To verify a delivery:
  1. To block replayed requests, refuse a timestamp more than 5 minutes away from your server’s clock.
  2. Compute the signature over the id, the timestamp and the raw body.
  3. Accept the delivery when any v1 signature in the header matches the computed one, comparing in constant time.
Sign the raw bytes of the body exactly as they arrived, before any JSON parsing, because parsed and re-serialized JSON rarely matches byte for byte. If your framework parses the body for you, keep a raw copy.
The Standard Webhooks project publishes verification libraries for Node, Python, Go and other languages. They take the whsec_ secret and the three headers as they are, for example new Webhook(secret).verify(rawBody, headers) in the standardwebhooks npm package.

Verification rules

  • Compare in constant time (timingSafeEqual, compare_digest), never with ==.
  • Check the timestamp. Without the check, a captured delivery could be sent again later and still verify.
  • Keep one secret per webhook on your server. The dashboard shows the secret when a webhook is created or its secret is rotated, and the API returns it in the subscribe response.
  • Refuse a mismatch with 401 and don’t process the body. A mismatch points to a bug in raw body handling, or to someone else calling your endpoint.
  • Drop duplicates by webhook-id. It stays the same on every retry and resend of a delivery.