API · v1
The Call0 API.
Retrieve calls, manage agents, receive results via webhook, and control enabled outbound workflows through a focused REST API.
Introduction
All endpoints use the base URL https://www.call0.ai/api/v1. Requests and responses are JSON (Content-Type: application/json). Every resource is limited to the account associated with your API key.
Authentication
Create API keys in the dashboard under Developer. Keys begin with ck_live_, are shown once, and use either the read or write scope.
curl https://www.call0.ai/api/v1/calls \ -H "Authorization: Bearer ck_live_yourKey"
An invalid key returns 401; an insufficient scope returns 403.
List calls
GET/v1/calls
Lists calls for your account, newest first. Scope: read.
| Field | Type | Description |
|---|---|---|
| limit | integer | Items per page, max. 100 (default 20). |
| offset | integer | Pagination offset (default 0). |
| agent_id | string | Optional: only calls for this agent. |
curl "https://www.call0.ai/api/v1/calls?limit=2" \ -H "Authorization: Bearer ck_live_…"
Response · 200
{
"calls": [{
"id": "3af91e9e-…",
"agent_id": "23061e5a-…",
"direction": "inbound",
"status": "completed",
"duration_seconds": 216,
"summary": "Table reservation for four people on Friday at 7 PM.",
"callback_requested": false
}],
"total": 1,
"limit": 2,
"offset": 0
}Retrieve a call
GET/v1/calls/{id}
Returns one call with its complete transcript. Scope: read. A missing call or a call owned by another account returns 404.
curl https://www.call0.ai/api/v1/calls/3af91e9e-… \ -H "Authorization: Bearer ck_live_…"
Start a call (outbound)
POST/v1/calls/outbound
409 outbound_disabled.Starts an outgoing call. Scope: write. The agent_id may identify either the outbound agent or its inbound parent.
| Field | Type | Description |
|---|---|---|
| agent_id | string | Required. Outbound agent or associated inbound agent ID. |
| to | string | Required. Destination number in E.164 format. |
| mode | string | Optional. Demo mode "1", "2", or "3" for this call only. |
| variables | object | Optional conversation variables; values may contain up to 200 characters. |
curl -X POST https://www.call0.ai/api/v1/calls/outbound \
-H "Authorization: Bearer ck_live_…" \
-H "Content-Type: application/json" \
-d '{"agent_id":"23061e5a-…","to":"+14155550120","mode":"2"}'Retrieve progress through GET /v1/calls/{call_id} or receive the result via webhook. A missing caller ID returns 422.
Agents
GET/v1/agents
Lists account agents with their ID, name, role, language, and status.
POST/v1/agents
| Field | Type | Description |
|---|---|---|
| name | string | Display name or company name used in the greeting. |
| system_prompt | string | Agent behavior and instructions. |
| greeting | string | Greeting or outbound opening line. |
| language | string | Language code such as de-DE, en-US, or fr-FR. |
| voice_id | string | Voice selected from the dashboard voice library. |
Webhooks
Add webhook endpoints in the dashboard under Integrations → Create webhook. After each completed conversation, Call0 sends a call.completed POST request to your URL. You can also subscribe to call.missed, call.failed, handoff.requested, handoff.connected, intake.captured and booking.created. The Docs button in the webhook dialog shows every payload, the retry schedule and the pause rules.
{
"event": "call.completed",
"call": {
"id": "3af91e9e-…",
"status": "completed",
"duration_seconds": 216,
"summary": "…",
"transcript": [ … ]
}
}Verify X-Call0-Signature as an HMAC-SHA256 of timestamp.body using your webhook secret. The timestamp is provided in X-Call0-Timestamp. Return a 2xx status and reject stale timestamps to prevent replay attacks.
Live chat (chatbot handoff)
When a chatbot visitor asks for a person, Call0 sends the chat to your system (webhook). Your team answers through the Live Chat API and the reply appears in the chat window right away. While a team member holds the chat, the chatbot stays silent.
Set up in Chatbot → Behaviour → When a person should help → Livechat per Webhook: your endpoint, the signing secret and an API key with the scope livechat:write. That key only works for the live chat of this one chatbot; other keys are refused here.
Endpoints
Base URL https://www.call0.ai/api/v1/livechat, header Authorization: Bearer ck_live_….
| Method | Path | Effect |
|---|---|---|
| POST | /conversations/{id}/messages | Send a team member reply to the visitor (takes over the chat if needed) |
| POST | /conversations/{id}/takeover | Take over: the chatbot stops answering |
| POST | /conversations/{id}/release | Hand back to the chatbot |
| POST | /conversations/{id}/close | Close the conversation |
| GET | /conversations/{id} | Status and recent messages (?limit=50, max 200) |
curl -X POST https://www.call0.ai/api/v1/livechat/conversations/6f1c2a9e-3b7d-4c55-9a1e-2d8f0b4c7e11/messages \
-H "Authorization: Bearer ck_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: reply-4711" \
-d '{
"text": "Hallo, hier ist Anna vom Support. Wie kann ich helfen?",
"author": { "name": "Anna", "avatar_url": "https://deine-firma.de/team/anna.png" }
}'| Field | Type | Description |
|---|---|---|
| text | string | Required, 1–4000 characters. Plain text; https:// links become clickable. |
| author.name | string? | Team member name, up to 80 characters. |
| author.avatar_url | string? | Team member picture, https only. |
| idempotency_key | string? | Or header Idempotency-Key. Same key → no duplicate message. |
A message takes over the chat automatically. Responses: 201 (new) or 200 (repeat with the same Idempotency-Key). If a team member took the chat in the Call0 inbox, you get 409.
Events to your system
| Event | When | Contents |
|---|---|---|
| handoff.requested | Visitor asks for a person | Conversation, visitor, summary, transcript, links |
| message.created | New visitor message while a person is in charge | Conversation, message, links |
| conversation.closed | Conversation closed (API or inbox) | closed_by, closed_at |
{
"id": "chatbot-handoff:6f1c2a9e-…:webhook:1761148800000",
"event": "handoff.requested",
"created_at": "2026-10-22T16:00:00.000Z",
"data": {
"conversation": {
"id": "6f1c2a9e-3b7d-4c55-9a1e-2d8f0b4c7e11",
"chatbot_id": "23061e5a-8c4f-4b2e-9d61-7a0e5f3c9b28",
"status": "waiting",
"created_at": "2026-10-22T15:58:12.000Z"
},
"visitor": {
"email": null,
"locale": "de",
"page_url": "https://deine-firma.de/preise"
},
"summary": "Der Besucher fragt nach einem Angebot für 20 Nutzer.",
"transcript": [
{
"id": "…",
"role": "visitor",
"text": "Was kostet das für 20 Nutzer?",
"author": null,
"created_at": "2026-10-22T15:58:12.000Z"
},
{
"id": "…",
"role": "bot",
"text": "Gern verbinde ich dich mit dem Team.",
"author": null,
"created_at": "2026-10-22T15:58:14.000Z"
}
],
"links": {
"dashboard": "https://www.call0.ai/dashboard/chatbot/inbox?agent=…&conversation=…",
"api": "https://www.call0.ai/api/v1/livechat/conversations/6f1c2a9e-3b7d-4c55-9a1e-2d8f0b4c7e11"
}
}
}Every delivery carries X-Call0-Event, X-Call0-Event-Id (same on retries), X-Call0-Timestamp and X-Call0-Signature = sha256=HMAC(secret, timestamp + "." + body). Answer with 2xx. Otherwise we retry up to 5 times with growing delays (1, 2, 4, 8 min). Targets must be publicly reachable over HTTPS.
import crypto from 'node:crypto'
// rawBody: der unveränderte Text der Anfrage
function verify(headers, rawBody, secret) {
const ts = headers['x-call0-timestamp']
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(ts + '.' + rawBody)
.digest('hex')
const given = Buffer.from(headers['x-call0-signature'] || '')
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) < 300
return fresh && given.length === expected.length &&
crypto.timingSafeEqual(given, Buffer.from(expected))
}Limits
| Limit | Value | Response |
|---|---|---|
| Requests per key | 120 / min | 429 + Retry-After |
| Messages per conversation | 30 / min | 429 + Retry-After |
| Request size | 16 KB | 413 |
| Foreign or unknown conversation | — | 404 |
| Chatbot is mid-answer | — | 409 bot_busy + Retry-After: 2 |
Errors
| Field | Type | Description |
|---|---|---|
| 400 | invalid_request | A required field is missing or malformed. |
| 401 | unauthorized | The API key is missing or invalid. |
| 403 | insufficient_scope | The key does not have the required scope. |
| 404 | not_found | The resource does not exist or belongs to another account. |
| 422 | unprocessable | The request is valid but cannot be completed. |
| 5xx | server_error | Unexpected error; retry with backoff. |
Errors use { "error": "…" } with the corresponding HTTP status. Questions? Contact us.