Build your integration / Verify webhook signatures
GUIDE

Verify webhook signatures

If you set a secret on a V2 webhook, LeadTruffle signs each delivery with HMAC SHA-256 headers:

  • x-leadtruffle-timestamp: Unix timestamp in seconds
  • x-leadtruffle-signature: v1= followed by the hex HMAC SHA-256 signature
  • x-leadtruffle-signature-algorithm: hmac-sha256

The signature is computed over ${timestamp}.${rawRequestBody} using the webhook secret as the HMAC key. Verify the signature against the raw request body before parsing JSON.

Python verification example:

import hmac, hashlib, time

raw_body = request.get_data()
timestamp = request.headers["x-leadtruffle-timestamp"]
signature = request.headers["x-leadtruffle-signature"].removeprefix("v1=")

try:
    timestamp_seconds = int(timestamp)
except ValueError:
    raise Exception("invalid timestamp")

if abs(time.time() - timestamp_seconds) > 5 * 60:
    raise Exception("stale webhook")

expected = hmac.new(
    b"YOUR_WEBHOOK_SECRET",
    timestamp.encode("utf-8") + b"." + raw_body,
    hashlib.sha256,
).hexdigest()

if not hmac.compare_digest(expected, signature):
    raise Exception("invalid signature")

PHP verification example:

$rawBody = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_LEADTRUFFLE_TIMESTAMP'];
$signature = preg_replace('/^v1=/', '', $_SERVER['HTTP_X_LEADTRUFFLE_SIGNATURE']);

if (!ctype_digit($timestamp) || abs(time() - intval($timestamp)) > 5 * 60) {
    http_response_code(401);
    exit;
}

$expected = hash_hmac('sha256', $timestamp . '.' . $rawBody, 'YOUR_WEBHOOK_SECRET');

if (!hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}

Guides & API endpoints Esc to close