Outgoing webhooks
Receive events in your own systems, and verify that they really came from us.
Updated 2026-09-05The events
lead.created— a visitor left their details.conversation.completed— someone marked a conversation closed or escalated.document.indexed— a document finished indexing and can be answered from.document.failed— a document could not be indexed.sync.completed— a connected source finished a sync run.
Adding an endpoint
In Destinations → Webhooks, add a public https URL and tick the events you want. We show the signing secret once, when the endpoint is created and whenever you rotate it. Store it then; we only keep a hash of it afterwards.
Use Send a test to fire a real delivery with sample data: same signature, same retries, same log.
The envelope
We POST JSON with two headers that matter:
X-WelcomeAI-Signature: t=1788639323,v1=6f3a...
X-WelcomeAI-Event: lead.createdThe body looks like this:
{
"id": "evt_2b91Ha0Kd3fQ",
"type": "lead.created",
"created_at": "2026-09-05T20:15:23.201Z",
"org_id": "org_UWzIf5jv8lW2",
"data": { "lead_id": "ld_GSTPfNF6SEkE", "email": "grace@example.com" }
}Verifying a delivery
Take t and v1 from the signature header. Compute HMAC-SHA256 over the timestamp, a dot, and the raw request body, using your signing secret. Compare it with v1 using a constant-time comparison, and reject anything where t is more than five minutes old.
const [t, v1] = header.split(",").map((p) => p.split("=")[1]);
const expected = crypto.createHmac("sha256", secret).update(`${t}.${rawBody}`).digest("hex");
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(v1));Use the raw body, not a re-serialized object: any difference in whitespace or key order changes the digest.
Retries
We try six times: after 30 seconds, 2 minutes, 10 minutes, 1 hour, 6 hours and 24 hours. Every attempt is signed again, so a retry never arrives with a stale timestamp.
Anything in the 2xx range means delivered. 410 Gone means stop sending and we do not retry. Everything else is retried, including 4xx, because a receiver that deploys badly should not lose events.
An endpoint that fails twenty times in a row is switched off, and you can turn it back on once the receiver is fixed.
Duplicates
The same event id can arrive more than once, for example if your acknowledgement was lost. Treat id as the deduplication key.