The signature header
Each delivery carries:t— the timestamp the signature was generated.v1— the signature.
"{t}.{rawRequestBody}" — the t value, a literal dot, then the exact raw bytes of the request body.
How to verify
- Parse
tandv1from theX-Numero-Signatureheader. - Build the signed string:
`${t}.${rawBody}`(use the raw body, before JSON parsing). - Compute
HMAC-SHA256of that string with your subscription’s signing secret, Base64-encode it. - Compare to
v1using a constant-time comparison. - Reject deliveries whose
tis older than your tolerance (e.g. 5 minutes) to prevent replays.
Legacy: a bare-bodyX-Webhook-Signature(HMAC-SHA256 of just the body, Base64) is sent in parallel until 2026-06-26 for back-compat. Migrate toX-Numero-Signature.
Code examples
Node.js
Python
C#
Important
- Verify against the raw request body — before parsing it to JSON.
- Always use a constant-time comparison (
timingSafeEqual/compare_digest/FixedTimeEquals). - Enforce the timestamp tolerance so an intercepted delivery can’t be replayed later.
- Use the envelope
idto dedupe — the same event may be delivered more than once. - Never skip verification in production.