Securing Webhooks
Truedy signs every webhook request so you can confirm:- The request really came from Truedy
- The payload wasn’t modified in transit
- The request isn’t a replay of an older delivery
Headers sent with every request
Signature algorithm (step by step)
- Read the raw request body bytes exactly as received — do not parse JSON first.
- Extract
X-Truedy-TimestampandX-Truedy-Signature. - Build the signed message:
"{timestamp}.{raw_body_as_string}" - Compute
HMAC-SHA256(key=webhook_secret, message=signed_message)and hex-encode it. - Compare with
X-Truedy-Signatureusing a constant-time comparison. - Reject if the timestamp is more than 5 minutes old (replay protection).
Implementation examples
Where to find your webhook secret
- Open the Truedy dashboard → Settings → Webhooks
- Select (or create) your webhook endpoint
- Copy the Signing Secret — it looks like
whsec_...
TRUEDY_WEBHOOK_SECRET). Never hardcode it in source files.
Security checklist
Always use HTTPS — never accept webhooks over plain HTTP in production
Read the raw body bytes before parsing JSON — parsers may normalize whitespace and break HMAC
Reject stale timestamps (>5 min old) to block replay attacks
Use constant-time comparison (
timingSafeEqual / compare_digest) — never === on signaturesReturn
2xx immediately after verification — process asynchronously in a background jobStore your webhook secret in an environment variable, not in source code
Treat all payload fields as untrusted input — validate types and handle missing fields
Troubleshooting signature failures
Next steps
Available Webhooks
Full event catalogue and payload shapes
Error Handling & Retries
Idempotent receiver runbook

