Routeur-Signature header: an HMAC-SHA256 of the delivery’s timestamp and raw body, keyed with your subscription’s signing secret. Recompute it over the exact bytes you received, compare in constant time, and reject timestamps far from your clock. The functions below were checked against a signature produced by Routeur’s own signing code.
Headers
The header matches
^t=[0-9]+,v1=[0-9a-f]{64}$. There is one signature per delivery; there is no list of alternatives and no other version than v1.
The algorithm
- Take the raw request body as bytes, before any JSON parsing or re-encoding.
- Build the signing string: the decimal
t, a single., then the body bytes. - Compute HMAC-SHA256 with the key set to your secret as ASCII, the whole string including the
whsec_prefix. - Hex-encode the digest in lowercase and compare it with
v1using a constant-time comparison. - Reject the delivery when
|now − t|is larger than your tolerance. Five minutes is a sensible default.
Worked example
With this secret and timestamp:body.json and reproduce the digest from a shell:
Code
Each function takes the raw body, the header value, the secret and a tolerance, and returns whether the delivery is authentic and recent. Thenow argument exists so you can test against the worked example with a fixed clock; leave it out in production.
In a handler
Read the body before anything parses it, verify, acknowledge, then do the work.Timestamps and replay
tis set when each attempt is signed, not when the event was created. A retry can arrive up to about an hour aftercreated_atwith a fresht, so comparetwith your clock, never withcreated_at.- A captured delivery can be replayed for as long as your tolerance allows. To close that window, record every
Routeur-Deliveryid you accept and ignore repeats; the id is also what makes retries idempotent. - Keep your endpoint’s clock synchronized. If you must accept a wider skew, widen the tolerance rather than dropping the check.
Related
- Webhooks overview: delivery headers, retries and endpoint requirements.
lead.executable: the body being signed.ping: a signed test delivery to check your verifier end to end.