/api/voice/start#Oeffnet einen neuen VoiceCall-Eintrag und gibt dessen ID zurueck.
{
"branch": "shop",
"flowId": "optional flow id"
}{
"callId": "ck0123abc...",
"startedAt": "2026-05-18T09:32:11.123Z"
}API-Referenz
47 oeffentliche Endpoints aus app/api/*. Jede Route mit Request- und Response-Beispiel sowie einem Try-it-Button, der einen kopierbaren cURL-Snippet generiert. Source-of-Truth bleibt die jeweilige route.ts.
Strukturierte Quelle: lib/api/endpoints.ts - Ergaenze dort einen Eintrag, wenn eine neue Route dazukommt.
Voice-Pipeline: Call eroeffnen, Audio-Chunks streamen, Call beenden, Persona-Greeting, NPS.
/api/voice/start#Oeffnet einen neuen VoiceCall-Eintrag und gibt dessen ID zurueck.
{
"branch": "shop",
"flowId": "optional flow id"
}{
"callId": "ck0123abc...",
"startedAt": "2026-05-18T09:32:11.123Z"
}/api/voice/audio#Ein Audio-Chunk durch die volle Pipeline (Whisper -> Claude+Tools -> ElevenLabs).
Multipart-Upload. maxDuration=60s.
multipart/form-data
audio: File (webm/opus)
callId: string
branch: "shop" | "b2b" | "dienstleister"{
"transcript": { "user": "...", "agent": "..." },
"audioBase64": "...",
"toolCalls": [
{ "name": "shop_get_order", "input": { "orderNumber": "1042" }, "result": { ... } }
],
"latencyMs": 1820
}/api/voice/end#Schliesst den Call ab. Schreibt durationMs / latencyMs / WER (wenn Reference-Transcript dabei).
{
"callId": "ck0123abc...",
"taskCompleted": true,
"referenceTranscript": "optional reference"
}{ "ok": true, "durationMs": 32100, "wer": 0.07 }/api/voice/nps#Speichert NPS-Score (0-10) + optionalen Kommentar nach Call-Ende.
{ "callId": "ck0123abc...", "score": 9, "comment": "klappt" }{ "ok": true }/api/voice/greeting#Synthetisiert die Persona-Greeting-Zeile via ElevenLabs (mp3, base64).
Budget-Check absichtlich skipped (~0.001 EUR/Call).
{ "branch": "shop" }{
"persona": { "id": "lara", "name": "Lara", "tone": "freundlich", "greetingText": "..." },
"audioBase64": "...",
"mimeType": "audio/mpeg"
}/api/voice/calls?branch=shop&limit=50#Liste der letzten VoiceCalls fuer /admin und /eval.
limit max 500. Beide Query-Params optional.
[
{
"id": "ck0123abc",
"branch": "ECOMMERCE",
"durationMs": 32100,
"latencyMs": 1820,
"startedAt": "2026-05-18T09:32:11.123Z"
}
]Tool-Dispatch fuer Mock-Shop, Demo-ERP, Calendar, Gmail und Mailbox. Wird von der Voice-Pipeline und vom Flow-Builder genutzt.
/api/connectors/mockshop#Fuehrt eines der shop_*-Tools aus. Read by default, Write nur mit Permissions.
{
"toolName": "shop_get_order",
"args": { "orderNumber": "1042" },
"permissions": { "canRead": true, "canWrite": false }
}{
"ok": true,
"result": { "orderNumber": "1042", "status": "SHIPPED", "totalEur": 49.9 }
}/api/connectors/mockshop/admin#Vier Shop-Admin-Tools (Search / Invoice / Overdue / UpdateNote).
{ "toolName": "shop_admin_list_overdue_invoices", "args": {} }{ "ok": true, "result": [ { "orderNumber": "1042", "overdueDays": 14 } ] }/api/connectors/erp#Demo-ERP / B2B-Tools (Customer, Order, Tickets).
{
"toolName": "erp_create_ticket",
"args": { "customerId": "c1", "subject": "Lieferung verspaetet", "priority": "HIGH" },
"permissions": { "canRead": true, "canWrite": true }
}{ "ok": true, "result": { "ticketId": "t-123", "status": "OPEN" } }/api/connectors/erp/lager#Fuenf Inventory-fokussierte ERP-Tools (Check / LowStock / Reserve / Release / Adjust).
{ "toolName": "erp_inventory_check", "args": { "sku": "SKU-1" } }{ "ok": true, "result": { "sku": "SKU-1", "available": 42, "reserved": 3 } }/api/connectors/calendar#Calendar-Tools (Available / Book / Reschedule / Upcoming).
{ "action": "book", "input": { "slotId": "2026-05-20T10:00" } }{ "ok": true, "result": { "meetingId": "m-7", "startsAt": "2026-05-20T10:00:00Z" } }/api/connectors/gmailSession#Gmail-Tools (Send / ListRecent / Search). Echter OAuth-Connector.
{ "action": "search", "input": { "query": "from:alice@example.com newer_than:7d" } }{
"ok": true,
"result": [
{ "id": "msg_123", "subject": "Re: Angebot", "from": "alice@example.com" }
]
}/api/connectors/mailbox#Demo-Mailbox-Tools (List / Get / Search / Reply / Mark / Archive / Star).
{
"toolName": "mailbox_send_reply",
"args": { "threadId": "thread_1", "body": "Danke fuer Ihre Nachricht..." }
}{ "ok": true, "result": { "messageId": "msg_456" } }/api/connectors/[type]/activateSession#Setzt einen Mock-Connector (mockshop / erp / calendar) im Onboarding auf CONNECTED.
Kein Body. type kommt aus der URL. Gmail laeuft separat via OAuth.
{ "ok": true, "type": "MOCK_SHOP", "status": "CONNECTED" }Cookie-basierter Warenkorb + Demo-Checkout. Schreibt in dieselbe Tabelle, aus der die Shop-Tools lesen.
/api/shop/cart#Aktuelle CartView (read-only, Cookie-basiert).
{
"items": [
{ "sku": "SKU-1", "title": "Espresso 1kg", "quantity": 2, "priceEur": 12.5 }
],
"totalEur": 25
}/api/shop/cart/add#Item zum Cart hinzufuegen.
{ "sku": "SKU-1", "quantity": 2 }{ "items": [ { "sku": "SKU-1", "quantity": 2 } ], "totalEur": 25 }/api/shop/cart/update#Menge fuer eine SKU setzen. quantity=0 entfernt das Item.
{ "sku": "SKU-1", "quantity": 3 }{ "items": [ { "sku": "SKU-1", "quantity": 3 } ], "totalEur": 37.5 }/api/shop/cart/remove#SKU komplett aus dem Cart entfernen.
{ "sku": "SKU-1" }{ "items": [], "totalEur": 0 }/api/shop/cart/clear#Cart komplett leeren.
{ "items": [], "totalEur": 0 }/api/shop/checkout#Demo-Checkout. Schreibt Order + OrderItems und leert den Cart.
{
"customerName": "Anna Beispiel",
"email": "anna@example.com",
"address": "Musterstrasse 1, 80331 Muenchen"
}{ "orderNumber": "1042" }Demo-Webmail-UI Endpoints. Gleicher Datentopf wie die mailbox_* MCP-Tools.
/api/demo/mailbox/list#Mailbox-Snapshot (Threads + Stats). Vom UI alle 15s gepollt.
{
"threads": [ { "id": "thread_1", "subject": "Angebot", "unread": true } ],
"stats": { "unread": 3, "total": 27 }
}/api/demo/mailbox/thread?id=thread_1#Einzelnen Thread inklusive aller Messages laden.
{
"id": "thread_1",
"subject": "Angebot",
"messages": [ { "id": "msg_1", "from": "alice@example.com", "body": "..." } ]
}/api/demo/mailbox/reply#Antwort an einen Thread senden.
{ "threadId": "thread_1", "body": "Vielen Dank fuer Ihre Anfrage..." }{ "ok": true, "messageId": "msg_789" }/api/demo/mailbox/archive#Thread archivieren.
{ "threadId": "thread_1" }{ "ok": true }/api/demo/mailbox/star#Stern fuer einen Thread setzen / entfernen.
{ "threadId": "thread_1", "starred": true }{ "ok": true }Auswertung der Bachelor-Studie (Stats, WER, NPS) + Cost-Tracking gegen das Monatsbudget.
/api/eval/stats?branch=shop&dateFrom=2026-05-01&dateTo=2026-05-31#Aggregierte Stats (mean latency, WER, NPS, Task-Completion).
{
"count": 42,
"meanLatencyMs": 1820,
"meanWer": 0.08,
"npsScore": 8.4,
"taskCompletionRate": 0.93
}/api/eval/calls?branch=shop&page=1&pageSize=20#Paginierte Liste der Calls fuer /eval.
{
"data": [
{ "id": "ck01", "startedAt": "2026-05-18T09:32:11Z", "latencyMs": 1820, "nps": 9 }
],
"total": 42
}/api/eval/calls/[id]#Vollstaendige Call-Details (Transcript + Tool-Calls).
{
"id": "ck01",
"transcript": [ { "speaker": "user", "text": "..." } ],
"toolCalls": [ { "name": "shop_get_order", "result": {} } ],
"nps": { "score": 9, "comment": "klappt" }
}/api/eval/export?branch=shop#CSV-Export fuer den BA-Appendix.
text/csv
id,startedAt,branch,durationMs,latencyMs,wer,taskCompleted,npsScore,npsComment,toolCallsCount
ck01,2026-05-18T09:32:11Z,ECOMMERCE,32100,1820,0.07,true,9,klappt,3/api/eval/tool-counts?branch=shop&days=30#Aggregierte Tool-Call-Haeufigkeiten (fuer Eval-Bar-Charts).
{
"counts": [
{ "toolName": "shop_get_order", "count": 18 },
{ "toolName": "shop_request_return", "count": 4 }
]
}/api/cost#Monatsverbrauch (EUR) und verbleibendes Budget, per Provider.
{
"monthlyEur": 7.42,
"budgetEur": 40,
"remainingEur": 32.58,
"percentage": 18.55,
"byProvider": { "anthropic": 5.2, "elevenlabs": 1.8, "openai_whisper": 0.42 }
}CRUD fuer Flow-Definitionen (Reactflow-Graphen) und ihre Tool-Permissions.
/api/flowsSession#Liste aller Flows (Presets + Custom).
[
{
"id": "flow_1",
"name": "Shop Standard",
"branch": "ECOMMERCE",
"isPreset": false,
"updatedAt": "2026-05-18T09:32:11Z"
}
]/api/flowsSession#Neuen Flow anlegen.
{
"name": "Mein Flow",
"branch": "shop",
"graph": { "nodes": [], "edges": [] },
"permissions": []
}{ "id": "flow_42", "name": "Mein Flow" }/api/flows/[id]Session#Einzelnen Flow inkl. Permissions laden.
{
"id": "flow_42",
"name": "Mein Flow",
"graph": { "nodes": [], "edges": [] },
"permissions": []
}/api/flows/[id]Session#Flow ueberschreiben (Graph + Permissions).
{
"name": "Mein Flow v2",
"graph": { "nodes": [], "edges": [] },
"permissions": []
}{ "ok": true }/api/flows/[id]Session#Flow inkl. Permissions loeschen.
{ "ok": true }Magic-Link Callback, Test-Login, Sign-out und Account-Operationen (Profil, Avatar, Soft-Delete).
/api/auth/callback?code=...&next=/onboarding#Magic-Link / OAuth-Callback. Tauscht code gegen Session-Cookies.
302 -> next/api/auth/signout?next=/Session#Aktuelle Supabase-Session beenden.
302 -> next/api/auth/test-login#One-Click-Login als Test-User (nur Demo).
{ "ok": true, "redirectTo": "/demo/shop" }/api/account/profileSession#Display-Name + Avatar des eigenen Profils aktualisieren.
{ "displayName": "Philipp", "avatarUrl": "https://..." }{ "ok": true, "profile": { "displayName": "Philipp", "avatarUrl": "..." } }/api/account/avatarSession#Avatar-Bild als data: URI im Profil speichern (max 1 MB).
multipart/form-data
file: File (image/jpeg|image/png|image/webp){ "ok": true, "avatarUrl": "data:image/png;base64,..." }/api/account/deleteSession#Soft-Delete des Profils + Hard-Delete in auth.users (wenn Service-Role-Key gesetzt).
{ "ok": true }Health-Snapshot, SSE-Realtime-Bus, Onboarding-Flag, Client-Error-Logging, Demo-Reset.
/api/health#Health-Snapshot (200 ok / 503 degraded).
{
"ok": true,
"checks": [
{ "name": "postgres", "status": "ok", "latencyMs": 4 },
{ "name": "anthropic", "status": "ok" }
]
}/api/realtime?channel=shop&channel=erp#Server-Sent-Events Stream. Channel-Param wiederholbar (oder '*').
text/event-stream
event: tool.executed
data: { "toolName": "shop_request_return", "branch": "shop", "result": { ... } }/api/onboarding/completeSession#Onboarding-Flag setzen + preferredBranch persistieren.
{ "preferredBranch": "shop" }{ "ok": true }/api/log/error#Client-seitige Errors aus den Route-Error-Boundaries entgegennehmen.
Antwortet immer 200 (logging soll nie failen).
{
"message": "...",
"stack": "...",
"url": "...",
"userAgent": "..."
}{ "ok": true }/api/demo/reset?scope=shop#Demo-Daten zuruecksetzen (Shop, ERP, Mailbox, Calendar).
scope = shop | erp | mailbox | calendar | all.
{
"ok": true,
"scope": "shop",
"durationMs": 245,
"cleared": { "orders": 12, "items": 31 }
}