API
Webhooks
Webhooks push events to your server as they happen: a conversation starts, a customer asks for a human, a document finishes processing. Create endpoints under Developer → Webhooks.
Events
| Field | Type | Description |
|---|---|---|
conversation.started | event | A new conversation began (widget or API). |
conversation.finished | event | A conversation was resolved or went idle. |
human.requested | event | An end user asked for human handoff. |
document.uploaded | event | A document was added and queued for processing. |
document.processed | event | Ingestion finished; the document is searchable. |
document.failed | event | Ingestion failed — the payload includes the error. |
knowledge.synced | event | A website crawl completed and the index was refreshed. |
feedback.submitted | event | An end user rated an assistant answer. |
api_key.created | event | A new API key was created in your organization. |
Subscribe an endpoint to specific events or to * for everything.
Delivery format
Deliveries are POST requests with a JSON body:
{
"id": "evt_8f2c1a...",
"event": "human.requested",
"createdAt": "2026-07-12T10:30:00.000Z",
"data": {
"conversationId": "cm_abc123",
"projectId": "cm_prj789",
"reason": "Wants to change billing address",
"customerEmail": "jane@example.com"
}
}Verifying signatures
Every delivery is signed with your endpoint's secret (whsec_..., shown when you create the endpoint). The X-KB-Signature header contains sha256=<hex digest> — an HMAC-SHA256 of the raw request body. Always verify before trusting a payload:
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyWebhook(rawBody: string, header: string, secret: string) {
const expected = "sha256=" +
createHmac("sha256", secret).update(rawBody).digest("hex");
return (
header.length === expected.length &&
timingSafeEqual(Buffer.from(header), Buffer.from(expected))
);
}
// Express example — use the raw body, not the parsed JSON:
// app.post("/webhooks/asklify", express.raw({ type: "*/*" }), (req, res) => {
// const ok = verifyWebhook(req.body.toString(), req.get("X-KB-Signature")!, secret);
// if (!ok) return res.status(401).end();
// const event = JSON.parse(req.body.toString());
// res.status(200).end();
// });Responding and retries
Respond with a 2xx within a few seconds — do slow work asynchronously after acknowledging. Failed deliveries are retried with backoff; endpoints that keep failing are visible (with delivery logs) under Developer → Webhooks, where you can also rotate secrets or disable an endpoint.
Best practices
Make handlers idempotent (dedupe on the delivery id), verify signatures before any processing, and use one endpoint per environment so staging events never hit production.
