Schnittstelle: Grundlagen
Basisadresse und Fassung der XICBOT-Schnittstelle, Zugangszonen, Fehlerformen, Antwortköpfe, HTTPS, CORS, seitenweise Abfrage und wiederholte Anfragen.
In einfacher Sprache
Die Schnittstelle ist der Weg, über den andere Programme mit dem Dienst sprechen. Diese Seite gilt für alle ihre Wege. Sie nennt die Grundadresse und die Fassung. Sie zeigt, wie eine Anfrage aufgebaut ist. Sie zeigt auch, wie ein Fehler aussieht. Dazu kommen Regeln für sichere Verbindungen. Lange Listen kommen in Teilen. Die Seite sagt, was bei einer wiederholten Anfrage geschieht.
Alle Themen der Dokumentation
Diese Seite beschreibt, was für alle Wege der XICBOT-Schnittstelle gilt: Basisadresse und Fassung, Zugangszonen, Aufbau von Anfragen und Fehlern, HTTPS, Antwortköpfe, CORS, seitenweise Abfrage und das Verhalten bei wiederholten Anfragen. Die einzelnen Wege beschreiben die Seiten zu Anmeldung, Integration und den übrigen Bereichen.
Basisadresse und Fassung
Die Schnittstelle liegt unter https://app.xicbot.de/api/. Alle Fachwege tragen die Fassung v1 im Pfad, die Basisadresse für eigene Aufrufe ist also https://app.xicbot.de/api/v1/. Die Anwendung selbst und die Clients aus dem Werkzeugbausatz rufen dieselben Wege auf.
Ob die Schnittstelle arbeitet, zeigt ohne Anmeldung GET /api/v1/public/status. Der Weg meldet nur, ob die einzelnen Teile tragen, und nennt keine weiteren Einzelheiten. Mehr dazu unter Verfügbarkeit und Überwachung.
Eine Anbindung prüfen Sie am einfachsten mit dem Statusweg der Integration. Er ist der einzige Integrationsweg ohne eigenen Bereich und liest keine Daten:
Befehl in der Schale bash
curl https://app.xicbot.de/api/v1/integration/status \
-H 'Accept: application/json' \
-H 'X-Api-Key: xbot_…'Die Antwort nennt das Konto, die Bereiche und den Minutendeckel des Schlüssels. Ihre Felder beschreibt Schnittstelle: Integration, die Deckel Paketsperren und Drosseln.
Zugangszonen
Die Wege unter /api/v1/ sind in Zonen mit eigener Anmeldung gegliedert. Innerhalb einer Zone setzen einzelne Wege zusätzlich eine Rolle, ein Paketmerkmal oder einen Bereich des Schlüssels voraus.
| Zone | Pfade unter /api/v1/ | Anmeldung | Weitere Voraussetzungen | Beschreibung |
|---|---|---|---|---|
| Anmeldung | register, verify, login, password/forgot, password/reset | keine | - | Anmeldung |
| Öffentlich | public/status, public/changelog, public/accessibility, public/enquiry, public/demo, public/demo/{id}, invitation/{token}, invitation/accept, cart/pickup/{token} | keine | - | Öffentliche Wege |
| Widget | public/widget/{key}/… | Widget-Schlüssel im Pfad | - | Widget-Wege |
| Integration | integration/… | Kopf X-Api-Key | Paketmerkmal; dazu je Weg ein Bereich des Schlüssels, etwa conversations oder leads.write | Integration |
| Konto | me, logout, password, totp, webauthn, sessions, logins, confirmation/resend, tenant/switch | Authorization: Bearer | aktives Konto, außer bei tenant/switch und logout | Konto |
| Schlüssel und Webhooks | keys, webhooks | Authorization: Bearer | aktives Konto, Rolle Admin; Paketmerkmal zum Anlegen, Ändern und für die Probe | Schlüssel und Webhooks |
| Fachbereiche | knowledge, assistants, conversations, catalog, records/{type} und weitere | Authorization: Bearer | aktives Konto, bestätigte E-Mail-Adresse, je Weg Rolle oder Paketmerkmal | Wissen und Assistenten, Gespräche und Verwaltung |
| Aktivität | activity | Authorization: Bearer | aktives Konto, bestätigte E-Mail-Adresse, Rolle Admin | Team und Rollen |
Anfragen
- Schicken Sie Körper als JSON mit
Content-Type: application/jsonund fordern Sie mitAccept: application/jsonJSON an. So verfährt auch die Anwendung selbst. - Dateien, etwa für eine Wissensquelle vom Typ
file, gehen alsmultipart/form-data. Den KopfContent-Typesetzt dabei Ihr HTTP-Client samt Trennmarke; ein von Hand gesetzter Kopf ohne Trennmarke macht den Körper unlesbar. - Unter
/api/antworten Fehler auch ohneAccept-Kopf als JSON, nicht als HTML-Seite. - Wege der Anwendung melden sich mit
Authorization: Bearer <Marke>an, die Integration mit dem KopfX-Api-Key. Steht ein Schlüssel in der Adresse (?api_key=oder?key=), lehnt die Integration die Anfrage mit 400 undkey_in_urlab. Details stehen unter Anmeldung. - Zeitpunkte gibt die Schnittstelle als Zeichenkette nach ISO 8601 aus, etwa im Feld
created. - Antworten eines Assistenten, etwa auf
POST integration/chat, kommen als Datenstrom mitContent-Type: text/event-stream. Fehler, die vor dem Start feststehen, kommen als JSON mit passendem Status. Läuft der Strom bereits, steht ein Fehler als Ereignis im Strom, und der Status ändert sich nicht mehr. Der Python-Client aus dem Werkzeugbausatz fordert solche Antworten mitAccept: text/event-streaman. - Der Webserver bricht eine Anfrage ab, wenn die Anwendung 300 Sekunden lang keine Daten liefert. Stellen Sie die Zeitgrenze Ihres Clients für lange Antworten entsprechend ein.
Fehlerformat
Fehler kommen als JSON mit passendem HTTP-Status. Je nach Herkunft hat der Körper eine von fünf Formen:
| Form | Wann | Beispiel |
|---|---|---|
error mit Kennzeichen, teils mit weiteren Feldern | Fehler, die die Schnittstelle selbst feststellt: Schlüssel, Rolle, Paket, unbekannter Weg | {"error":"role_too_low","required":"admin"} |
message und errors | Feldprüfung der Eingaben, Status 422; errors nennt je Feld die Meldungen | {"message":"…","errors":{"email":["…"]}} |
error: "validation" und fields | eigene Prüfung nach der Feldprüfung, etwa eine schon vergebene Adresse bei der Registrierung | {"error":"validation","fields":{"email":["validation.unique"]}} |
nur message | etwa fehlende oder ungültige Sitzungsmarke (401) und allgemeine Drossel (429) | {"message":"…"} |
message: "Serverfehler" | unerwarteter Fehler mit Status 500 oder höher | {"message":"Serverfehler"} |
Bei einem unerwarteten Fehler mit Status 500 oder höher ersetzt die Schnittstelle den Text in message durch „Serverfehler“ und entfernt die Felder exception, file, line und trace. Eine Antwort ohne message bekommt dabei keine. Der Text einer Meldung mit Status 400 bis 499 bleibt erhalten, einschließlich der Feldfehler.
Statuscodes und Kennzeichen
| Status | Kennzeichen | Bedeutung |
|---|---|---|
| 400 | key_in_url | Integrationsschlüssel in der Adresse statt im Kopf; note nennt den richtigen Ort. |
| 401 | key_missing | Kopf X-Api-Key fehlt oder beginnt nicht mit xbot_. |
| 401 | invalid_key | Schlüssel unbekannt, zurückgezogen oder abgelaufen; die drei Fälle antworten gleich. |
| 401 | nur message | Sitzungsmarke fehlt oder gilt nicht mehr. |
| 402 | plan_feature_missing | Das Paket enthält das Merkmal nicht. Dazu feature, plan, plan_name und available_in mit den Paketen, die es enthalten. Siehe Pakete und Kontingente. |
| 402 | plan_limit_reached | Eine Mengengrenze des Pakets ist erreicht. Dazu limit, allowed, used, plan und plan_name. |
| 403 | role_too_low | Die Rolle reicht nicht; required nennt die nötige. Siehe Team und Rollen. |
| 403 | email_unverified | Die E-Mail-Adresse ist noch nicht bestätigt. |
| 403 | no_tenant, tenant_… | Kein Konto gewählt oder Konto nicht aktiv. Bei einem nicht aktiven Konto enthält das Kennzeichen dessen Zustand, und message lautet „Das Konto ist derzeit nicht aktiv.“ |
| 403 | tenant_suspended | Das Konto hinter dem Integrationsschlüssel ist nicht aktiv. |
| 403 | scope_missing, read_only | Dem Schlüssel fehlt der nötige Bereich; read_only, wenn ein Schreibbereich fehlt. required nennt den Bereich. |
| 403 | https_required | Anfrage über http mit einer anderen Methode als GET oder HEAD, die die Anwendung unverschlüsselt erreicht; siehe HTTPS. |
| 404 | route_unknown | Unbekannter Weg. |
| 404 | not_found | Datensatz nicht vorhanden. Kennungen aus einem anderen Konto ergeben ebenfalls 404. |
| 404 | unknown_widget, demo_expired | Widget-Schlüssel unbekannt oder Demo abgelaufen. |
| 404 | unknown_cart | Abholmarke eines Warenkorbs unbekannt. |
| 405 | method_not_allowed | Weg bekannt, Methode nicht; allowed nennt die erlaubten Methoden. |
| 409 | run_in_progress | Es ist schon ein Lauf offen, etwa beim Start einer Einrichtung; run beschreibt ihn. |
| 409 | reply_in_progress | Zu diesem Gespräch läuft über POST integration/chat schon eine Antwort. |
| 410 | cart_expired | Die Abholfrist des Warenkorbs ist abgelaufen. |
| 413 | input_too_long | Die Eingabe im Chat ist länger als erlaubt; limit nennt die Höchstlänge, length die gesendete Länge. |
| 422 | validation oder errors | Eingaben ungültig. |
| 422 | bad_credentials, invalid_token | Anmeldedaten falsch oder Bestätigungslink ungültig. |
| 422 | no_version | Der Assistent hat noch keine Fassung, mit der er antworten kann. |
| 429 | too_many_requests, quota_exhausted, too_many_attempts oder nur message | Deckel erreicht. Die Wartezeit in Sekunden steht im Kopf Retry-After; Anmeldung und Kennwortrücksetzung nennen sie stattdessen im Feld retry_in. Die Integration ergänzt scope (minute oder day), limit, retry_after, limit_per_min und wait. quota_exhausted meldet beim Chat über die Integration das erschöpfte Monatskontingent mit scope: "month", budget, used und retry_after. Siehe Grenzen. |
| 500 | message: "Serverfehler", plan_gate_misconfigured | Unerwarteter Fehler auf der Serverseite; plan_gate_misconfigured meldet eine falsch eingerichtete Paketschranke. |
| 500 | not_logged | Die Aktion ließ sich nicht protokollieren und wurde darum nicht ausgeführt. Der Körper lautet auf jedem Weg nur {"error":"not_logged"}, ohne message. Die Anwendung meldet „Nicht gespeichert: Der Eintrag ins Protokoll kam nicht zustande. Bitte versuchen Sie es erneut.“ |
| 503 | plan_limit_unmeasured | Der Stand einer Paketgrenze ließ sich nicht ermitteln; reason nennt den Grund. Die Anfrage lässt sich später wiederholen. |
Unbekannte Adressen und falsche Methode
Einen Aufruf, zu dem es keinen Weg gibt, beantwortet ein Auffangzweig mit JSON statt mit einer HTML-Fehlerseite. Er greift unter /api/ für GET, HEAD, POST, PUT, PATCH und DELETE, auch außerhalb von /api/v1/: /api/ selbst und jede erfundene Adresse antworten mit 404 und route_unknown.
Gibt es den Pfad, aber nicht für die verwendete Methode, antwortet die Schnittstelle mit 405 und method_not_allowed. Das Feld allowed listet die erlaubten Methoden alphabetisch, ohne HEAD. OPTIONS beantwortet der Auffangzweig nicht, damit Vorabfragen fremder Ursprünge bei der CORS-Schicht bleiben.
Befehl in der Schale bash
curl -s https://app.xicbot.de/api/v1/login -H 'Accept: application/json'
{"error":"method_not_allowed","allowed":["POST"]}
curl -s https://app.xicbot.de/api/v1/beispiel -H 'Accept: application/json'
{"error":"route_unknown"}HTTPS und HSTS
Die Schnittstelle arbeitet über HTTPS. Anfragen über http unter /api/ leitet der Webserver mit 301 auf die https-Adresse um, gleich mit welcher Methode. Erreicht eine unverschlüsselte Anfrage dennoch die Anwendung, leitet diese nur GET und HEAD mit 301 um und lehnt alle anderen Methoden mit 403 und https_required ab. Das Umleitungsziel baut die Anwendung aus der eigenen Adresse, nicht aus dem Host-Kopf der Anfrage.
Antworten über https tragen Strict-Transport-Security: max-age=31536000; includeSubDomains. Browser rufen die Adresse damit ein Jahr lang nur noch über https auf. preload ist bewusst nicht gesetzt.
Antwortköpfe
| Kopf | Wert | Bedeutung |
|---|---|---|
X-Konfigurationsstand | 12 Zeichen | Abdruck der wirksamen Einstellungen: die ersten 12 Stellen eines SHA-256-Hashes, kein Inhalt. Festgehalten beim Start der Anwendung, auch auf Fehlerantworten gesetzt. Ein neuer Wert zeigt, dass ein anderer Stand antwortet. |
X-Conf-Stand | Kennung | Stand der Webserver-Einstellungen für /api/. Zeigt von außen, welche Fassung dieser Einstellungen eingespielt ist. |
Strict-Transport-Security | max-age=31536000; includeSubDomains | Nur über https, siehe HTTPS. |
X-Content-Type-Options | nosniff | Browser übernehmen den angegebenen Inhaltstyp. |
X-Frame-Options | DENY | Antworten lassen sich nicht in Rahmen einbetten. |
Referrer-Policy | no-referrer | Browser senden beim Weiterklicken keine Herkunftsadresse. |
X-Robots-Tag | noindex, nofollow | Bittet Suchmaschinen, die Antworten nicht aufzunehmen. |
Retry-After | Sekunden | Bei Status 429 der Integration, des Monatskontingents und der allgemeinen Drossel. Anmeldung und Kennwortrücksetzung nennen die Wartezeit im Feld retry_in. |
Content-Type, Cache-Control, X-Accel-Buffering | text/event-stream; charset=utf-8, no-cache, no-store, no | Bei Antworten als Datenstrom, unabhängig vom Accept-Kopf der Anfrage. |
x-rows, x-masked, x-capped | Zahl, 0 oder 1 | Bei der CSV-Ausfuhr von Gesprächen: Zeilenzahl und ob Inhalte maskiert sind; x-capped nur bei der Ausfuhr eines einzelnen Gesprächs und zeigt, ob gekürzt wurde. Siehe Gespräche und Verwaltung. |
x-sections, x-failed, x-unexported, x-truncated | Zahl | Bei der Datenausfuhr des Kontos: Zahl der Abschnitte, der gescheiterten Abschnitte, der nicht abgedeckten Tabellen und der gekürzten Tabellen. Siehe Konto. |
CORS
CORS-Köpfe setzt die Schnittstelle nur auf der öffentlichen Strecke /api/v1/public/*, etwa für Statusseite, Änderungsprotokoll und Widget-Zweig, und nur für die zugelassenen Ursprünge aus der Tabelle. Die Integration und die Wege mit Anmeldung setzen keine CORS-Köpfe. Rufen Sie die Integration darum von Ihrem Server auf, nicht aus Javascript im Browser.
Eine eigene Regel gilt für GET cart/pickup/{token}. Der Weg ist für den Abruf von Server zu Server gedacht. Im Browser darf nur der Ursprung der hinterlegten Übergabeadresse die Antwort lesen. Die Antworten tragen Cache-Control: no-store und Vary: Origin.
| Einstellung | Wert |
|---|---|
| Pfade | api/v1/public/* |
| Ursprünge | null für das Widget, das in einem abgeschotteten iframe ohne allow-same-origin läuft und Origin: null sendet; die eigenen Ursprünge von Anwendung und Widget; weitere einzeln freigegebene Ursprünge mit Schema. Einträge mit * werden verworfen. |
| Methoden | GET, POST, DELETE, OPTIONS |
| Anfrageköpfe | Content-Type, Accept |
| Für Skripte lesbare Köpfe | Retry-After |
| Gültigkeit der Vorabfrage | 600 Sekunden (max_age) |
| Zugangsdaten | nicht unterstützt (supports_credentials: false) |
Da nur Content-Type und Accept zugelassen sind, lässt eine Vorabfrage aus einem fremden Ursprung weder X-Api-Key noch Authorization zu. Die Wege für das Chatfenster beschreibt Widget-Wege, die übrigen öffentlichen Wege Öffentliche Wege.
Seitenweise Abfrage
Listen liefert die Schnittstelle seitenweise über den Abfrageparameter page, beginnend bei 1. Seitengröße, Spannen und Rückgabefelder unterscheiden sich je Weg. Wo ein Weg eine Spanne prüft, ergeben Werte außerhalb davon 422; die Integration wertet Werte unter 1 als 1.
| Weg | page | per_page | Felder der Antwort |
|---|---|---|---|
GET integration/conversations, integration/leads, integration/appointments | ab 1; kleinere Werte gelten als 1 | fest 50 | Liste und page |
GET conversations | 1 bis 10000 | 1 bis 200, Vorgabe 50 | conversations, total, page, per_page |
GET catalog | ab 1 | 1 bis 200, Vorgabe 50 | products, total, page, per_page; total zählt alle Produkte, auch wenn search gesetzt ist |
GET records/{type} | ab 1 | 1 bis 200, Vorgabe 50 | entries, total, page, per_page; total berücksichtigt den Filter status |
GET activity | 1 bis 1000 | fest 25 | entries, actions, total, page, pages; actions nennt die vorkommenden Aktionen für den Filter |
Wiederholte Anfragen
Doppelungen verhindert die Schnittstelle über Kennungen im Körper oder über den Zustand des Datensatzes, nicht über einen eigenen Kopf. Ob sich eine Anfrage nach einem Abbruch schadlos wiederholen lässt, hängt vom Weg ab:
| Weg | Verhalten bei Wiederholung |
|---|---|
POST integration/leads mit external_id | Die Kennung darf bis 100 Zeichen lang sein. Gibt es zu ihr schon eine Anfrage, antwortet der Weg mit 200, dem bestehenden Eintrag und duplicate_prevented: true; eine neue Anfrage ergibt 201 und duplicate_prevented: false. |
POST integration/leads ohne external_id | Jeder Aufruf legt eine neue Anfrage an. |
POST catalog/import | Gleicht über external_id ab. Ein zweiter Lauf derselben Datei erzeugt keine Dubletten. Bis 500 Produkte je Aufruf, Antwort mit new, changed und total. Siehe Katalog und Shop. |
Vorschlag bestätigen, ablehnen oder melden (…/tool/{call}/confirm, …/reject, …/report) | Ein schon entschiedener Vorschlag wird nicht erneut ausgeführt; die Antwort trägt duplicate: true. Ein zweiter Bericht zu einem ausgeführten Vorschlag im Widget meldet ebenfalls duplicate: true. |
DELETE keys/{id} | Ein zweites Zurückziehen ändert nichts; withdrawn behält den Zeitpunkt des ersten. |
POST public/demo | 200 für eine bestehende Demo, 201 für eine neue. |
POST integration/knowledge/sources | Jeder Aufruf legt eine neue Quelle an. |
POST integration/chat | Ohne conversation_id beginnt jeder Aufruf ein neues Gespräch. Mit conversation_id setzen Sie ein Gespräch fort, das derselbe Assistent über die Integration begonnen hat; andere Kennungen ergeben 404. Läuft zu dem Gespräch noch eine Antwort, ergibt ein weiterer Aufruf 409 und reply_in_progress. Nach 180 Sekunden gilt ein laufender Lauf als abgebrochen, und das Gespräch ist wieder frei. |
Häufige Fragen
Wie erkenne ich, ob ein Fehler an meiner Anfrage liegt?
Ein Status von 400 bis 499 betrifft die Anfrage: das Kennzeichen steht in error, Feldfehler unter errors oder fields. Ab 500 liegt der Fehler auf der Serverseite; bei einem unerwarteten Fehler lautet die Meldung dann nur „Serverfehler“. Eine Antwort 503 mit plan_limit_unmeasured lässt sich später wiederholen.
Kann ich die Integration direkt aus dem Browser aufrufen?
Nein. Die Integration setzt keine CORS-Köpfe, und im Browser läge der Schlüssel offen. Rufen Sie /api/v1/integration/… von Ihrem Server auf. Für das Chatfenster gibt es den Widget-Zweig unter /api/v1/public/widget/{key}/.
Was passiert mit einer Anfrage über http?
Der Webserver leitet sie mit 301 auf https um. Erreicht sie die Anwendung unverschlüsselt, lehnt diese alles außer GET und HEAD mit 403 und https_required ab. Ihr Inhalt war in beiden Fällen schon unverschlüsselt unterwegs. Tragen Sie die Basisadresse mit https:// ein und ziehen Sie einen so verschickten Schlüssel zurück.
Warum antwortet ein Weg mit 405 statt mit 404?
Den Pfad gibt es, aber nicht für die verwendete Methode. Das Feld allowed nennt die erlaubten Methoden, bei /api/v1/login etwa ["POST"]. Ein 404 mit route_unknown bedeutet dagegen, dass es den Pfad nicht gibt.
Wie vermeide ich doppelte Anfragen, wenn ich einen Aufruf wiederhole?
Geben Sie bei POST /api/v1/integration/leads eine stabile external_id mit. Eine Wiederholung ergibt dann 200 mit dem bestehenden Eintrag und duplicate_prevented: true statt einer zweiten Anfrage.
Selbst fragen, Assistent dieser Website
Automatischer Assistent