Endpunkte für Einbindungen im Browser, aufgerufen mit dem Client API Key.
Client API Key
Dieser Key gehört ins Frontend und ist dort für jeden lesbar — das ist so vorgesehen. Er benennt Ihren Assistenten, er schützt nichts: Welche Unterhaltung eine Anfrage erreicht, entscheidet allein das Session-Token, das der Server vergibt und signiert. Aus einem fremden Browser scheitert der Key an Ihren erlaubten Domains; wie viel mit ihm insgesamt möglich ist, begrenzen Anfragegrenzen und das Tagesbudget Ihres Arbeitsbereichs.
Session-Token
Die Unterhaltung wird über den Header X-Session-ID zugeordnet. Dessen Wert vergibt der Server: Bei einer Anfrage ohne gültiges Token antwortet er mit einem neuen im gleichnamigen Response-Header. Speichern Sie diesen Wert und schicken Sie ihn bei jeder weiteren Anfrage mit. Solange die Unterhaltung läuft, wird das Token gelegentlich erneuert — der Response-Header trägt dann einen neuen Wert, der den alten ersetzt. Eine selbst erzeugte ID wird nicht angenommen; die Anfrage landet dann in einer neuen, leeren Unterhaltung.
Nur aus dem Browser
Die Endpunkte, die etwas auslösen, verlangen einen Origin-Header: /api/chat, /api/chat/graph/continue, /api/chat/attachments, /api/transcribe, /api/booking und der Formular-Submit. Diesen Header setzt der Browser selbst, er lässt sich im Code nicht ergänzen. Aufrufe aus einem Skript, einer nativen App oder von einem Server bekommen deshalb 403 origin header required. Für solche Aufrufe ist die Server API mit dem Server Key gedacht.
/api/chatSendet eine Nachricht und empfängt die Antwort als Server-Sent Events Stream. Jedes Event enthält ein Content-Fragment. Das letzte Event ist immer data: [DONE]. Welche Unterhaltung gemeint ist, entscheidet das Session-Token — siehe oben.
// Request
POST /api/chat
Authorization: Bearer YOUR_API_KEY
// Weglassen, wenn noch keins vorliegt — die Antwort bringt dann eins mit.
X-Session-ID: <session-token>
// Optional, siehe "Identity Verification" unten. Beide Header nur setzen,
// wenn der Nutzer über window.go33.identify() verifiziert wurde — sonst
// beide weglassen, dann bleibt der Chat wie gewohnt anonym.
X-User-Id: <user-id>
X-User-Hash: <hmac-sha256-hex>
Content-Type: application/json
{ "query": "Wie kann ich euch kontaktieren?" }
// Response: text/event-stream
data: {"content":"Sie"}
data: {"content":" können"}
data: {"content":" uns..."}
data: [DONE]JavaScript Beispiel
// Vom Server vergeben, nicht selbst erzeugt.
const token = localStorage.getItem("chat_session") ?? "";
const res = await fetch("https://go33.de/api/chat", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_KEY",
...(token ? { "X-Session-ID": token } : {}),
},
body: JSON.stringify({ query: "Hallo!" }),
});
// Beim ersten Aufruf und bei jeder Erneuerung steht hier ein neuer Wert.
const issued = res.headers.get("X-Session-ID");
if (issued) localStorage.setItem("chat_session", issued);
const reader = res.body.getReader();
const decoder = new TextDecoder();
let output = "";
while (true) {
const { done, value } = await reader.read();
if (done) break;
for (const line of decoder.decode(value).split("\n")) {
if (line.startsWith("data: ") && line !== "data: [DONE]") {
const { content } = JSON.parse(line.slice(6));
output += content;
renderMessage(output);
}
}
}/api/chat/historyGesprächsverlauf laden oder löschen. Ohne gültiges Session-Token ist der Verlauf leer — es gibt keinen Weg, über eine fremde ID an eine fremde Unterhaltung zu kommen.
// Verlauf laden
GET /api/chat/history
Authorization: Bearer YOUR_API_KEY
X-Session-ID: <session-token>
// Response
{
"messages": [
{ "role": "user", "content": "Hallo!", "timestamp": "2024-01-01T..." },
{ "role": "assistant", "content": "Guten Tag!", "timestamp": "2024-01-01T..." }
]
}
// Verlauf löschen
DELETE /api/chat/history
Authorization: Bearer YOUR_API_KEY
X-Session-ID: <session-token>
// Response: 204 No Content/api/chat/configLiefert die Widget-Einstellungen — nützlich wenn das eigene UI Bot-Name, Farbe und Begrüßungstext übernehmen soll.
GET /api/chat/config
Authorization: Bearer YOUR_API_KEY
// Response
{
"bot_name": "KI-Assistent",
"welcome_message": "Hallo! Wie kann ich helfen?",
"primary_color": "#6366f1",
"language": "de"
}/api/chat/messages/{id}/feedbackBewertet eine einzelne Assistant-Nachricht als hilfreich oder nicht hilfreich (Daumen hoch/runter). Die Message-ID stammt aus dem SSE-Stream bzw. aus /api/chat/history.
POST /api/chat/messages/{id}/feedback
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{ "feedback": "up" }
// "feedback" ist entweder "up" oder "down"
// Response: 204 No ContentBild-Anhänge
Kunden können dem Chat ein Bild anhängen, sofern das für den Tenant konfigurierte KI-Modell Bildverständnis unterstützt (siehe Antworten KI-Modell). Der Upload läuft zweistufig: Bild hochladen, die zurückgegebene attachment_id anschließend im normalen /api/chat-Aufruf mitschicken.
/api/chat/attachmentsLädt ein einzelnes Bild hoch (JPEG, PNG oder WebP, max. 5 MB) und liefert eine attachment_id zurück. Wird das konfigurierte Modell kein Bildverständnis unterstützt, antwortet der Endpunkt mit 422.
POST /api/chat/attachments
Authorization: Bearer YOUR_API_KEY
X-Session-ID: <session-token>
Content-Type: image/jpeg
<Rohe Bilddaten als Request-Body, kein JSON/Multipart>
// Response
{ "attachment_id": "atc_...", "mime_type": "image/jpeg" }/api/chat/attachments/{id}Lädt die Bilddaten eines zuvor hochgeladenen Anhangs erneut, z. B. um ihn nach einem Seiten-Reload wieder anzuzeigen. Erreichbar nur mit dem Session-Token, unter dem das Bild hochgeladen wurde.
GET /api/chat/attachments/{id}
Authorization: Bearer YOUR_API_KEY
X-Session-ID: <session-token>
// Response: die Bilddaten mit passendem Content-TypeTerminbuchung
Endpunkte für eine eigene Terminbuchungs-Oberfläche, die dieselbe Verfügbarkeit und Konfiguration nutzt wie das Chat-Widget — siehe Terminbuchung einrichten.
Jeder dieser Endpunkte erwartet eine workflow_id: die Terminbuchung ist eine Aktion Ihres Assistenten, und ein Assistent kann mehrere davon haben — mit eigenen Leistungen, Zeiten und Kalendern. Die IDs Ihrer aktiven Aktionen liefert /api/chat/config im Feld workflows (Typ booking).
/api/booking/available-daysLiefert die Tage eines Monats mit mindestens einem freien Zeitfenster.
GET /api/booking/available-days?month=2026-08&workflow_id=wf_...
Authorization: Bearer YOUR_API_KEY
// Response
{ "available_days": [3, 4, 5, 10, 11, 12] }/api/booking/slotsLiefert die freien Zeitfenster eines einzelnen Tages.
GET /api/booking/slots?date=2026-08-03&workflow_id=wf_...
Authorization: Bearer YOUR_API_KEY
// Response
{ "slots": [{ "start": "2026-08-03T09:00:00Z", "end": "2026-08-03T09:30:00Z" }, ...] }/api/bookingBucht ein Zeitfenster verbindlich. Der Kunde erhält danach eine E-Mail mit Bestätigungslink — erst nach dessen Bestätigung wird der Termin final in den Kalender des Tenants eingetragen.
POST /api/booking
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
{
"name": "Max Mustermann",
"email": "max@example.com",
"phone": "+49 151 12345678",
"company": "",
"notes": "",
"booked_at": "2026-08-03T09:00:00Z",
"service_id": "",
"workflow_id": "wf_..."
}
// Response: 201 Created, das erstellte Appointment-ObjektIdentity Verification
Eingeloggte Website-Besucher gegenüber dem Chat als verifizierten Nutzer ausweisen — z.B. für personalisierten Support statt eines rein anonymen Chats.
Sicherheitshinweis
Das Identity Secret (Entwickler API-Schlüssel) gehört ausschließlich auf Ihren Server. Der HMAC-Hash muss serverseitig berechnet werden — würde der Browser ihn berechnen, könnte jeder Besucher sich selbst als beliebigen anderen Nutzer ausgeben.
window.go33.identify()Übergibt eine verifizierte Nutzer-ID ans Widget. Ihr eigenes Backend berechnet userHash = HMAC-SHA256(identity_secret, userId) und liefert beide Werte an Ihre Seite aus (z.B. serverseitig ins HTML gerendert), sobald der Nutzer eingeloggt ist. Kann vor oder nach dem Laden des Chat-Widgets aufgerufen werden — die Übergabe wird intern gepuffert, falls das Widget-iframe noch nicht bereit ist.
<script>
window.go33.identify({
userId: "{{USER_ID}}",
userHash: "{{USER_HASH}}", // serverseitig berechnet, siehe unten
});
</script>Server-seitige Hash-Berechnung
const crypto = require("crypto");
const userHash = crypto
.createHmac("sha256", process.env.GO33_IDENTITY_SECRET)
.update(userId)
.digest("hex");Verhalten bei falschem Hash
Passt der Hash nicht zur User-ID, lehnt der Chat die Anfrage mit 401 ab — es gibt keinen stillen Fallback auf anonym. Das verhindert, dass ein falsch oder gar nicht gesetzter Hash unbemerkt eine falsche Identität durchlässt; Fehler beim Setup werden so sofort in der Browser-Konsole sichtbar statt erst beim Kunden aufzufallen.
Client Actions
Die KI kann während eines Chats ein Ereignis auslösen, auf das Ihre Website direkt im Browser reagiert — z.B. eine Weiterleitung, ein eigenes Modal oder ein Tracking-Event.
Konfiguration
Client Actions werden im Admin-Dashboard unter Antworten Was er tun kann Client-Aktion angelegt: Beschreibung, Trigger-Stichwörter, ein frei wählbarer Aktionsname und optionale Parameter, die die KI aus der Nutzeranfrage extrahiert.
go33:actionWenn eine konfigurierte Client-Aktion während eines Chats ausgelöst wird, sendet das eingebettete Widget dieses Ereignis an Ihre Seite. go33 interpretiert Aktionsname und Parameter nie selbst — was damit passiert, entscheidet ausschließlich Ihr eigener Code.
// Variante 1: window.go33 API
window.go33.on("action", ({ action, parameters }) => {
if (action === "redirect") {
window.location.href = `/preise/${parameters.plan}`;
}
});
// Variante 2: natives CustomEvent
window.addEventListener("go33:action", (event) => {
const { action, parameters } = event.detail;
console.log(action, parameters);
});Kein window.go33 vorhanden?
window.go33 wird von widget.js beim Laden des Chat-Widgets angelegt. Prüfen Sie, dass das Embed-Skript (siehe Schnellstart) auf der Seite eingebunden ist, bevor Sie window.go33.on(...) aufrufen.
Bekannte Einschränkung: postMessage-Origin
go33 leitet Aktions-Payloads intern per postMessage mit targetOrigin "*" an Ihre Seite weiter, da das eingebettete Widget die Origin Ihrer Seite nicht zuverlässig im Voraus kennt. Führen Sie eine strikte Origin-Policy oder CSP, kontaktieren Sie uns für eine origin-spezifische Konfiguration.