Pandabase is moving to a replay-resistant webhook signature scheme. The new signature is sent on every delivery alongside the legacy one, so you can migrate at your own pace. The legacy header will be removed on a future date — you’ll receive at least 60 days’ notice.Documentation Index
Fetch the complete documentation index at: https://docs.pandabase.io/llms.txt
Use this file to discover all available pages before exploring further.
What’s changing
Legacy (X-Pandabase-*) | New (Webhook-*) | |
|---|---|---|
| Signature header | X-Pandabase-Signature | Webhook-Signature |
| Timestamp header | X-Pandabase-Timestamp | Webhook-Timestamp |
| Idempotency header | X-Pandabase-Idempotency | Webhook-Id |
| Signed string | rawBody | ${timestamp}.${rawBody} |
| Replay protection | None | 5-minute freshness window enforced by you |
| Algorithm | HMAC-SHA256, hex | HMAC-SHA256, hex |
| Secret | Your existing webhook secret | Same secret — no rotation needed |
Migrate your endpoint
Step 1: Read the new headers
ReadWebhook-Signature and Webhook-Timestamp from the request. Headers are case-insensitive — most frameworks lowercase them.
Step 2: Construct the signed payload
Concatenate the timestamp, a literal., and the raw request body. Hash the bytes your server received — do not re-serialize a parsed JSON object.
express.raw(), fastify-raw-body, request.body in Django, c.req.raw.text() in Hono.
Step 3: Compute the expected signature
Hex-encoded HMAC-SHA256 with your webhook secret as the key.Step 4: Compare in constant time
Always usetimingSafeEqual / hmac.compare_digest. Length-check first — timingSafeEqual throws on unequal-length buffers in Node.
Step 5: Reject stale timestamps
Reject deliveries older than 5 minutes. This step is what actually prevents replay — without it, the timestamp binding gives you nothing.Verify signatures
Example delivery
A delivery now carries both header sets:Webhook-Timestamp is milliseconds since Unix epoch. Webhook-Signature is hex-encoded HMAC-SHA256.
Test your integration
Send a test delivery from the dashboard (open your webhook → Send test event) or via the API:2xx, both signatures verified. The delivery appears in your webhook’s delivery log immediately.
Pitfalls
- Signing only the body. This is the legacy behavior. The new signature requires
${timestamp}.${rawBody}. - Skipping the freshness check. The signature alone does not stop replay. The 5-minute window is load-bearing.
- Hashing a re-serialized body. Whitespace, key order, and number formatting all change. Hash the raw bytes.
- Comparing with
==or===. UsetimingSafeEqual/hmac.compare_digest. - Case-sensitive header lookup. Read
webhook-signature(lowercase) when in doubt. - Clock skew. A drift larger than 5 minutes between your server and Pandabase will reject valid events. Keep hosts NTP-synced.
Rollout timeline
| Phase | Status |
|---|---|
| Both headers sent on every delivery | Now |
X-Pandabase-* deprecation announcement | Future — minimum 60 days notice |
X-Pandabase-* removed | After deprecation window |
FAQ
Do I need to rotate my webhook secret?
Do I need to rotate my webhook secret?
No. The same secret signs both formats. Rotate only if you suspect compromise.
My existing verifier still works. Will it break?
My existing verifier still works. Will it break?
No. The legacy header is still sent. You stay on the legacy format — and the replay risk — until you migrate.
Can I verify both during a transition?
Can I verify both during a transition?
Yes. Accept the request if either signature verifies. Switching to the new format only is preferred, since accepting the legacy format keeps the replay window open.
Is this Standard Webhooks?
Is this Standard Webhooks?
The header names match Standard Webhooks (
webhook-id, webhook-timestamp, webhook-signature). The signature value is hex HMAC-SHA256 — Standard Webhooks uses base64 with a v1, prefix. To verify with a generic Standard Webhooks library, set the encoding to hex or use the snippets above.The Webhook-Id header looks like X-Pandabase-Idempotency. Should I check it?
The Webhook-Id header looks like X-Pandabase-Idempotency. Should I check it?
Yes — use it to dedupe. Failed deliveries retry up to 5 times with exponential backoff; without idempotency you may process the same event twice.
