Skip to main content
Your endpoint URL is not a secret. Anyone who discovers it can send it a convincing looking payload, so verify the signature before you act on one.

The header

The signed message is the timestamp, a full stop, then the raw request body:
Sign that with your endpoint’s whsec_ secret and compare the result to v1.
Sign the bytes exactly as received. Parsing JSON and re-serialising it changes key order and whitespace, which changes the signature. Capture the raw body before any middleware consumes it.

Two checks, not one

Compare in constant time. A normal string comparison returns as soon as it finds a mismatched byte, and that timing difference is enough to recover a valid signature one byte at a time. Reject an old timestamp. The timestamp is inside the signed message, so it cannot be altered without breaking the signature. That is what makes a replay detectable: a captured delivery keeps its original t forever. Five minutes is a reasonable tolerance.

Examples

Rotating a secret

There is no rotation endpoint. Create a second endpoint with the same URL, move your verification to accept either secret, then delete the original. That keeps you receiving deliveries throughout.