Server-API (REST v1) und MCP
Die REST-Schnittstelle von reactive.chat für dein Backend – API-Schlüssel und Rechtestufen, Ratenbegrenzung, Antwort- und Fehlerformat, Paginierung, alle Endpunkte für Projekte, Gespräche, Nachrichten, Besucher, Ereignisse, Regeln und Hooks – sowie der MCP-Server für KI-Werkzeuge.
Die Server-API ist für dein Backend gedacht, nicht für den Browser: Sie erlaubt kein CORS, und ein API-Schlüssel gehört nie in eine Webseite oder App.
Grundlagen
- Basis:
https://reactive.chat/v1/ - Version: im Pfad (
v1). Innerhalb von v1 kommen Felder hinzu, aber keine fallen weg; ignoriere unbekannte Felder. - Format: JSON, UTF-8. Zeitangaben als ISO 8601 in UTC (
2026-10-21T08:15:30.123Z). Kennungen werden als Zeichenketten ausgegeben ("id":"123"). - Antwortköpfe:
Cache-Control: no-store, private,X-Content-Type-Options: nosniff. - Ein Pfad, den es nicht gibt, liefert eine 404-Seite (nicht JSON).
API-Schlüssel
Im Konto unter API-Schlüssel (/app/api-keys, nur Eigentümer und Admins). Du vergibst einen Namen und eine Rechtestufe; der Schlüssel (rc_live_ + 48 Zeichen) wird genau einmal angezeigt, wir speichern nur einen Hash.
Rechtestufen:
- Lesen –
read - Lesen und schreiben –
read,write - Lesen mit Besucherdaten –
read,besucherdaten:lesen - Lesen, schreiben, Besucherdaten –
read,write,besucherdaten:lesen - Nur Kundendaten-Import –
kundendaten:schreiben(Kundendaten)
Ein Schlüssel gehört zu genau einem Workspace; kein Pfad und kein Parameter wählt einen anderen. Er wird ungültig, wenn du ihn widerrufst oder wenn die Person, die ihn angelegt hat, nicht mehr Eigentümer oder Admin des Workspace ist. Ein Ablaufdatum gibt es nicht – rotiere selbst (neuen anlegen, umstellen, alten widerrufen).
Senden:
curl https://reactive.chat/v1/me -H "Authorization: Bearer rc_live_..."
Gleichwertig ist die Kopfzeile X-Api-Key: rc_live_... (wird nur gelesen, wenn kein Authorization: Bearer vorhanden ist).
Ratenbegrenzung
- 120 Anfragen je Minute und Schlüssel, festes Fenster zur vollen Minute. Jede Anfrage zählt, auch eine abgelehnte.
- Jede Antwort trägt
X-RateLimit-Limit,X-RateLimit-RemainingundX-RateLimit-Reset(Sekunden bis zum nächsten Fenster, kein Zeitstempel). - Darüber: 429
rate_limitedmitRetry-After. - Nach 60 fehlgeschlagenen Anmeldungen je Adresse in 15 Minuten: 429 mit
Retry-After: 900.
Antwortformat
{ "data": { ... } }
Listen:
{ "data": [ ... ], "has_more": true, "next": { "before_id": "812" } }
Paginierung: limit (Vorgabe 25, höchstens 100) und ein Cursor – before_id bei Listen „neueste zuerst“, after_id bei Listen „älteste zuerst“. next steht nur da, wenn has_more wahr ist. Einen Gesamtzähler gibt es nicht.
Rümpfe von POST/PUT: nur Content-Type: application/json (sonst 415), höchstens 65 536 Bytes (sonst 413), ein JSON-Objekt mit höchstens 32 Ebenen.
Fehlerformat
{ "error": { "code": "insufficient_scope", "message": "...", "required_scope": "write" } }
message ist ein fester englischer Satz für Entwickler. Je nach Fehler kommen param, required_scope, max, allowed, reason hinzu. Die Codes sind abschließend:
- 400
bad_request,bad_json - 401
auth_required(kein Schlüssel),auth_failed(ungültig oder widerrufen) - 402
plan_required - 403
insufficient_scope,workspace_inactive - 404
not_found,conversation_not_found - 405
method_not_allowed(mitAllow) - 409
conversation_closed,import_disabled - 413
payload_too_large - 415
unsupported_media_type - 422
msg_too_long(mitmax) - 429
rate_limited - 500
internal, 501not_implemented, 503unavailable
Endpunkte
Konto
- GET /v1/me – ohne besondere Rechtestufe.
{ key: {id, name, scopes}, workspace: {id, name}, rate_limit: {requests, window_seconds} }. Gut zum Prüfen eines Schlüssels.
Projekte (read)
- GET /v1/projects –
limit,before_id. Je Projekt:id,name,domain,site_key,status,locale,created_at,updated_at,last_used_at. - GET /v1/projects/{id}
Gespräche (read)
- GET /v1/conversations – neueste zuerst. Filter
project_id,status(open,bot,waiting,assigned,closed),limit,before_id. Je Gespräch:id,project_id,status,channel,visitor_id,session_id,assignee_id,csat_score,handoff_reason,created_at,updated_at,closed_at. - GET /v1/conversations/{id}
Nachrichten
- GET /v1/conversations/{id}/messages (
read) – älteste zuerst,after_id,limit. Je Nachricht:id,conversation_id,client_ulid,direction(inzum Besucher,outvom Besucher),author_type,author_id,kind,body,redacted,delivery_state,created_at; wenn vorhandencard,cards,form,form_reply,action,quick_replies,quick_reply_of. - GET /v1/messages (
read) – alle Nachrichten des Workspace als Strom,conversation_idoptional,after_id,limit. Zum Abholen ohne Webhooks. - POST /v1/conversations/{id}/messages (
write) – Nachricht in ein Gespräch schreiben:
curl -X POST https://reactive.chat/v1/conversations/815/messages \
-H "Authorization: Bearer rc_live_..." \
-H "Content-Type: application/json" \
-d '{"body":"Ihre Rücksendung ist angekommen.","author_type":"agent","client_ulid":"01JAB3C4D5E6F7G8H9JKMNPQRS"}'
- body (String, Pflicht, höchstens 4000 Zeichen)
- author_type (
agent|bot|system, Vorgabeagent) – nicht im Namen des Besuchers - client_ulid (ULID, optional) – für Idempotenz: dieselbe Kennung noch einmal ergibt 200 mit der bestehenden Nachricht statt einer zweiten (201 beim ersten Mal).
- 409
conversation_closedbei geschlossenem Gespräch, 422msg_too_long. - Hinweis: So geschriebene Nachrichten werden gespeichert, erreichen ein gerade offenes Widget aber nicht sofort, sondern beim nächsten Abgleich. Für Live-Antworten nimm das MCP-Werkzeug
nachricht_senden(unten).
Besucher (read)
- GET /v1/visitors – Live-Besucherliste:
project_id,online(0/1),limit. Je Besucher u. a.online,consent,first_seen_at,last_active_at,visitor_id,page,pages_viewed,source(mit UTM),device,country,language,returning,conversation. Zusätzlichdisabled_project_idsfür Projekte, in denen die Besucherliste abgeschaltet ist.
Ereignisse
- GET /v1/events (
read) –project_id,type,source(mp,rc,integration),after_id,limit. Je Ereignisid,project_id,source,type,session_id,conversation_id,payload,created_at. - POST /v1/events (
write) – eigenes Ereignis aus deinem System an eine Sitzung oder ein Gespräch hängen:
{ "project_id": "123", "type": "bestellung.storniert",
"session_id": "s_...", "conversation_id": "01JAB...",
"payload": { "nummer": "2026-0815" }, "ts": 1792503600000 }
type nach ^[a-z][a-z0-9_.:-]{0,47}$, payload höchstens 8192 Bytes, ts in Millisekunden (höchstens 7 Tage alt, höchstens 5 Minuten voraus). source ist immer integration. Antwort 201.
Regeln (read)
- GET /v1/rules –
project_id. Je Projektsource(customoderdefault) undrules. Nur lesend; Regeln bearbeitest du unter Anpassung.
Hooks – siehe Webhooks: GET /v1/hooks, POST /v1/hooks, DELETE /v1/hooks/{id}.
Kundendaten – siehe Kundendaten: PUT und DELETE /v1/kundendaten/{user_id}.
Beispiel: offene Gespräche abholen
<?php
$key = getenv('RC_API_KEY');
$url = 'https://reactive.chat/v1/conversations?status=waiting&limit=100';
do {
$ch = curl_init($url);
curl_setopt_array($ch, [CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . $key]]);
$antwort = json_decode((string) curl_exec($ch), true);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
if ($status === 429) { sleep(60); continue; }
foreach ($antwort['data'] as $g) { echo $g['id'], ' ', $g['created_at'], "\n"; }
$url = !empty($antwort['has_more'])
? 'https://reactive.chat/v1/conversations?status=waiting&limit=100&before_id=' . $antwort['next']['before_id']
: null;
} while ($url);
MCP-Server
Für KI-Werkzeuge, die das Model Context Protocol sprechen, gibt es einen MCP-Server unter derselben Basis:
- Adresse:
POST https://reactive.chat/v1/mcp(Streamable HTTP, JSON-RPC 2.0, zustandslos, kein Batching). Die genaue Adresse zeigt die Seite API-Schlüssel. - Anmeldung: derselbe API-Schlüssel als
Authorization: Bearer; dieselbe Ratenbegrenzung. - Protokollfassungen:
2026-07-28(mitserver/discover; die KopfzeilenMCP-Protocol-Version,Mcp-Methodund beitools/callMcp-Namesind Pflicht) sowie2025-11-25,2025-06-18und2025-03-26(mitinitialize). - Nur vom Server: Anfragen mit Browser-
Originwerden mit 403 abgewiesen.
Werkzeuge (tools/list zeigt nur die, die dein Schlüssel darf):
- kb_suchen (
read) –projekt,frage(höchstens 500 Zeichen),n(1–10, Vorgabe 5). Durchsucht die Wissensdatenbank; höchstens 20 Suchen je Minute und Schlüssel. - gespraeche_auflisten (
read) –projekt,status,seit(ISO-Zeit),limit(höchstens 100),vor_id. - gespraech_lesen (
read) –id,limit(höchstens 200, Vorgabe 100). - nachricht_senden (
write) –gespraech,text(höchstens 4000 Zeichen), optionalals(E-Mail eines Agenten, der im Projekt antworten darf). Stellt sofort als Agentennachricht zu; der Assistent verstummt in diesem Gespräch. - wissensluecken (
read) –projekt,stand(offen,erledigt,ignoriert),limit(höchstens 60).
Ohne besucherdaten:lesen werden Name, E-Mail und Telefon der Besucher gekürzt und persönliche Daten in Texten maskiert. Werkzeugfehler kommen als isError: true mit Kennungen wie project_not_found, conversation_not_found, conversation_closed, disabled, bad_argument, too_long, search_rate_limited.
Beispiel-Eintrag für einen MCP-Client:
{
"mcpServers": {
"reactive-chat": {
"url": "https://reactive.chat/v1/mcp",
"headers": { "Authorization": "Bearer rc_live_..." }
}
}
}
MCP und die Besucherliste sind neue Funktionen; sie können je Projekt abgeschaltet sein (das betroffene Projekt meldet dann disabled).
Was es nicht gibt
- Keine persönlichen Agenten-Tokens und keine Test-Schlüssel; alle Schlüssel sind Workspace-Schlüssel
rc_live_. - Keine Endpunkte zum Anlegen von Gesprächen, zum Schreiben im Namen von Besuchern oder zum Ändern von Projekteinstellungen, Regeln oder Wissensdatenbank.
- Kein CORS – die API ist nicht für Browser gedacht.
Weiter: Webhooks · Integrationen und Kanäle
Stand: