Signature scheme
Every delivery carries the header:tis the Unix time in seconds when this attempt was sent.- Each endpoint has two secrets.
s1is computed with the first secret ands2with the second. - Each signature is the lower-case hex HMAC-SHA256 of
<raw body>.<t>: the exact request bytes before any JSON parsing, a dot, then the value oft.
t more than 5 minutes away from your clock. Deduplicate on the body’s event.id, because retries and replays reuse it with a fresh t.
Secrets are shown once, when you create the endpoint and when you rotate a secret.
No library needed
No library is needed: the scheme is an HMAC-SHA256 that every platform has. There are no official SDKs in v1; the samples below are complete verifiers you can copy. They read the secrets from the environment variablesWEBHOOK_FIRST_SECRET and WEBHOOK_SECOND_SECRET (during a rotation one of them may be unset) and take an optional now (Unix seconds) so you can run the test vector. Two rules matter in every language:
- Read the raw body bytes. Re-serialising parsed JSON changes the bytes and breaks the signature.
- Compare in constant time.
Verify manually
Test vector
Use these documentation values to test your verifier.t is in the past, so pass now = 1792656000 (the vector’s t) when you run it.
Raw body (403 bytes, UTF-8, one line, no trailing newline):
Secret rotation
Rotate one secret at a time, so every delivery stays verifiable:- Call
POST /partner/v1/webhook-endpoints/{webhookEndpointId}:rotate-first-secret(dashboard users need a recent sign-in). The response contains the newfirstSecret, once. - Update your receiver to accept the new first secret and the unchanged second secret. Deliveries in between still verify through
s2. - Later, rotate the second secret the same way with
:rotate-second-secret.