0API · v1
Die Call0-API.
Anrufe starten und abrufen, Agenten verwalten, Ergebnisse als Webhook empfangen — eine schlanke REST-API, JSON rein, JSON raus.
Einführung
Alle Endpoints liegen unter der Basis-URL https://www.call0.ai/api/v1. Requests und Responses sind JSON (Content-Type: application/json). Alle Ressourcen sind strikt auf das Konto deines API-Keys beschränkt.
Authentifizierung
Erstelle API-Keys im Dashboard unter Entwickler. Keys beginnen mit ck_live_ und werden nur einmal angezeigt. Jeder Key hat einen Scope: read (lesen) oder write (lesen + Anrufe starten).
Sende den Key als Bearer-Token:
curl https://www.call0.ai/api/v1/calls \ -H "Authorization: Bearer ck_live_IhrSchluessel"
Ohne gültigen Key antwortet die API mit 401, bei fehlendem Scope mit 403.
Anrufe auflisten
GET/v1/calls
Listet die Anrufe deines Kontos, neueste zuerst. Scope: read.
| Feld | Typ | Beschreibung |
|---|---|---|
| limit | integer | Anzahl pro Seite, max. 100 (Standard 20). |
| offset | integer | Versatz für Pagination (Standard 0). |
| agent_id | string | Optional: nur Anrufe dieses Agenten. |
curl "https://www.call0.ai/api/v1/calls?limit=2" \ -H "Authorization: Bearer ck_live_…"
Antwort · 200
{
"calls": [
{
"id": "3af91e9e-…",
"agent_id": "23061e5a-…",
"direction": "inbound",
"status": "completed",
"from": "+4917612345678",
"to": "+4921268943062",
"started_at": "2026-07-01T14:00:05Z",
"ended_at": "2026-07-01T14:03:41Z",
"duration_seconds": 216,
"sentiment": "positive",
"summary": "Tischreservierung für 4 Personen am Freitag, 19 Uhr.",
"action_items": ["Reservierung bestätigen"],
"callback_requested": false
}
],
"limit": 2,
"offset": 0
}Anruf abrufen
GET/v1/calls/{id}
Ein einzelner Anruf — zusätzlich zur Liste mit vollständigem transcript. Scope: read.
curl https://www.call0.ai/api/v1/calls/3af91e9e-… \ -H "Authorization: Bearer ck_live_…"
Antwort · 200
{
"call": {
"id": "3af91e9e-…",
"status": "completed",
"duration_seconds": 216,
"summary": "Tischreservierung für 4 Personen …",
"transcript": [
{ "role": "agent", "text": "Willkommen bei MAKU …" },
{ "role": "caller", "text": "Ich hätte gern einen Tisch für vier." },
{ "role": "agent", "text": "Sehr gern — für wann?" }
]
}
}Existiert der Anruf nicht (oder gehört er einem anderen Konto): 404.
Anruf starten (Outbound)
POST/v1/calls/outbound
Startet einen ausgehenden Anruf über einen deiner Outbound-Agenten. Scope: write. Als agent_id ist der Outbound-Agent selbst oder sein Inbound-Elternteil erlaubt — Call0 löst automatisch zum Outbound-Agenten auf.
| Feld | Typ | Beschreibung |
|---|---|---|
| agent_id | string | Pflicht. ID des Agenten (Outbound oder zugehöriger Inbound). |
| to | string | Pflicht. Zielnummer im E.164-Format, z. B. +4917612345678. |
| variables | object | Optional. Dynamische Variablen fürs Gespräch (z. B. {"name": "Frau Weber"}). Werte max. 200 Zeichen. |
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": "+4917612345678",
"variables": { "name": "Frau Weber", "sendung": "DHL-4471" }
}'Antwort · 201
{
"success": true,
"call_id": "d9d63b86-…",
"call_sid": "CA7f3e…"
}Den Verlauf holst du danach über GET /v1/calls/{call_id} — oder du lässt dir das Ergebnis per Webhook schicken. Fehlt dem Agenten eine Absender-Nummer: 422.
Agenten
GET/v1/agents
Listet die Agenten deines Kontos (ID, Name, Rolle, Sprache, Status).
POST/v1/agents
Legt einen Agenten an. Wichtigste Felder:
| Feld | Typ | Beschreibung |
|---|---|---|
| name | string | Anzeigename / Firmenname für die Begrüßung. |
| system_prompt | string | Verhalten & Anweisungen des Agenten. |
| greeting | string | Begrüßung (Outbound: Eröffnungszeile). |
| language | string | Sprachcode, z. B. de-DE (Standard), en-US, fr-FR … |
| voice_id | string | Stimme (siehe Stimmen im Dashboard). |
Webhooks
Lege Webhook-Endpoints im Dashboard unter Entwickler an. Nach jedem abgeschlossenen Gespräch senden wir call.completed als POST an deine URL:
{
"event": "call.completed",
"call": {
"id": "3af91e9e-…",
"agent_id": "23061e5a-…",
"direction": "outbound",
"status": "completed",
"duration_seconds": 216,
"summary": "…",
"transcript": [ … ]
}
}Jede Zustellung ist signiert: Header X-Call0-Signature enthält sha256=<hex> — ein HMAC-SHA256 über timestamp.body mit deinem Webhook-Secret; der Zeitstempel steht in X-Call0-Timestamp. Verifikation in Node:
import crypto from 'crypto'
function verify(req, secret) {
const ts = req.headers['x-call0-timestamp']
const sig = req.headers['x-call0-signature'] // "sha256=…"
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(ts + '.' + req.rawBody)
.digest('hex')
return crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))
}Antworte mit einem 2xx-Status. Lehne Zustellungen ab, deren Zeitstempel älter als ein paar Minuten ist (Replay-Schutz).
Fehler
| Feld | Typ | Beschreibung |
|---|---|---|
| 400 | invalid_request | Pflichtfeld fehlt oder Format ungültig (z. B. Nummer nicht E.164). |
| 401 | unauthorized | API-Key fehlt oder ist ungültig. |
| 403 | insufficient_scope | Key hat nicht den nötigen Scope (read/write). |
| 404 | not_found | Ressource existiert nicht oder gehört einem anderen Konto. |
| 422 | unprocessable | Anfrage verstanden, aber nicht ausführbar (z. B. keine Absender-Nummer). |
| 5xx | server_error | Unerwarteter Fehler — mit Backoff erneut versuchen. |
Fehler kommen als { "error": "…" } mit passendem HTTP-Status. Fragen? Schreib uns.