Webhooks · Verify signatures
Verify webhook signatures
Authenticate each webhook request with its timestamp, exact raw body, and endpoint secret before you parse or process the event.
Webhook signature verification is coming soon
This page previews the planned design. It is not available in the API yet, so the examples below will not work against it today.
Live POS webhooks are not signed today
The POS webhooks delivered to your callback URL do not carry a signature, signing secret, or timestamp header. Everything below describes the planned design, so do not make verification a required step in your integration yet. See Webhook events for what is available now.
Signature headers
X-Webhook-Signature
v1=<hex HMAC-SHA256 digest>
X-Webhook-Timestamp
Unix time in seconds, for example 1758641050
X-Webhook-Id
Event ID, for example evt_demo_01
Keep the raw request body
Read the exact UTF-8 bytes received from the network. JSON parsing, whitespace normalization, character conversion, or re-serialization changes the signed payload.
Verify before parsing
Disable middleware that consumes or mutates the body on the webhook route. Never compute the digest from JSON.stringify(parsedBody).
Canonical verification sequence
Success and failure outcomes
Verified · 200
Acknowledge and enqueue once.
Invalid signature · 401
Reject without processing.
Stale timestamp · 401
Reject as a possible replay.
Malformed headers · 400
Reject and log the event ID only.
Constant-time comparison
Confirm both digests have the same length, then use a platform timing-safe equality function. Some of these functions throw on unequal lengths, and a normal string equality check can leak comparison timing.
Timestamp tolerance and replay protection
The planned tolerance is a fixed 300 seconds (five minutes), applied in both directions and measured against a synchronized server clock. Persist event IDs and reject replays of events you already processed.
Key rotation
During a controlled rotation, accept signatures from the new and previous endpoint secrets for a short overlap. Try each active secret without logging it, then remove the previous secret after traffic is verified.
Rotate without downtime
Store versioned secrets in a managed secret store and record which version verified the request—not the secret value.
Common implementation mistakes
Troubleshooting
Every request fails
The secret matches the one issued for the endpoint.
Intermittent failures
Body middleware and encoding are deterministic.
Stale timestamp
NTP synchronization on your server.
Duplicate processing
Persist the event ID before side effects.