Schnittstelle: Widget-Wege
Alle 14 Wege des Widgets unter /api/v1/public/widget/{key}: Einstellungen, Gespräch, Antwortstrom, Einwilligung, Auskunft, Löschung, Werkzeuge und Anhänge.
In einfacher Sprache
Das Chatfenster spricht über eigene Wege mit dem Dienst. Diese Wege brauchen keine Anmeldung. Der Schlüssel des Fensters legt den Assistenten fest. Eine Kennung bindet jeden Aufruf an ein Gespräch. Die Seite zeigt jeden Weg mit Feldern, Antwort und Fehlern. Über diese Wege sendet der Besucher Fragen und bewertet Antworten. Er kann ein Gespräch löschen und Dateien senden. Auch der Widerruf seiner Zustimmung läuft so.
Alle Themen der Dokumentation
Das Chatfenster spricht mit dem Dienst über 14 Wege unter https://app.xicbot.de/api/v1/public/widget/{key}. Eine Anmeldung brauchen sie nicht: Der Widget-Schlüssel im Pfad bestimmt den Assistenten, und die Gesprächskennung, die der Start eines Gesprächs zurückgibt, bindet jeden weiteren Aufruf an dieses Gespräch. Diese Seite beschreibt jeden Weg mit Anfragefeldern, Antwort und Fehlern. Wie das Chatfenster die Wege nutzt, zeigt Gespräch im Widget; die Wege außerhalb des Widgets stehen unter Öffentliche Wege.
Überblick
Die Pfade in der Tabelle folgen auf https://app.xicbot.de/api/v1/public/widget/{key}. Adresse, Fehlerformat und die Regeln für Aufrufe aus dem Browser beschreibt Grundlagen der Schnittstelle, die Zähler der Drosseln Grenzen der Schnittstelle.
| Methode | Pfad nach {key} | Zweck | Drossel |
|---|---|---|---|
| GET | / | Einstellungen des Widgets abrufen | widget |
| POST | /conversation | Gespräch beginnen | widget |
| GET | /conversation/{conversation} | Verlauf laden | widget |
| POST | /send | Frage senden, Antwort als Ereignisstrom | widget-send |
| POST | /conversation/{conversation}/revoke | Einwilligung widerrufen | widget |
| POST | /conversation/{conversation}/tool/{call}/confirm | Werkzeugaufruf bestätigen | widget-send |
| POST | /conversation/{conversation}/tool/{call}/reject | Werkzeugaufruf ablehnen | widget |
| POST | /conversation/{conversation}/tool/{call}/report | Ergebnis einer Formularhilfe melden | widget |
| POST | /conversation/{conversation}/message/{message}/rating | Antwort bewerten | widget |
| GET | /conversation/{conversation}/export | Auskunft über gespeicherte Daten | widget |
| DELETE | /conversation/{conversation} | Gespräch löschen | widget |
| POST | /conversation/{conversation}/attachment | Anhang hochladen | widget-send |
| GET | /conversation/{conversation}/attachment | Anhänge auflisten | widget |
| GET | /conversation/{conversation}/attachment/{attachment} | Anhang abrufen | widget |
Gemeinsame Regeln
Schlüssel im Pfad
Der Schlüssel {key} ist der Wert des Attributs data-xicbot im Einbaucode: 16 Zufallsbytes, geschrieben als 32 Zeichen aus 0 bis 9 und a bis f. Er ist kein Geheimnis, denn er steht im Quelltext jeder Seite mit dem Widget. Vor jedem Weg prüft der Dienst den Schlüssel und antwortet sonst so:
| Status | error | Bedeutung |
|---|---|---|
| 404 | unknown_widget | Kein Assistent mit diesem Schlüssel, das Widget ist abgeschaltet oder der Assistent ist nicht aktiv. |
| 404 | unknown_widget | Das Konto, zu dem der Assistent gehört, ist nicht aktiv. |
| 404 | demo_expired | Die Demo, zu der das Widget gehört, ist abgelaufen. |
Einen neuen Schlüssel erzeugt POST /api/v1/assistants/{id}/key mit der Rolle admin, siehe Anmeldung an der Schnittstelle. Der Dienst protokolliert den Wechsel zuerst. Gelingt das nicht, antwortet er mit 500 und not_logged, und der bisherige Schlüssel bleibt stehen. Sonst steht der neue Wert in key, und der alte Schlüssel ergibt ab dann unknown_widget. Tauschen Sie deshalb den Einbaucode auf allen Seiten, siehe Öffentlicher Schlüssel.
Drosseln und Deckel
Zwei Schichten begrenzen die Wege. Die benannte Drossel zählt je Besucher, gebildet aus der IP-Adresse des Besuchers (bei IPv6 den ersten 64 Bit) und dem Widget-Schlüssel: widget erlaubt 60 und widget-send 12 Aufrufe je Minute, siehe Grenzen je Besucher. Dahinter prüft der Dienst die Deckel des Widgets, deren Werte am Konto hängen.
- Der Deckel für Aufrufe gilt für Einstellungen, Start, Verlauf, Widerruf, Bewertung, Auskunft, Löschen, für Bestätigen, Ablehnen und Rückmelden eines Werkzeugaufrufs sowie für Hochladen, Auflisten und Abrufen von Anhängen. Die Vorgabe sind 60 Aufrufe je Minute und 2000 je Tag.
- Der Deckel für Fragen gilt nur für
POST send. Die Vorgabe sind 10 Fragen je Minute und 200 je Tag. - Jeder Deckel zählt auf dem Besucher und, wenn der Aufruf ein Gespräch nennt, zusätzlich auf diesem Gespräch. Das Gespräch kommt aus dem Pfad oder aus
conversation_idim Rumpf. Jeder der beiden Zähler kann abweisen; gezählt wird erst, wenn keiner abgewiesen hat. - Die Zeitfenster sind 60 Sekunden und 86.400 Sekunden. Ein Deckel unter 1 ist abgeschaltet.
Weist ein Deckel ab, lautet die Antwort 429 mit diesem Rumpf und dem Kopf Retry-After:
| Feld | Inhalt |
|---|---|
error | too_many_requests |
limit_per_min | Minutenwert des Deckels, der abgewiesen hat, als Zahl |
limit_per_day | Tageswert desselben Deckels |
wait | Sekunden bis zum nächsten Versuch; derselbe Wert steht in Retry-After |
Gesprächskennung
Der Start eines Gesprächs gibt conversation_id zurück, eine UUID. POST send und jeder Weg mit {conversation} im Pfad suchen das Gespräch über diese Kennung, den Assistenten des Schlüssels und den Kanal widget. Passt eines davon nicht, lautet die Antwort 404 mit not_found. Ein Gespräch eines anderen Assistenten oder aus einem anderen Kanal ist über das Widget also nicht erreichbar. Die Kennungen von Nachrichten, Werkzeugaufrufen und Anhängen sind ebenfalls UUIDs und werden nur innerhalb des genannten Gesprächs gesucht.
Aufrufe aus dem Browser
Die CORS-Regeln unter /api/v1/public/ lassen die Herkunft null zu. Das Chatfenster läuft in einem Rahmen mit sandbox="allow-scripts" ohne allow-same-origin, und ein solcher Rahmen sendet Origin: null. Welche Seiten ein Gespräch beginnen dürfen, entscheidet nicht CORS, sondern die Domainliste beim Start eines Gesprächs. Methoden, Köpfe und die Gültigkeit der Vorabfrage stehen unter Schnittstelle: Grundlagen.
Fehler
Fehler kommen als JSON mit einem Code in error; einige Wege legen weitere Felder dazu, die Tabellen unten nennen sie. Die Prüfung der Anfragefelder antwortet mit 422, einem Text in message und je Feld einer Liste in errors, siehe Fehlerformat. Werten Sie den Code aus, nicht den Text. Hat der Antwortstrom von POST send einmal begonnen, meldet er Fehler als Ereignis und nicht mehr als Status.
Einstellungen abrufen
GET /api/v1/public/widget/{key}/
Liefert Darstellung, Texte und Schalter des Widgets. Das Chatfenster ruft den Weg beim Laden auf und baut sich daraus auf. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Abfrageparameter | Pflicht | Regel |
|---|---|---|
host | nein | Rechnername der einbettenden Seite. Eine ganze Adresse wird auf den Rechnernamen gekürzt, in Kleinbuchstaben; was über 120 Zeichen hinausgeht, wird abgeschnitten. |
preview | nein | Wahrheitswert. Mit true merkt sich der Dienst die Einbindung nicht. |
language | nein | Sprachwunsch. Es zählen die ersten zwei Buchstaben, gültig sind de und en. |
Mit host und ohne preview merkt sich der Dienst Zeitpunkt und Rechnernamen der Einbindung, für denselben Rechnernamen höchstens alle 300 Sekunden. Gegen die Domainliste prüft dieser Weg host nicht; das geschieht erst beim Start eines Gesprächs.
language wirkt nur auf die Texte, die der Dienst selbst stellt: note, limit_notice und den Standardtext der Einwilligung. Begrüßung und Ansprache bleiben, wie sie im Assistenten stehen. Ohne gültigen Wunsch gilt en, wenn die aktive Fassung des Assistenten englisch ist, sonst de.
Die Antwort ist ein JSON-Objekt mit diesen Feldern:
| Feld | Inhalt |
|---|---|
title | Titel des Widgets; ohne eigenen Titel der Name des Assistenten |
color, position, vertical | Farbe und Ecke des Widgets als Zeichenketten |
offset_x, offset_y, width, height, scale, radius | Abstände, Breite, Höhe und Eckenradius in Pixel, Skalierung in Prozent (100 heißt unverändert), jeweils als ganze Zahl |
avatar | Adresse des Avatarbilds; eine leere Zeichenkette heißt kein Bild |
language | Sprache der aktiven Fassung, ohne Fassung de |
greeting | Begrüßung der aktiven Fassung, sonst leer |
outreach_rules | Regeln der proaktiven Ansprache; das Chatfenster wertet sie im Browser aus |
note | Hinweis auf die Maschine: „Sie schreiben mit einem automatischen Assistenten.“ |
limit_notice | Grenzenhinweis: „Hinweis: Dieser Assistent ist ein Programm, er kann sich irren und ersetzt keine persönliche Beratung durch unsere Mitarbeiterinnen und Mitarbeiter.“ |
consent | true, wenn der Assistent vor der ersten Nachricht eine Einwilligung verlangt |
consent_text | Eigener Einwilligungstext oder der Standardtext in der gewählten Sprache; null ohne Einwilligungspflicht |
attachments | true, wenn Besucher Dateien anhängen dürfen |
attachment_max_bytes | 5242880, also 5 MiB je Datei |
attachment_types | image/png, image/jpeg, image/webp, application/pdf |
attachment_max_count | 5 Anhänge je Gespräch |
forms | Formulare, die das Chatfenster ausfüllen darf, siehe unten |
ready | true, sobald der Assistent eine aktive Fassung hat |
Der Standardtext der Einwilligung lautet „Ich bin damit einverstanden, dass mein Gespräch gespeichert und zur Beantwortung meiner Frage verarbeitet wird.“ Die Grenzen der Anhänge stehen in der Antwort, damit das Chatfenster eine zu große Datei ablehnen kann, bevor sie hochgeladen wird.
Feld in forms | Inhalt |
|---|---|
tool | Schlüssel des Werkzeugs |
selector | Selektor des Formulars auf der Seite |
page | Seite, auf der das Formular steht; leer, wenn keine bestimmte Seite festgelegt ist |
fields | Liste der Felder mit name und type |
submit_allowed | true, wenn das Chatfenster das Formular auch absenden darf |
forms enthält höchstens 10 Einträge, geordnet nach dem Schlüssel des Werkzeugs: nur aktive Werkzeuge zum Ausfüllen von Formularen, die die öffentliche Rolle nutzen darf. Werte stehen darin keine; das Chatfenster trägt nur in die genannten Felder ein. Einrichtung unter Formulare vorausfüllen, die Regeln für outreach_rules unter Ansprache.
Gespräch beginnen
POST /api/v1/public/widget/{key}/conversation
Legt ein Gespräch im Kanal widget an und gibt seine Kennung zurück. Antwort 201 mit conversation_id. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Feld | Pflicht | Regel |
|---|---|---|
host | nein | Zeichenkette, höchstens 120 Zeichen. Rechnername der einbettenden Seite; eine ganze Adresse wird auf den Rechnernamen gekürzt. Leer oder null gilt als fehlend. |
visitor | nein | Zeichenkette, höchstens 64 Zeichen. Kennung des Besuchers aus dem Chatfenster; leer wird nicht gespeichert. |
viewport | nein | Einer der Werte handy, tablet, desktop, breit. |
consent | bei Einwilligungspflicht | Wahrheitswert. Nur der JSON-Wert true gilt als Einwilligung; 1 oder "1" bestehen die Feldprüfung, reichen aber nicht. |
language | nein | Zeichenkette, höchstens 35 Zeichen. Derselbe Sprachwunsch wie beim Abruf der Einstellungen; es zählen die ersten zwei Buchstaben, gültig sind de und en. Fehlt consent_text, wählt er den Einwilligungstext, über den der Prüfwert gebildet wird; gilt der gezeigte Text nicht mehr, wählt er die Sprache des geltenden Textes in der Antwort. Das Chatfenster schickt hier denselben Wunsch wie beim Abruf der Einstellungen. |
consent_text | nein | Zeichenkette, höchstens 2000 Zeichen. Der Einwilligungstext, so wie das Chatfenster ihn gezeigt hat; das Chatfenster schickt ihn mit. Er zählt nur bei Einwilligungspflicht und wenn er nicht leer ist. Verglichen wird mit dem geltenden Text beider Sprachen; Folgen von Leerraum gelten dabei als ein Leerzeichen, Leerraum am Anfang und Ende zählt nicht. Passt er, wird der Prüfwert über den Text in dieser Sprache gebildet. |
Der Dienst prüft in dieser Reihenfolge und bricht beim ersten Treffer ab:
-
Schritt 1
Felder prüfen
Ungültige Felder ergeben 422 mit
messageunderrors. -
Schritt 2
Aktive Fassung
Hat der Assistent keine aktive Fassung, lautet die Antwort 422 mit
no_version. -
Schritt 3
Deckel für Aufrufe
Ist der Deckel erreicht, folgt 429 mit
too_many_requests. -
Schritt 4
Domainliste
Passt
hostnicht zur Domainliste, lautet die Antwort 403 mithost_not_allowed. -
Schritt 5
Sperrliste
Ist die IP-Adresse des Besuchers gesperrt, folgt 403 mit
blocked. -
Schritt 6
Einwilligung
Verlangt der Assistent eine Einwilligung und fehlt
consent: true, lautet die Antwort 422 mitconsent_missing. Passt ein mitgeschickterconsent_textzu keinem geltenden Einwilligungstext, folgt 422 mitconsent_changed;consent_textträgt dann den geltenden Text in der Sprache, dielanguagewählt. Diese Prüfungen stehen vor dem Anlegen: Ohne die nötige Einwilligung legt der Dienst kein Gespräch an. -
Schritt 7
Anlegen
Erst jetzt legt der Dienst das Gespräch mit dem Status
openan und antwortet mit 201.
Ist die Domainliste des Assistenten leer, darf jede Seite ein Gespräch beginnen. Enthält sie Einträge, muss host angegeben sein und entweder einem Eintrag gleichen oder auf einen Punkt und einen Eintrag enden: Der Eintrag example.com deckt shop.example.com mit ab. Einträge trennt ein Komma oder ein Zeilenumbruch, verglichen wird in Kleinbuchstaben. Die Liste pflegen Sie unter Erlaubte Domains.
Gesperrte Besucher legen kein Gespräch mehr an; die Sperre greift, bevor ein Gespräch angelegt wird. Wie Sie Besucher sperren, steht unter Besucher sperren.
Verlangt der Assistent eine Einwilligung, speichert das Gespräch den Zeitpunkt in consent_at und einen Prüfwert in consent_hash. Der Prüfwert ist ein SHA-256 über den Einwilligungstext, den der Besucher in der gewählten Sprache sieht, die Fassung der Datenschutzhinweise und den Rechnernamen. Das ist der eigene Text des Assistenten, sonst der Standardtext der Sprache. Schicken Sie den gezeigten Wortlaut in consent_text mit, gilt die Sprache, deren Text er entspricht. Fehlt er, wählt language die Sprache wie beim Abruf der Einstellungen; ohne gültigen Wunsch gilt en, wenn die aktive Fassung englisch ist, sonst de. Senden Sie in diesem Fall denselben Wunsch wie beim Abruf der Einstellungen: Gilt der Standardtext, hielte der Prüfwert sonst den Wortlaut einer anderen Sprache fest als den angezeigten. Die Einwilligung hängt damit am Gespräch und nicht an einem Wert im Browser. Mehr unter Einwilligung.
Nach dem Anlegen löst der Dienst den Webhook conversation.started mit conversation_id, assistant_id und channel aus.
| Status | error | Bedeutung |
|---|---|---|
| 422 | message, errors | Ein Feld ist ungültig. |
| 422 | no_version | Der Assistent hat keine aktive Fassung. |
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 403 | host_not_allowed | host fehlt oder passt nicht zur Domainliste. |
| 403 | blocked | Die IP-Adresse des Besuchers ist gesperrt. |
| 422 | consent_missing | Einwilligung verlangt, consent ist nicht true. Es wurde nichts angelegt. |
| 422 | consent_changed | Der mitgeschickte consent_text passt zu keinem geltenden Einwilligungstext; consent_text in der Antwort trägt den geltenden Text. Es wurde nichts angelegt. |
Frage senden
POST /api/v1/public/widget/{key}/send
Speichert die Frage des Besuchers und antwortet mit einem Ereignisstrom. Die Gesprächskennung steht im Rumpf, nicht im Pfad. Zählt gegen den Deckel für Fragen, nicht gegen den für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget-send, 12 je Minute je Besucher, dazu der Deckel für Fragen
| Feld | Pflicht | Regel |
|---|---|---|
conversation_id | ja | Kennung aus dem Start, höchstens 64 Zeichen. |
text | ja | Die Frage, 1 bis 4000 Zeichen. |
suggested | nein | Wahrheitswert. true, wenn der Besucher eine vorgeschlagene Folgefrage gewählt hat; der Dienst vermerkt es an der Frage. |
Hat das Konto einen kleineren Längendeckel als 4000 Zeichen, gilt dieser. Die Frage wird gespeichert, bevor der Strom beginnt. Steht das Gespräch auf closed, öffnet die gespeicherte Frage es wieder: war es übergeben (escalated_at gesetzt), wird es escalated mit neuem escalated_at, sonst open; resolved_at wird leer. Ein Ereignis geht dabei nicht hinaus, und eine abgewiesene Frage öffnet nichts. Je Gespräch läuft höchstens eine Antwort; der Dienst belegt das Gespräch mit einer bedingten Aktualisierung. Endet ein Lauf nicht sauber, gibt die Belegung das Gespräch nach 180 Sekunden frei.
| Status | error | Bedeutung |
|---|---|---|
| 422 | message, errors | Ein Feld ist ungültig. |
| 429 | too_many_requests | Deckel für Fragen erreicht. |
| 404 | not_found | Kein Gespräch dieses Assistenten im Kanal widget mit dieser Kennung. |
| 403 | consent_revoked | Die Einwilligung wurde widerrufen. |
| 403 | consent_missing | Der Assistent verlangt eine Einwilligung, das Gespräch hat keine, etwa weil die Pflicht erst nach dem Start eingeschaltet wurde. |
| 403 | blocked | Die IP-Adresse des Besuchers oder dieses Gespräch ist gesperrt. |
| 422 | no_version | Die Fassung, mit der das Gespräch begonnen hat, besteht nicht mehr. |
| 409 | reply_in_progress | Für dieses Gespräch läuft schon eine Antwort. |
| 413 | input_too_long | Die Frage ist länger als der Längendeckel des Kontos; limit nennt den Deckel, length die Länge. |
Befehl in der Schale bash
curl -N https://app.xicbot.de/api/v1/public/widget/0123456789abcdef0123456789abcdef/send \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{"conversation_id":"9d1f6c2a-3b4e-4f5a-8c7d-1e2f3a4b5c6d","text":"Ich habe eine Frage zu meiner Bestellung."}'Ereignisstrom
Nach den Prüfungen antwortet der Weg mit Status 200, Content-Type: text/event-stream; charset=utf-8 und Cache-Control: no-cache, no-store. Jedes Ereignis besteht aus einer Zeile event: mit dem Namen, einer Zeile data: mit einem JSON-Objekt und einer Leerzeile. Umlaute und Schrägstriche stehen unmaskiert im JSON. Das Chatfenster sendet dazu Accept: text/event-stream. Wie es die Ereignisse darstellt, beschreibt Antwortstrom.
| Ereignis | Daten | Bedeutung |
|---|---|---|
start | conversation_id, question_id (null) | Erstes Ereignis jedes Stroms. |
text | t | Ein Stück der Antwort. Hängen Sie die Stücke in der Reihenfolge des Eingangs aneinander. |
tool | Werkzeugaufruf in Kurzform | Der Assistent hat ein Werkzeug genutzt oder schlägt einen Schritt vor, der eine Bestätigung braucht (needs_confirmation). Felder unter Werkzeugaufrufe. |
live | live (true), since | Ein Mitarbeiter hat das Gespräch übernommen; since ist der Zeitpunkt der Übernahme. |
error | code, dazu scope und retry_after oder limit | Die Antwort ist gesperrt, siehe Sonderfälle. |
model_switch | reason (transient) | Nach einer vorübergehenden Störung wird die Antwort anders erzeugt; der Strom läuft weiter. |
fallback | reason (transient oder error), transient | Die Antwort ist gescheitert; es folgt die hinterlegte Notfallantwort als text. |
revoked | reason (consent_revoked) | Die Einwilligung wurde während des Laufs widerrufen; die Antwort wird verworfen. |
citations | citations | Die Quellen, die die Antwort nutzt; nur wenn es welche gibt. Bei einer Antwort aus einem Frage-Antwort-Paar genau ein Beleg mit der Frage des Paares. |
contact_offer | offered (true) | Der Assistent bietet an, den Kontakt herzustellen. |
follow_ups | questions, dropped, checked, reason | Bis zu 3 vorgeschlagene Folgefragen; nur wenn welche übrig bleiben. checked sagt, ob sie gegen das Wissen geprüft wurden, dropped, wie viele dabei wegfielen. Ohne Prüfung ist reason no_knowledge (kein Wissen hinterlegt) oder no_tenant_context, sonst null. |
handoff | handoff (true), reason | Übergabe an einen Menschen empfohlen. reason ist assistant, conversation_limit oder nach der Themenprüfung ein Text, der die berührten Themen nennt, etwa Gesperrtes Thema: …; ohne einen solchen Text enforcement. |
redaction | text, reason (claims oder notice), bei claims auch count und gegebenenfalls parts | Ersetzt den bisher gezeigten Text ganz durch text. Haben Werkzeugaufrufe die Antwort unterbrochen, kann parts denselben Text in Stücken an diesen Stellen tragen; leere Stücke fallen weg. |
verification | state, claims, total | Ergebnis der Belegprüfung: skipped, no_claims, verified, unverified oder no_source. |
enforcement | state (clear oder enforced), topics, handover | Ergebnis der Themenprüfung. |
end | state, message_id, refused, citations | Letztes Ereignis des Stroms. |
citations, contact_offer, follow_ups, handoff mit assistant, redaction, verification und enforcement kommen nur, wenn die Antwort regulär zu Ende läuft. Ein gekürzter Strom sieht so aus:
Quelltext text
event: start
data: {"conversation_id":"9d1f6c2a-3b4e-4f5a-8c7d-1e2f3a4b5c6d","question_id":null}
event: text
data: {"t":"Gern helfe ich Ihnen "}
event: text
data: {"t":"bei Ihrer Bestellung."}
event: verification
data: {"state":"no_claims","claims":[],"total":0}
event: enforcement
data: {"state":"clear","topics":[],"handover":false}
event: end
data: {"state":"done","message_id":"4b8e2f10-6c3d-4a5e-9f7b-2d1c0e9a8b76","refused":false,"citations":[]}Sonderfälle
Die Frage ist in jedem dieser Fälle gespeichert, bevor der Strom beginnt.
- Übernahme: Hat ein Mitarbeiter das Gespräch übernommen, folgen auf
startnurliveundendmitstategleichliveundmessage_idgleichnull. Die Antwort schreibt der Mitarbeiter, siehe Gespräch übernehmen. - Kontingent erschöpft: Es folgen
errormitcodegleichquota_exhausted,scopegleichmonthundretry_afterin Sekunden bis zum Monatswechsel, dann die Notfallantwort alstextundendmitblocked. Der Status bleibt 200; eine 429 für das Kontingent gibt es nur im Kanal der Integrationsschnittstelle. Siehe Kontingent erschöpft. - Gesprächsdeckel: Hat der Besucher in diesem Gespräch schon so viele Fragen gestellt, wie der Deckel des Kontos erlaubt, folgen
errormitconversation_limitundlimit, ein Hinweis alstext,handoffmitconversation_limitundendmitblocked. Die Vorgabe sind 60 Fragen, der Wert 0 schaltet den Deckel ab. - Störung: Bei einer vorübergehenden Störung kann
model_switchkommen, und die Antwort läuft weiter. Scheitert sie, folgenfallback, die Notfallantwort alstextundendmitfallback. - Widerruf während des Laufs: Bei Gesprächen mit Einwilligung prüft der Lauf höchstens einmal je Sekunde und noch einmal am Ende, ob die Einwilligung widerrufen wurde. Dann verwirft er die Antwort und sendet
revokedsowieendmitrevoked. - Antwort aus einem Frage-Antwort-Paar: Trifft die Frage ein aktives Paar, wird kein Modell gefragt. Auf
startfolgen die Antwort des Paares in einem einzigentext,citationsmit genau einem Beleg (die Frage des Paares alsdocument,chunk_idausqa:und der Kennung des Paares) undenforcement; berührt die Frage ein gesperrtes Thema oder ein Tabu, könnenredactionmitnotice, ein Hinweis als weiterestextundhandofffolgen. Zum Schluss kommtendmitdone.verification,follow_upsundcontact_offergibt es dabei nicht. Siehe Frage-Antwort-Paare. - Nachbearbeitung:
redactionersetzt den gezeigten Text. Mitclaimsstehen an Stelle unbelegter Aussagen die Platzhalter[nicht belegt]oder[not backed], mitnoticehat die Themenprüfung den Text umgeschrieben. Nachenforcementkann ein Hinweis als weiterestextfolgen, ebenso ein Hinweis auf unbelegte Aussagen, wenn der Assistent nur aus seinem Wissen antworten darf.
state in end | Bedeutung |
|---|---|
done | Die Antwort ist regulär zu Ende gelaufen. |
fallback | Statt der Antwort steht die Notfallantwort im Gespräch. |
revoked | Die Einwilligung wurde während des Laufs widerrufen; die Antwort ist verworfen. |
blocked | Kontingent erschöpft oder Gesprächsdeckel erreicht. |
live | Ein Mitarbeiter hat das Gespräch übernommen. |
message_id ist die Kennung der gespeicherten Antwort; mit ihr bewerten Sie die Antwort. Wurde nichts gespeichert, ist der Wert null. refused ist nur bei done true, wenn der Assistent die Frage abgelehnt hat. citations nennt die Quellen des Laufs.
Verlauf laden
GET /api/v1/public/widget/{key}/conversation/{conversation}
Liefert den bisherigen Verlauf, damit das Chatfenster nach einem Neuladen der Seite dort weitermacht, wo der Besucher war. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
Die Antwort enthält messages und taken_over. messages besteht aus den jüngsten 50 Nachrichten und den jüngsten 50 Werkzeugaufrufen, gemeinsam aufsteigend nach Zeit sortiert. taken_over ist true, solange ein Mitarbeiter das Gespräch übernommen hat. Ist das Gespräch unbekannt, lautet die Antwort 404 mit not_found.
| Eintrag | Felder |
|---|---|
| Frage des Besuchers | role (user), text, citations |
| Antwort des Assistenten | role (assistant), text, citations, id, rating (null, 0 oder 1) |
| Nachricht eines Mitarbeiters | role (operator), text, citations, id |
| Werkzeugaufruf | id (w und die Kennung des Aufrufs), role (tool), tool mit dem Aufruf in Kurzform |
Einwilligung widerrufen
POST /api/v1/public/widget/{key}/conversation/{conversation}/revoke
Widerruft die Einwilligung für dieses Gespräch. Der Besucher braucht dafür kein Konto, nur die Gesprächskennung. Ein Rumpf ist nicht nötig. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
Die Antwort lautet {"revoked": true, "run_aborted": …}. run_aborted ist true, wenn das Gespräch in diesem Moment für eine Antwort belegt war; ein laufender Lauf verwirft die Antwort dann und endet mit revoked. Der Widerruf wird einmal gesetzt: Ein zweiter Aufruf antwortet gleich und ändert den Zeitpunkt nicht. Mehr unter Widerruf.
| Weg nach dem Widerruf | Ergebnis |
|---|---|
POST send | 403 mit consent_revoked |
| Antwort bewerten | 403 mit consent_revoked |
| Anhang hochladen | 422 mit consent_revoked |
| Verlauf, Auskunft, Löschen | bleiben erreichbar |
Widerruf, Auskunft und Löschen stehen auch gesperrten Besuchern offen; die Sperrliste prüft der Dienst nur beim Start, beim Senden und beim Hochladen eines Anhangs.
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 404 | not_found | Gespräch unbekannt. |
| 422 | without_consent | Das Gespräch wurde ohne Einwilligung begonnen; es gibt nichts zu widerrufen. |
Antwort bewerten
POST /api/v1/public/widget/{key}/conversation/{conversation}/message/{message}/rating
Speichert die Bewertung einer Antwort des Assistenten. {message} ist message_id aus dem Ereignis end oder id aus dem Verlauf. Antwort {"message": {"id": …, "rating": …}}. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Feld | Pflicht | Regel |
|---|---|---|
rating | ja, darf null sein | 1 für Ja, 0 für Nein auf „War das hilfreich?“; null nimmt die Bewertung zurück. |
Der Deckel wird vor den Feldern geprüft. Mit der Note speichert der Dienst den Zeitpunkt; null löscht beides. Wie das Chatfenster die Knöpfe zeigt, steht unter Bewertung.
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 422 | message, errors | rating fehlt oder ist nicht null, 0 oder 1. |
| 404 | not_found | Gespräch unbekannt oder die Nachricht gehört nicht zu diesem Gespräch. |
| 403 | consent_revoked | Die Einwilligung wurde widerrufen. |
| 422 | not_rateable | Die Nachricht ist keine Antwort des Assistenten. |
Auskunft
GET /api/v1/public/widget/{key}/conversation/{conversation}/export
Liefert alles, was zu diesem Gespräch gespeichert ist, als JSON. Der Besucher braucht dafür kein Konto, nur die Gesprächskennung. Zählt gegen den Deckel für Aufrufe; ist das Gespräch unbekannt, lautet die Antwort 404 mit not_found.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Feld | Inhalt |
|---|---|
conversation | started, host, message_count, consent_at, consent_revoked_at |
messages | Alle Nachrichten, aufsteigend, mit role, text und time |
records.tool_calls | Werkzeugaufrufe in Kurzform |
records.requests | Anfragen mit name, email, phone, subject, time |
records.appointments | Termine mit starts_at, type, name, email, phone, status, time |
records.attachments | Anhänge mit denselben Feldern wie beim Auflisten |
records.carts | Warenkörbe mit items, subtotal_cents, discount_cents, coupon_code, shipping_cents, total_cents, currency, status, time |
controller | Name des Kontos, also des Betreibers der Seite, auf der das Widget läuft |
retention_days | Am Konto hinterlegte Aufbewahrungsdauer der Gespräche in Tagen oder null |
Zeitpunkte stehen im Format ISO 8601. Mehr zu den Rechten des Besuchers unter Auskunft.
Gespräch löschen
DELETE /api/v1/public/widget/{key}/conversation/{conversation}
Löscht das Gespräch. Der Besucher braucht dafür kein Konto, nur die Gesprächskennung. Antwort {"deleted": true, "messages": n} mit der Zahl der gelöschten Nachrichten. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
Die Löschung wird zuerst protokolliert: Der Protokolleintrag mit dem Auslöser visitor und den Anzahlen entsteht in derselben Datenbanktransaktion wie das Löschen und vor ihm. Kommt kein Eintrag zustande, löscht der Dienst nichts und antwortet mit 500 und not_logged. Was mit dem Gespräch zusammen gelöscht wird, beschreibt Was mit dem Gespräch geht.
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 404 | not_found | Gespräch unbekannt, auch nach einer bereits erfolgten Löschung. |
| 500 | not_logged | Der Protokolleintrag kam nicht zustande; es wurde nichts gelöscht. Versuchen Sie es später erneut. |
Werkzeugaufrufe
Schlägt der Assistent einen Schritt vor, der etwas verändert, oder ruft er ein lesendes Werkzeug mit der Freigabe mit Bestätigung auf, kommt im Strom ein Ereignis tool mit state gleich proposed und needs_confirmation gleich true. Ausgeführt wird der Schritt erst, wenn der Besucher ihn bestätigt: Der Bestätigungsweg ist der einzige, auf dem ein veränderndes Werkzeug im Widget läuft; der Antwortlauf selbst führt nur Lesendes aus. Die Karten im Chatfenster beschreibt Werkzeugkarten, die Werkzeuge selbst Werkzeuge.
Ereignis, Verlauf, Auskunft und die Wege dieses Abschnitts zeigen einen Aufruf in derselben Kurzform:
| Feld | Inhalt |
|---|---|
id | Kennung des Aufrufs, eine UUID |
key | Schlüssel des Werkzeugs |
kind | Art des Werkzeugs |
state | Zustand, siehe unten |
preview | Vorschau des Schritts für die Karte |
input | Eingaben des Aufrufs |
result | Ergebnis nach der Ausführung |
report | Rückmeldung einer Formularhilfe, sonst leer |
error | Im Widget der feste Text „Der Schritt konnte nicht ausgeführt werden.“, ohne Fehler null |
needs_confirmation | true im Zustand proposed |
chain_capped | true, wenn der Aufruf am Höchstwert von 5 Aufrufen je Antwort gescheitert ist |
created_at | Zeitpunkt des Aufrufs |
Dauer und Freigabeweg eines Aufrufs gibt das Widget nicht heraus, im Ergebnis auch nicht die Felder note und email_notified. Je Antwort laufen höchstens 5 Werkzeugaufrufe; ein weiterer endet mit failed und chain_capped gleich true.
state | Bedeutung |
|---|---|
proposed | Vorgeschlagen, wartet auf Bestätigung oder Ablehnung. |
confirmed | Bestätigt, die Ausführung läuft. |
executed | Ausgeführt; das Ergebnis steht in result. |
rejected | Vom Besucher abgelehnt. |
expired | Der Vorschlag ist älter als 60 Minuten und lässt sich nicht mehr bestätigen. |
failed | Gescheitert, etwa weil das Werkzeug inzwischen entfernt wurde oder Rolle, Paket oder Pflichtfelder nicht mehr passen. |
timeout | Die Ausführung hat ihre Zeitgrenze überschritten. |
Aufruf bestätigen
POST /api/v1/public/widget/{key}/conversation/{conversation}/tool/{call}/confirm
Bestätigt einen vorgeschlagenen Schritt und führt ihn aus. Kein Rumpf. Antwort {"call": …, "duplicate": …}. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget-send, 12 je Minute je Besucher, dazu die Deckel für Aufrufe
Zuerst setzt der Dienst einen Vorschlag, der älter als 60 Minuten ist, auf expired. Dann setzt er den Aufruf mit einer bedingten Aktualisierung von proposed auf confirmed; von zwei gleichzeitigen Klicks gewinnt nur einer. Beim Klick prüft er erneut, ob das Werkzeug noch besteht, ob Rolle und Paket es erlauben und ob die Pflichtfelder gefüllt sind; sonst endet der Aufruf mit failed. Die Ausführung endet mit executed, timeout oder failed.
duplicate ist true, wenn der Aufruf schon entschieden war oder ein anderer Klick gewonnen hat; der Schritt läuft dann kein zweites Mal. call zeigt in jedem Fall den aktuellen Stand, auch expired.
Aufruf ablehnen
POST /api/v1/public/widget/{key}/conversation/{conversation}/tool/{call}/reject
Lehnt einen vorgeschlagenen Schritt ab. Kein Rumpf. Antwort {"call": …, "duplicate": …} mit state gleich rejected; ein Vorschlag, der älter als 60 Minuten ist, wird stattdessen expired. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht (Bestätigen und Ablehnen). |
| 404 | not_found | Gespräch unbekannt oder der Aufruf gehört nicht zu diesem Gespräch. |
Rückmeldung zur Formularhilfe
POST /api/v1/public/widget/{key}/conversation/{conversation}/tool/{call}/report
Meldet, was das Ladeskript auf der Seite des Kunden mit einem ausgeführten Aufruf der Formularhilfe getan hat. Antwort {"report": …, "duplicate": …}. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Feld | Pflicht | Regel |
|---|---|---|
gefuellt | nein | Liste mit höchstens 20 Feldnamen zu je höchstens 80 Zeichen: eingetragene Felder |
fehlend | nein | Liste wie oben: Felder, die auf der Seite nicht gefunden wurden |
gesperrt | nein | Liste wie oben: Felder, die sich nicht füllen ließen |
abgesendet | nein | Wahrheitswert: das Formular wurde abgeschickt |
gefunden | nein | Wahrheitswert: das Formular wurde auf der Seite gefunden |
Der Rumpf ist JSON. Ohne JSON-Kopf liest der Dienst den rohen Rumpf bis 16384 Byte und wertet ihn als JSON aus; so kann das Ladeskript die Meldung als text/plain mit keepalive schicken. Eine solche Anfrage braucht keine Vorabprüfung und übersteht das Verlassen der Seite, etwa wenn das Formular die Seite beim Absenden wechselt.
Die Meldung ist eine Angabe der Seite des Kunden. Behalten werden nur Feldnamen, die in der Anweisung dieses Aufrufs stehen. Gespeichert wird report mit filled, missing, blocked, submitted und form_found; submitted ist nur true, wenn die Anweisung das Absenden vorsah und abgesendet gleich true ist. Angenommen wird die erste Meldung je Aufruf; jede weitere erhält duplicate gleich true und den schon gespeicherten Bericht. Was die Formularhilfe einträgt, beschreibt Formulare vorausfüllen.
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 422 | invalid_report | Rumpf ist kein JSON-Objekt oder ohne JSON-Kopf größer als 16384 Byte. |
| 422 | – | Ein Feld verletzt seine Regel; die Antwort trägt message und errors. |
| 404 | not_found | Gespräch oder Aufruf unbekannt, oder der Aufruf ist keine Formularhilfe. |
| 409 | not_executed | Der Aufruf ist nicht im Zustand executed. |
Anhänge
Besucher können Bilder und PDF-Dateien an ein Gespräch hängen, wenn der Assistent das erlaubt; eingeschaltet wird das unter Dateien vom Besucher. Wie der Besucher das im Widget erlebt, steht unter Anhänge im Gespräch. Alle drei Wege zählen neben der benannten Drossel gegen den Deckel für Aufrufe.
| Grenze | Wert |
|---|---|
| Größe je Datei | 5 MiB (5242880 Byte), mindestens 1 Byte |
| Anhänge je Gespräch | 5 |
| Arten | image/png, image/jpeg, image/webp, application/pdf |
Die Art bestimmt der Dienst am Inhalt der Datei, nicht an Endung oder Angabe des Browsers: PNG, JPEG, WebP und PDF werden an ihren ersten Bytes erkannt, alles andere wird abgewiesen. Auch die Größe misst er an der empfangenen Datei.
Anhang hochladen
POST /api/v1/public/widget/{key}/conversation/{conversation}/attachment
Nimmt eine Datei als multipart/form-data im Feld file an. Antwort 201 mit dem Anhang. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget-send, 12 je Minute je Besucher, dazu die Deckel für Aufrufe
| Feld | Inhalt |
|---|---|
id | Kennung des Anhangs (UUID) |
name | Bereinigter Dateiname |
mime | Die am Inhalt erkannte Art |
bytes | Größe in Byte |
sha256 | SHA-256 des Inhalts, hexadezimal |
lead_id | Kennung der Anfrage, an der der Anhang hängt, oder null |
time | Zeitpunkt des Hochladens, ISO 8601 |
Vom Dateinamen entfernt der Dienst Schrägstriche, umgekehrte Schrägstriche, Anführungszeichen und Steuerzeichen, behält nur den letzten Pfadteil und kürzt auf 120 Zeichen. Bleibt nichts übrig, heißt die Datei anhang.png, anhang.jpg, anhang.webp oder anhang.pdf.
Gibt es im Gespräch schon eine Anfrage, hängt der Anhang sofort an der jüngsten; lead_id trägt dann ihre Kennung. Entsteht die Anfrage erst später, übernimmt sie alle Anhänge des Gesprächs, deren lead_id noch leer ist. Das Hochladen wird in der Regel im Aktivitätsprotokoll mit Art und Größe festgehalten; kommt dieser Eintrag nicht zustande, bleibt der Anhang trotzdem gespeichert und die Antwort ist 201.
Die Prüfungen laufen in der Reihenfolge der Tabelle; die erste, die greift, bestimmt die Antwort. Die vier Abweisungen aus der Prüfung der Datei (upload_failed, too_large, too_many und type_not_allowed) tragen zusätzlich max_bytes, types und max_per_conversation, damit das Widget dem Besucher die Grenzen nennen kann.
| Status | error | Bedeutung |
|---|---|---|
| 429 | – | Benannte Drossel widget-send erreicht. |
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 403 | attachments_disabled | Der Assistent nimmt keine Dateien an. |
| 404 | not_found | Gespräch unbekannt. |
| 422 | consent_revoked | Die Einwilligung wurde widerrufen; das Gespräch nimmt nichts mehr auf. |
| 403 | blocked | Die IP-Adresse des Besuchers oder dieses Gespräch ist gesperrt. |
| 422 | file_missing | Die Anfrage enthält keine verwertbare Datei im Feld file. |
| 422 | upload_failed | Die Übertragung der Datei ist gescheitert. |
| 413 | too_large | Datei größer als 5 MiB oder leer. |
| 422 | too_many | Das Gespräch trägt schon 5 Anhänge. |
| 415 | type_not_allowed | Inhalt ist weder PNG, JPEG, WebP noch PDF. |
anhang.sh bash
curl -X POST \
https://app.xicbot.de/api/v1/public/widget/0123456789abcdef0123456789abcdef/conversation/9d1f6c2a-3b4e-4f5a-8c7d-1e2f3a4b5c6d/attachment \
-F 'file=@schaden.jpg'Anhänge auflisten
GET /api/v1/public/widget/{key}/conversation/{conversation}/attachment
Liefert {"attachments": […]} mit allen Anhängen des Gesprächs, nach Zeitpunkt aufsteigend, je Eintrag mit denselben Feldern wie beim Hochladen. Zählt gegen den Deckel für Aufrufe; ist das Gespräch unbekannt, lautet die Antwort 404 mit not_found.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
Anhang abrufen
GET /api/v1/public/widget/{key}/conversation/{conversation}/attachment/{attachment}
Liefert die Datei selbst als Download. Der Anhang muss zu diesem Gespräch gehören. Zählt gegen den Deckel für Aufrufe.
- Anmeldung
- Keine
- Begrenzung
widget, 60 je Minute je Besucher, dazu die Deckel für Aufrufe
| Kopfzeile | Wert |
|---|---|
Content-Type | Die erkannte Art, sonst application/octet-stream |
Content-Length | Größe in Byte |
Content-Disposition | attachment mit filename in ASCII und filename* in UTF-8 |
X-Content-Type-Options | nosniff |
Content-Security-Policy | default-src 'none'; sandbox |
Cache-Control | private, no-store, max-age=0 |
Referrer-Policy | no-referrer |
| Status | error | Bedeutung |
|---|---|---|
| 429 | too_many_requests | Deckel für Aufrufe erreicht. |
| 404 | not_found | Gespräch unbekannt oder der Anhang gehört nicht zu diesem Gespräch. |
| 410 | file_missing | Der Eintrag besteht, die Datei fehlt; die Antwort trägt zusätzlich measured gleich false. |
Häufige Fragen
Warum antwortet die Schnittstelle bei einem falschen Schlüssel mit 404 und nicht mit 403?
Ein unbekannter Schlüssel, ein abgeschaltetes Widget, ein inaktiver Assistent und ein inaktives Konto sehen von außen gleich aus: 404 mit unknown_widget. Wer einen Schlüssel rät, erfährt aus der Antwort nicht, ob er richtig geraten hat. Einzige Abweichung ist eine abgelaufene Demo, die demo_expired meldet.
Warum liefert das Senden einer Frage auch bei erschöpftem Kontingent den Status 200?
Der Antwortstrom hat zu diesem Zeitpunkt schon begonnen. Das Ereignis error mit code gleich quota_exhausted meldet die Lage, danach folgen die Notfallantwort und end mit blocked. Werten Sie darum die Ereignisse aus, nicht den Status.
Was geschieht mit einer laufenden Antwort, wenn der Besucher seine Einwilligung widerruft?
Der Lauf prüft während der Antwort und an ihrem Ende, ob widerrufen wurde. Dann verwirft er die Antwort und sendet revoked und end mit revoked. Weitere Fragen und Anhänge nimmt das Gespräch nicht mehr an.
Darf die Rückmeldung zur Formularhilfe mehrfach gesendet werden?
Ja, aber nur die erste Meldung je Aufruf wird gespeichert. Jede weitere erhält duplicate gleich true und den schon gespeicherten Bericht zurück.
Schützt die Liste der erlaubten Domains vor Aufrufen außerhalb des Browsers?
Nein. Die Liste hält das Widget von fremden Seiten fern, aber host ist eine Angabe des Aufrufers. Gegen Missbrauch wirken die Drosseln, die Deckel für Aufrufe und Fragen und das Sperren einzelner Besucher.
Selbst fragen, Assistent dieser Website
Automatischer Assistent