Webhooks
Send signed real-time events to external services.
Webhooks send signed notifications when leads, forms, conversations, or escalations change. They require a Hobby plan or above with active billing.
Configure an endpoint
Open an agent's Settings → Webhooks, choose one or more events, enter a public HTTPS endpoint, and create the subscriptions. Agentkit keeps one signing secret for all event rows at the same endpoint. Account owners can reveal or rotate it from the endpoint card.
Supported event names are:
lead_createdform_submission(legacy lead alias)custom_form_submittedconversation_startedconversation_endedescalation_created
conversation_ended is emitted after 30 minutes without a message. Its transcript is an immutable snapshot of at most 200 messages, with each message capped at 2,000 characters. Playground-only and user-message-free conversations are not dispatched. Transcript analysis is currently null.
Envelope
Every event uses the same stable envelope:
{
"event": "conversation_started",
"eventId": "evt_91d0a3ce-5a9d-4b67-a454-bafb9484281a",
"timestamp": "2026-07-14T13:05:02.000Z",
"data": {
"conversationId": "0b8e43d2-6cdf-42a8-8df1-a17f082df99f",
"conversationReferenceId": "a1b2c3d4e5f6a7b8",
"chatbotId": "d21c2aca-52d7-4056-a7d6-805713d3d39c",
"source": "widget",
"startedAt": "2026-07-14T13:05:02.000Z"
}
}
Use eventId as your idempotency key. Delivery is at least once and ordering is not guaranteed. The same event ID, occurrence timestamp, and JSON bytes are reused across retries.
Verify signatures
Deliveries include:
X-Agentkit-Event: conversation_started X-Agentkit-Event-Id: evt_91d0a3ce-5a9d-4b67-a454-bafb9484281a X-Agentkit-Signature: t=1784043902,v1=<hex-hmac-sha256>
Read the request body as raw UTF-8 text. Parse t and v1, compute HMAC-SHA256 with the endpoint secret over the exact bytes of t + "." + rawBody, and compare digests with a constant-time function. Do not parse and reserialize JSON before verification. Reject stale timestamps according to your replay policy.
import { createHmac, timingSafeEqual } from 'node:crypto';
const expected = createHmac('sha256', process.env.AGENTKIT_WEBHOOK_SECRET!)
.update(`${timestamp}.${rawBody}`, 'utf8')
.digest('hex');
const valid = timingSafeEqual(Buffer.from(expected, 'hex'), Buffer.from(v1, 'hex'));
Reliability and outcomes
Return a 2xx status within 10 seconds. A non-2xx response, timeout, or network error is retried five times after the initial request (normally six attempts total) with QStash backoff. The settings page shows the latest 20 terminal outcomes.
One exhausted event increments the failure streak once, regardless of attempts or duplicate callbacks. A subscription is automatically disabled only after at least 10 consecutive exhausted events spanning at least seven days. Owners receive one retryable notification and can re-enable it after repair. A successful event resets the streak.
Endpoint URLs must use HTTP or HTTPS, must be public, and cannot target localhost, private/link-local IP ranges, or cloud metadata endpoints. Production requires HTTPS. At delivery time Agentkit resolves the hostname once, requires every resolved address to be public, and pins the connection to those addresses, so DNS rebinding cannot redirect a delivery to an internal address.
Schedule activation
The idle-conversation sweep code ships disabled. An operator may review and run pnpm --filter chatbots setup:idle-conversation-webhooks after deployment. The command creates the 15-minute QStash schedule; merging code does not create or enable it.