Skip to main content

Why verify

Webhook endpoints are public URLs. Without verification, anyone who discovers your endpoint URL could send fake events. Signature verification proves that a delivery genuinely came from Bluvo.

How it works

Every webhook delivery is signed with your endpoint’s secret using HMAC-SHA256:
  1. Bluvo concatenates the timestamp and JSON payload: ${timestamp}\n${payload}
  2. Computes the HMAC-SHA256 of that string using your webhook secret
  3. Base64-encodes the result and sends it in the X-Webhook-Signature header

Headers

Verification example

Timestamp validation

Bluvo does not enforce a maximum age on deliveries. We recommend your receiver rejects any payload where X-Webhook-Timestamp is more than 5 minutes from the current time. This prevents replay attacks where an attacker captures a valid delivery and resends it later.

Secret rotation

Bluvo supports zero-downtime secret rotation with a 3-phase lifecycle: During rotation, verify against both the new and old secrets:
To rotate a secret in the Portal:
  1. Navigate to Settings > Webhooks and select your endpoint
  2. Click Rotate Secret — this creates a new pending secret
  3. Update your server with the new secret
  4. Click Activate Secret to promote it to active
Only one pending secret is allowed at a time. You must activate or let it expire before creating another.

Common mistakes

If you parse the JSON body before computing the signature, the re-serialized string may differ from the original (key ordering, whitespace). Always use the raw request body bytes.
The signature is Base64-encoded, not hex. Make sure your HMAC output is encoded as Base64 before comparing.
Using === instead of timingSafeEqual (Node.js) or hmac.compare_digest (Python) leaks timing information that can be exploited to forge signatures.