Every webhook request from Paxos Labs includes a cryptographic signature that lets you confirm the request is authentic and hasn’t been tampered with. Always verify signatures before processing webhook payloads.Documentation Index
Fetch the complete documentation index at: https://developers.paxoslabs.com/llms.txt
Use this file to discover all available pages before exploring further.
Headers
Each webhookPOST request includes these headers:
| Header | Example | Description |
|---|---|---|
X-PAXOS-LABS-TIMESTAMP | 2026-04-07T18:06:40.000Z | RFC 3339 UTC timestamp of event creation. Concatenated with the payload before signing. |
X-PAXOS-LABS-SIGNATURE | a3f2...9b01 | HMAC-SHA256 hex digest of the timestamp and payload |
Content-Type | application/json | Always JSON |
User-Agent | PaxosLabs-Webhooks/1.0 | Identifies the sender |
Signature Scheme
X-PAXOS-LABS-SIGNATURE contains the raw hex-encoded HMAC-SHA256 digest. The timestamp used in the HMAC computation is sent in the separate X-PAXOS-LABS-TIMESTAMP header.
Verification Algorithm
Read the timestamp and signature headers
Read
X-PAXOS-LABS-TIMESTAMP for the RFC 3339 timestamp and X-PAXOS-LABS-SIGNATURE for the hex signature.Check the timestamp
Reject requests where the timestamp is more than 5 minutes from your server’s current time. This protects against replay attacks.
Construct the signed payload
Concatenate the timestamp, a literal period (
.), and the raw request body (the exact bytes received — do not parse and re-serialize):Compute the expected signature
Calculate an HMAC-SHA256 using your endpoint’s signing secret as the key and the constructed string as the message. Hex-encode the result.
Implementation Examples
- Node.js
- Python
- Go
Use
timingSafeEqual instead of === to prevent timing side-channel attacks.Best Practices
Always verify before processing
Always verify before processing
Never process a webhook payload without verifying the signature first. An unverified payload could be forged by a malicious actor.
Use constant-time comparison
Use constant-time comparison
Standard string comparison (
===, ==) leaks timing information that attackers can exploit. Always use timingSafeEqual (Node.js), hmac.compare_digest (Python), or hmac.Equal (Go).Enforce a replay window
Enforce a replay window
Reject events where the timestamp is more than 5 minutes from your server’s clock. This prevents captured requests from being replayed later.
Use the raw request body
Use the raw request body
Compute the HMAC over the exact bytes received in the HTTP body. Parsing to JSON and re-serializing can change whitespace or key ordering, producing a different signature.
Store secrets securely
Store secrets securely
Keep your signing secret in a secrets manager or encrypted environment variable — never hard-code it or commit it to source control.
Respond quickly
Respond quickly
Return a
2xx status code within 10 seconds. Move heavy processing to a background queue so the webhook handler returns immediately.Handle duplicates idempotently
Handle duplicates idempotently
Use the event
id field to deduplicate. Store processed event IDs and skip any that you’ve already handled.Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Signature mismatch | Re-serialized body instead of raw bytes | Use the raw HTTP body for HMAC computation |
| Timestamp rejection | Server clock drift | Sync your server with NTP; widen tolerance if needed |
401 on test events | Wrong secret | Verify you’re using the correct pxlwh_ secret for this endpoint |
| Secret lost | Secret was not saved at creation | Delete the endpoint and create a new one |