Call job completion webhook
One request when every row of a call job has finished — with the counts, and the URLs to fetch the rows.
Instead of polling a call job until it finishes, give it a completion webhook. When the
last row has finished, Kilevel sends one POST to your URL.
Request
POST /your-endpoint HTTP/1.1
Content-Type: application/json
User-Agent: Kilevel-Completion-Webhook/1.0
X-Kilevel-Event-Type: call_job.completed
X-Kilevel-Event-Id: <unique event id>
X-Kilevel-Delivery-Attempt: 1{
"eventId": "…",
"eventType": "call_job.completed",
"occurredAt": "2026-09-14T14:55:10Z",
"deliveryAttempt": 1,
"job": {
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"name": "Q1 Outreach",
"status": "COMPLETED",
"totalRows": 1200,
"processedRows": 1200,
"successfulRows": 1104,
"errorRows": 96,
"flowApiId": "f_sales_voice"
},
"retrieval": {
"endpoints": {
"callJob": "https://api.kilevel.com/api/external/v1/call-jobs/…",
"callRows": "https://api.kilevel.com/api/external/v1/call-jobs/…/rows"
}
}
}The payload carries the summary; the rows themselves — transcripts, outcomes, extracted
fields — are fetched from the retrieval URLs with your API key. That keeps the webhook
small however large the job.
Authentication
Choose how Kilevel authenticates to your endpoint:
| Mode | What is sent |
|---|---|
| None | No credentials — only for endpoints that verify the request some other way |
| Bearer token | Authorization: Bearer <your secret> |
| Custom header | A header name and value of your choice |
Handling it
- Respond with a
2xxquickly and do the work afterwards. - Use
X-Kilevel-Event-Idto ignore duplicates: a delivery can be retried, andX-Kilevel-Delivery-Attempttells you which attempt you are looking at.