Every webhook request from Leaf includes an X-Leaf-Signature header. This header contains a base64-encoded HMAC SHA-256 digest of the request body, signed with the secret you provided when creating the webhook. Verify this signature before processing any payload.
How signature verification works
- Read the raw request body as bytes. Do not parse or reformat it first.
- Compute an HMAC SHA-256 digest of those bytes using your webhook secret as the key.
- Base64-decode the value from the
X-Leaf-Signature header.
- Compare the two digests using a constant-time comparison function.
The signed content is a compact JSON string without extra line breaks or spaces (other than spaces after : and ,).
Code examples
import hmac
import base64
import json
def verify_leaf_signature(raw_body: bytes, secret: str, signature_header: str) -> bool:
expected_sig = hmac.digest(
msg=raw_body,
key=secret.encode("utf-8"),
digest="sha256"
)
request_sig = base64.b64decode(signature_header)
return hmac.compare_digest(expected_sig, request_sig)
Example payload
If you receive a fieldCreated event, the signed body looks like:
{"source": "REST", "leafUserId": "uuid", "fieldId": "uuid", "timestamp": "2024-06-15T14:30:00.000000Z", "type": "fieldCreated"}
Compute the HMAC of this exact byte string with your secret to get the expected signature.
IP addresses
Leaf uses cloud infrastructure and does not have a fixed range of IP addresses for webhook delivery. If your network architecture requires allow-listing, consider placing a load balancer or reverse proxy in a DMZ to receive webhook traffic and forward it to your internal systems.
Using an X-CompanyName-Signature header for webhook verification is an industry-standard pattern also used by Twilio, Slack, and Stripe.
What to do next