Webhook Signing & Verification
Verify Lead Distro AI webhook payloads with HMAC-SHA256 signatures. Signing secret format and X-LeadDistro-Signature header.
Why Sign Webhooks?
Lead Distro AI signs every outbound webhook with HMAC-SHA256 over the JSON body. Receivers can verify the signature to confirm: (1) the payload originated from Lead Distro AI (not a spoofer), and (2) the body wasn't tampered with in transit (TLS already protects against this, but signature gives belt-and-suspenders assurance).
Required for TCPA-sensitive verticals (legal lead distribution), HIPAA-adjacent leads, and any vertical where regulators may ask 'how do you know that lead came from your verified source?'
How the Signature Is Computed
- Take the raw JSON body bytes of the webhook POST.
- Compute HMAC-SHA256 with the buyer-specific signing secret as the key.
- Encode the resulting 32-byte digest as a lowercase hex string.
- Include it in the
X-LeadDistro-SignatureHTTP header on the webhook request.
Finding the Signing Secret
- Open the buyer's detail page in Lead Distro AI.
- Find the Webhook Signing Secret field (alongside the webhook URL).
- Copy the secret — it's a 32-byte hex string.
- Store it as an environment variable on the receiver's side. Don't commit to source control.
Always use a timing-safe comparison (crypto.timingSafeEqual in Node, hmac.compare_digest in Python, hash_equals in PHP) when comparing signatures. Naive string comparison leaks the expected signature one byte at a time to timing-attack adversaries.
Frequently Asked Questions
Where do I find the Lead Distro AI webhook signing secret?
What HTTP header contains the webhook signature?
X-LeadDistro-Signature. The value is a lowercase hex-encoded HMAC-SHA256 digest computed over the raw JSON body bytes using the buyer's signing secret. Headers are case-insensitive per HTTP spec.Do I have to verify webhook signatures, or is TLS enough?
Can I rotate the signing secret without downtime?
What happens if signature verification fails?
delivery_failed and you can investigate. Don't accept the lead 'just in case' — accepting unsigned payloads defeats the entire signing layer.Why must I use a timing-safe comparison for signatures?
== or ===) returns false on the first byte mismatch — and the time taken depends on where the mismatch occurred. An attacker can measure response time to learn the expected signature one byte at a time. Timing-safe comparison takes constant time regardless of where bytes differ, preventing the side-channel leak.Related Articles
If you have any questions, send us an email at support@leaddistro.ai