Zum Hauptinhalt springen

Server-to-Server-Einbettung

Standardmäßig spricht das Widget die AI-Hub-API direkt aus dem Browser an und authentifiziert sich dabei mit einem öffentlichen API-Schlüssel. Für viele Anwendungsfälle reicht das aus.

In manchen Szenarien soll die Chat-Komponente aber in eine eigene Applikation eingebettet werden, in der

  • ein persistenter, personalisierter Chat-Verlauf pro angemeldetem Benutzer geführt wird und
  • die Benutzeridentität serverseitig aus der eigenen Anwendung stammt und nicht manipulierbar sein darf.

Persistenter Verlauf pro Benutzer erfordert einen geheimen API-Schlüssel — und ein geheimer Schlüssel darf niemals im Browser sichtbar sein. Die API setzt das durch: Wird der Verlauf eines Benutzers gelesen oder gesammelt gelöscht, antwortet sie mit 403, wenn der Schlüssel öffentlich ist. Einzelne Konversationen lassen sich weiterhin mit jedem Schlüssel lesen und löschen.

Die Lösung: Das Widget schickt seine Requests nicht mehr direkt an den AI Hub, sondern an ein eigenes Backend. Dieses ergänzt den geheimen Schlüssel und die geprüfte Benutzer-ID und leitet den Request dann an den AI Hub weiter (ein solcher Vermittler wird auch Proxy genannt). Der geheime Schlüssel bleibt so ausschließlich auf dem eigenen Server.

Damit das Widget statt des AI Hubs Ihr Backend anspricht, lässt sich mit dem Attribut api-url der API-Endpunkt des Widgets überschreiben.

info

Die überschreibbare API-URL ist ausschließlich für die Einbettung in externe Applikationen gedacht.

Ablauf​

Browser (<ai-hub-chat api-url="…">)
│ Request an Ihr Backend (ohne Schlüssel)
▼
Ihr eigenes Backend
│ fügt geheimen Schlüssel + geprüfte Benutzer-ID hinzu
▼
AI Hub API

Schritt 1: Geheimen Schlüssel erstellen​

Im Bereich API Keys einen API-Schlüssel vom Typ Widget erstellen und Geheim wählen. Der Schlüssel muss sicher im eigenen Backend aufbewahrt werden — er wird nur einmalig angezeigt und darf nicht im Frontend landen.

Schritt 2: Weiterleitung im eigenen Backend einrichten​

Das eigene Backend stellt einen Endpunkt (z. B. https://ihre-app.example.com/ai-proxy) bereit, der die Requests des Widgets entgegennimmt und weiterleitet. Für jeden weitergeleiteten Request muss das Backend:

  1. Den Benutzer in der eigenen Anwendung authentifizieren.
  2. Den Header X-Api-Key mit dem geheimen Schlüssel setzen.
  3. Die userId durch die tatsächliche, geprüfte Benutzer-ID ersetzen (im Request-Body bzw. als Query-Parameter). Die vom Widget übergebene user-id gilt nur als Hinweis und darf nicht ungeprüft übernommen werden.
  4. Den Request an die AI Hub API weiterleiten.

Dabei muss keine feste Liste von Endpunkten gepflegt werden: Das Backend leitet jeden eingehenden Request generisch weiter — mit Methode, Query-Parametern und Body unverändert. Es stellt lediglich den Pfad-Präfix wieder her, den das Widget weglässt:

Request an api-url beginnt mit …Weiterleiten an
/chat<AI_HUB_API>/api/v2<pfad>
/file-uploads/upload<AI_HUB_API>/api/v2<pfad>
/speech<AI_HUB_API>/api/v2<pfad>
/file-uploads<AI_HUB_API>/api<pfad>

Die Zeilen von oben nach unten prüfen und die erste passende verwenden: /file-uploads/upload ist der Datei-Upload auf v2, alle übrigen /file-uploads-Pfade sind Datei-Downloads und liegen ohne Versions-Präfix direkt unter /api. Bis auf die Datei-Downloads liegt die gesamte öffentliche API auf v2.

:::info Die Sammellöschung setzt einen geheimen Schlüssel voraus

Das Leeren des gesamten Verlaufs (/chat/conversation/bulk) funktioniert nur in dieser Einbettung. Bei einem öffentlichen Schlüssel im Seitenquelltext ist die userId ungeprüft — die API antwortet dort mit 403. Einzelne Konversationen lassen sich in jeder Einbettung löschen.

:::

Eine Konversation bleibt an den API-Schlüssel gebunden, mit dem sie begonnen wurde: Wird sie mit einem anderen Schlüssel fortgesetzt, antwortet die API mit 401. Beim Wechsel eines Schlüssels beginnen laufende Konversationen daher neu. Eine gelöschte Konversation lässt sich nicht weiterschreiben — eine Nachricht an ihre sessionId beantwortet die API mit 404.

Damit sind automatisch alle Endpunkte abgedeckt, die das Widget nutzt. Welche Chat-, Verlaufs-, Feedback- und Datei-Endpunkte das im Einzelnen sind und welche Parameter sie erwarten, ist in der Swagger/OpenAPI-Collection dokumentiert — das Backend muss diese Requests nur unverändert durchreichen.

warnung

Auch Bild- und Datei-Downloads laufen über das eigene Backend. Es muss diese GET-Requests ebenfalls weiterleiten, sonst werden hochgeladene Dateien und Bilder im Chat nicht angezeigt.

Umstellung eines bestehenden Proxys​

Wer bereits einen Proxy betreibt, ändert nur die Weiterleitung, nicht die Requests:

  • Aus der Zeile für /chat wird api/v2 statt api/v1.
  • Die Zeile für /custom-file-uploads wird durch /file-uploads/upload auf api/v2 ersetzt und muss vor der Zeile für /file-uploads geprüft werden — sonst landet der Upload bei den Datei-Downloads. Beide Änderungen sind nötig, sobald das Widget aktualisiert wird.

Pfade, Methoden, Query-Parameter und Bodies bleiben unverändert — mit zwei Ausnahmen auf den beiden Endpunkten, die sich zwischen den Versionen absichtlich unterscheiden:

  • GET /chat/history kennt auf v2 keinen Parameter versionId mehr. Zurückgegeben werden alle Konversationen, die dieser Schlüssel für den Benutzer angelegt hat, auch die von zwischenzeitlich gelöschten Agent-Versionen.
  • DELETE /chat/conversation/bulk erwartet auf v2 nur noch die userId und löscht damit denselben Verlauf, den die Liste zeigt.

Ein Proxy, der Requests generisch durchreicht, ist von beidem nicht betroffen — die Parameter kommen vom Widget.

v1 bleibt bis auf Weiteres funktionsfähig und ist in der Swagger-Collection als veraltet markiert. Ein Enddatum ist nicht gesetzt: selbst gehostete Widget-Bundles laufen mit einer gepinnten Version weiter gegen v1.

Schritt 3: Widget einbetten​

Das Widget mit api-url (statt api-key) einbetten und die Benutzer-ID über user-id mitgeben:

<ai-hub-chat
language="de"
height="690"
width="570"
integration-location="#IHR_STANDORT"
api-url="https://ihre-app.example.com/ai-proxy"
user-id="[BENUTZER_ID]"
widget-id="[WIDGET_ID]"
/>
<script src="[SCRIPT_URL]" type="module" defer></script>

Da kein Schlüssel im Browser liegt, wird api-key weggelassen — die Authentifizierung übernimmt vollständig das eigene Backend.

Mit einem geheimen Schlüssel lädt das Widget kein reCAPTCHA. Die Content Security Policy der eigenen Applikation muss die Domains von Google reCAPTCHA daher nicht freigeben.

Attribute​

AttributErforderlichBeschreibung
api-urlJaBasis-URL des eigenen Backend-Endpunkts. Ist sie gesetzt, sendet das Widget keinen api-key und ruft alle Endpunkte relativ zu dieser URL auf. Erlaubt sind absolute URLs (https://…) und Same-Origin-Pfade (/ai-proxy).
user-idNeinKennung des angemeldeten Benutzers als Hinweis. Die verbindliche, geprüfte userId setzt das Backend.
widget-idJaDie ID des Widgets.

Die übrigen Attribute (language, height, width, integration-location) verhalten sich wie bei der normalen Widget-Einbettung.