Use this file to discover all available pages before exploring further.
Every webhook delivery includes a Zest-Signature header that lets you authenticate the request before processing it. The scheme is HMAC-SHA256 over the timestamped raw body, modelled on Stripe’s signing format.
Compare v1 to expected in constant time. Reject on mismatch.
The signing secret is the plaintext value of the whsec_<hex> string Zest issued you. Zest stores it AES-256-GCM-encrypted at rest and never logs it.
Compare bytes, not strings. Use hmac.compare_digest in Python or crypto.timingSafeEqual in Node. A naive == comparison leaks length/timing information.
Computing HMAC over the parsed body, not the raw bytes
Most JSON middleware mutates whitespace and key order. The signature is computed over the exact bytes Zest sent — verify before any parsing. Use express.raw() in Node, await request.body() in FastAPI/Starlette.
Forgetting the period separator
The signed payload is <t>.<body>, not <t><body>. Drop the period and every signature mismatches.
String comparison instead of constant-time
== reveals timing-side-channel info. Always use hmac.compare_digest / crypto.timingSafeEqual.
No replay-window check
Without a window check, a captured request can be replayed forever. Reject if |now - t| > 300s.