X-Notealy-Signature header so your receiver can confirm Notealy sent it and that the payload was not tampered with in transit.
Header format
t— unix timestamp (seconds) at signing timev1— hex-encoded HMAC-SHA256 of"{t}.{rawBody}", keyed by your subscription’s signing secret
Verifying with @notealy/sdk
The TypeScript SDK ships the verifier as a tree-shakeable subpath, so you don’t have to roll the HMAC math yourself:
verifyWebhook throws WebhookVerificationError (with a discriminating code) on any mismatch — never returns a falsy value, so use a try/catch. The same function enforces a 5-minute timestamp tolerance by default; override with options.toleranceSec.
See SDKs for setup.
Verifying manually (Node.js)
- Use the raw body, not a re-serialized one. Express middlewares like
express.json()consume the buffer; capture it with averifycallback or usebody-parserraw mode for the webhook route. - Compare in constant time with
timingSafeEqual(or your language’s equivalent) to avoid timing attacks. - Reject stale signatures — we recommend a 5-minute tolerance window. Replay attempts older than that should be rejected even if the HMAC matches.
- Rotate periodically. Use Rotate signing secret in the dashboard; the new secret is shown once and old signatures stop validating immediately.