Session webhooks

Get a request when a call or chat starts, when it ends, and when its analysis is ready — for every flow, or per flow.

Session webhooks push each conversation's lifecycle to your own endpoint, so your systems react as it happens instead of polling for results.

Events

EventSent when
OnSessionBeginA call or chat starts
OnSessionEndIt ends — with how it ended and what was collected
OnAIAnalysisReadyPost-conversation analysis, such as structured outputs, has finished

Most integrations only need OnAIAnalysisReady: it arrives after the conversation is over and the extracted fields exist.

Where to configure them

  • Workspace-wide, as the default for every flow.
  • Per flow, overriding the workspace default.

For each, choose which events to send, and whether to send them for inbound sessions, outbound sessions or both.

Note

Session webhooks belong to saved flows. A call started with an inline flow over the API does not run them.

The request

urlhttpsRequired

Your endpoint. Addresses on localhost are rejected.

methodPOST | PUT | PATCH | GET

POST unless your endpoint expects something else.

headersobject

Headers added to every request — this is where authentication for your endpoint goes, such as an Authorization header or an API key your endpoint checks.

customBodytemplate

Optional. Replace the default payload with a body shaped for the system receiving it.

Every request carries two headers:

X-Kilevel-Event-Type: OnSessionEnd
X-Kilevel-Event-Id: <unique event id>

The payload

The default payload identifies the event and the session, and carries what is known at that point. An abridged example for a call:

{
  "eventId": "…",
  "eventName": "OnSessionEnd",
  "sessionType": "call",
  "flowApiId": "f_sales_voice",
  "callerPhoneNumber": "+15551234567",
  "callStatus": "ENDED",
  "startedAt": "2026-09-14T09:12:03Z",
  "endedAt": "2026-09-14T09:15:41Z",
  "endedReason": "customer-ended-call",
  "sessionMemory": {
    "appointmentDate": "2026-09-18"
  }
}

sessionMemory holds the values the conversation collected. Fields present depend on the event and the channel; treat any field you do not recognise as optional.

Handling them

  • Answer with a 2xx straight away and do the work afterwards.
  • Deduplicate on X-Kilevel-Event-Id.
  • Fetch anything the payload does not include — the full transcript, the recording — from the API using the identifiers in the payload.