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.

FeldTypBeschreibung
limitintegerAnzahl pro Seite, max. 100 (Standard 20).
offsetintegerVersatz für Pagination (Standard 0).
agent_idstringOptional: 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.

FeldTypBeschreibung
agent_idstringPflicht. ID des Agenten (Outbound oder zugehöriger Inbound).
tostringPflicht. Zielnummer im E.164-Format, z. B. +4917612345678.
variablesobjectOptional. 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:

FeldTypBeschreibung
namestringAnzeigename / Firmenname für die Begrüßung.
system_promptstringVerhalten & Anweisungen des Agenten.
greetingstringBegrüßung (Outbound: Eröffnungszeile).
languagestringSprachcode, z. B. de-DE (Standard), en-US, fr-FR …
voice_idstringStimme (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

FeldTypBeschreibung
400invalid_requestPflichtfeld fehlt oder Format ungültig (z. B. Nummer nicht E.164).
401unauthorizedAPI-Key fehlt oder ist ungültig.
403insufficient_scopeKey hat nicht den nötigen Scope (read/write).
404not_foundRessource existiert nicht oder gehört einem anderen Konto.
422unprocessableAnfrage verstanden, aber nicht ausführbar (z. B. keine Absender-Nummer).
5xxserver_errorUnerwarteter Fehler — mit Backoff erneut versuchen.

Fehler kommen als { "error": "…" } mit passendem HTTP-Status. Fragen? Schreib uns.