Webhook payload & signature

Vellow signs every outbound webhook, Zapier and Make.com payload with HMAC-SHA256 so your endpoint can verify it came from us.

Headers

Each POST contains three custom headers.

X-Vellow-Event: lead
X-Vellow-Timestamp: 1753953600
X-Vellow-Signature: sha256=...

Payload shape

The body is a JSON object. For lead events the lead key is present; for testimonial events the testimonial key is present instead.

{
  "event": "lead",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "createdAt": "2026-07-31T12:00:00.000Z",
  "workspaceId": "...",
  "widget": {
    "id": "...",
    "name": "Pricing page widget",
    "publicId": "fp_abc123"
  },
  "lead": {
    "name": "Jane Doe",
    "email": "jane@example.com",
    "phone": "+1 555 0199",
    "fields": { "company": "Acme" },
    "sourceUrl": "https://example.com/pricing",
    "consent": true,
    "device": "desktop",
    "referrer": "google.com",
    "trafficSource": "google_ads"
  },
  "mappedFields": {
    "email": "jane@example.com",
    "company": "Acme"
  }
}

mappedFields contains any custom field mappings configured on the integration. If no mapping is set it is an empty object.

Verifying the signature

The signature is computed over {timestamp}. concatenated with the raw request body, using the per-workspace secret shown in your Vellow integration settings.

Node.js

const crypto = require("crypto");

function isValid(reqBody, timestamp, signature, secret) {
  const expected = crypto
    .createHmac("sha256", secret)
    .update(`${timestamp}.${reqBody}`)
    .digest("hex");
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Python

import hmac, hashlib

def is_valid(body: str, timestamp: str, signature: str, secret: str) -> bool:
    expected = hmac.new(
        secret.encode(),
        f"{timestamp}.{body}".encode(),
        hashlib.sha256
    ).hexdigest()
    return hmac.compare_digest(signature, expected)

PHP

function isValid($body, $timestamp, $signature, $secret) {
  $expected = hash_hmac(
    'sha256',
    "$timestamp.$body",
    $secret
  );
  return hash_equals($signature, $expected);
}

Retries and delivery log

Vellow attempts delivery up to three times with exponential backoff. Every attempt is recorded in the workspace delivery log on the Integrations page, including the HTTP status code and any error message returned by your endpoint.

IP addresses

Outbound deliveries originate from Vellow's edge runtime. IPs are not fixed, so we recommend whitelisting by the X-Vellow-Signature header rather than by IP address.