Signing secret
Each webhook endpoint has its own signing secret (a 48-character hex string). You receive it once, in the response toPOST /webhooks:
How Pocketsflow signs a request
For each delivery, Pocketsflow:- Builds the JSON body (your event data with a
webhookIdfield merged in). - Computes
HMAC-SHA256(secret, rawBody)over the exact bytes of that body. - Sends the hex digest in the
X-Pocketsflow-Signatureheader.
The timestamp is sent for your logging and freshness checks but is not
included in the signed content — the signature covers the raw body only (which
already contains
webhookId). Do not add the timestamp to the string you
hash.Verifying the signature
1
Read the raw body
Capture the request body as raw bytes before any JSON parsing or
middleware re-serializes it. In Express, use
express.raw({ type: "application/json" }) for the webhook route.2
Recompute the HMAC
Compute
HMAC-SHA256(secret, rawBody) and hex-encode it, using the signing
secret for that endpoint.3
Compare in constant time
Compare your digest to
X-Pocketsflow-Signature with a timing-safe
comparison (crypto.timingSafeEqual, hmac.compare_digest,
hash_equals). Reject with 400 if they differ.4
Only then parse and process
Parse the JSON, route on
X-Pocketsflow-Event, and process idempotently.Node.js
Freshness (optional but recommended)
ReadX-Pocketsflow-Timestamp and reject deliveries whose timestamp is outside
a reasonable window (for example a few minutes) to blunt replay attempts. Since
the timestamp isn’t signed, treat it as a secondary defense layered on top of
signature verification, not a replacement for it.
Additional defenses
- Serve your endpoint over HTTPS with a valid certificate (Pocketsflow only
delivers to
https://URLs). - Validate
Content-Type: application/jsonand the payload shape before acting. - Respond fast — deliveries time out after 5 seconds. Acknowledge with a
2xxand offload work to a queue. - Restrict inbound access with a firewall/WAF if feasible, and never expose sensitive internal services directly.
Handling secrets safely
- Store secrets in environment variables or a secret manager — never in source control or client-side code.
- Use a distinct endpoint (and therefore secret) per environment; keep test-mode and live-mode endpoints separate.
- Rotate a secret (by recreating the endpoint) if you suspect exposure or change infrastructure ownership.