Overview
All Daya Pro webhooks include anX-Webhook-Signature header containing an HMAC-SHA256 signature of the payload with a sha256= prefix. Always verify this signature to ensure the webhook came from Daya.
Signature Header
Additional Headers
Daya also sends these headers with every webhook request:Verification Algorithm
- Get raw request body as string
- Compute HMAC-SHA256 using your webhook secret
- Strip the
sha256=prefix fromX-Webhook-Signatureheader - Compare computed signature with the extracted signature
- Use timing-safe comparison to prevent timing attacks
Implementation Examples
Important Notes
Use raw request body
Use raw request body
Critical: Compute HMAC on the raw request body before parsing JSON. Parsing changes whitespace and ordering, breaking the signature.
Use timing-safe comparison
Use timing-safe comparison
Regular string comparison (==) is vulnerable to timing attacks. Use constant-time comparison:
- Node.js:
crypto.timingSafeEqual() - Python:
hmac.compare_digest() - Go:
hmac.Equal() - PHP:
hash_equals()
Keep secrets secure
Keep secrets secure
- Store webhook secret in environment variables
- Never commit secrets to version control
- Rotate secrets regularly
- Use different secrets for different environments
Testing Verification
Generate test signatures for local testing:Common Issues
Signature always fails
Signature always fails
Possible causes:
- Using wrong webhook secret
- Not using raw request body
- Character encoding issues
Intermittent failures
Intermittent failures
Cause: Parsing JSON before verificationFix: Always compute HMAC on raw body, then parse JSON
Different signatures on retry
Different signatures on retry
Cause: This shouldn’t happen - same payload = same signatureDebug: Log and compare payloads between requests
Next Steps
Webhook Overview
Delivery guarantees and implementation
Webhook Events
Event schemas and payloads