AACSearch
API-Referenz

Embed-Session

POST /api/v1/embed/session — tauscht einen API-Schlüssel serverseitig gegen ein kurzlebiges, reines Such-Session-Token, das sicher auf einer Seite stehen darf. Dazu die browserseitigen /embed/*-Endpunkte, die es akzeptieren.

POST /api/v1/embed/session
Authorization: Bearer aac_live_…

Ein aac_live_…-Schlüssel darf niemals in einen Browser gelangen. Dieser Endpunkt existiert genau dafür: Er tauscht den Schlüssel gegen ein Embed-Session-Token, beschränkt auf einen Index, eine Aktion (search:read) und eine Laufzeit. Das Token kommt auf die Seite (data-aac-token); der Schlüssel bleibt auf Ihrem Server.

Ein GET /embed/bootstrap und eine ?key=-Variante gibt es nicht. Ein Schlüssel in einer Query-Zeichenfolge, einem data--Attribut oder im HTML der Seite ist genau das Leck, das dieses Design beseitigt: Der Endpunkt liest den Schlüssel nur aus dem Authorization-Header und antwortet sonst mit 401 UNAUTHORIZED.

Rufen Sie ihn aus Ihrem eigenen Backend auf — Route-Handler, SSR-Durchlauf oder Build-Schritt — und reichen Sie das resultierende token an die Seite weiter.

Session ausstellen

curl -sS -X POST "$AAC_API/embed/session" \
  -H "Authorization: Bearer $AAC_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "index": "documentation", "expires_in": 900 }'
Body-FeldTypStandardBedeutung
indexstring ≤ 64Index des Schlüssels bzw. ältester Index des MandantenIndex-Slug, auf den die Session beschränkt wird. Ein an einen Index gebundener Schlüssel kann keine Session für einen anderen ausstellen
expires_inGanzzahl, Sekunden900 (15 Minuten)Gewünschte Laufzeit, begrenzt auf 60–3600

Der Body ist optional. Ein nicht numerisches expires_in oder ein zu langer index ergibt 422 VALIDATION_ERROR.

{
	"ok": true,
	"token": "aac_sess_…",
	"token_type": "embed_session",
	"scope": ["search:read"],
	"index": { "slug": "documentation", "name": "Documentation" },
	"expires_at": "2026-10-23T11:15:02.000Z",
	"expires_in": 900,
	"settings": {
		"placeholder": "Dokumentation durchsuchen…",
		"perPage": 8,
		"queryBy": "title,content",
		"facets": ["category"],
		"showStats": true,
		"showRecent": true,
		"showVoice": false,
		"showImage": false,
		"showRelated": false,
		"accent": "#2563eb",
		"dark": false,
		"sortOptions": [
			{ "label": "Relevanz", "value": "default" },
			{ "label": "Neueste zuerst", "value": "created_at:desc" }
		]
	},
	"ui": { "name": "AACSearch UI", "version": "1.0.0" },
	"request_id": "req_4a6c8e0b2d4f6a8c0e2b4d6f"
}

Was die Antwort garantiert:

  • Das Token ist nur zum Suchen. Es trägt search:read und sonst nichts, kann also weder schreiben noch löschen noch reindexieren. Wird die Seite kompromittiert, erbeutet man ein Credential, das von selbst abläuft und nur liest, was die Seite ohnehin anzeigt.
  • Das Token ist an einen Index und einen Mandanten gebunden. Der Mandantenfilter wird bei jeder Anfrage serverseitig angewendet; der Browser sieht weder einen Infrastrukturschlüssel noch Host oder Collection-Namen.
  • Es läuft ab. Standard 900 Sekunden, höchstens 3600. Für langlebige Seiten rechtzeitig ein neues ausstellen; ein abgelaufenes Token ergibt 401 EMBED_SESSION_EXPIRED.
  • Es wird nicht gecacht. Antworten tragen cache-control: no-store; jede Ausstellung landet im Audit-Log (embed.session.issue).
  • Einstellungen sind live. settings stammt aus SearchIndex.settings.embed; eine Änderung im Panel „Erscheinungsbild“ der Konsole ist beim nächsten Seitenaufruf sichtbar — ohne Redeploy.

Origin-Allowlist

Hat der Schlüssel allowedOrigins, ergibt ein Browser-Aufruf von einem anderen Origin 403 ORIGIN_NOT_ALLOWED und erhält keine CORS-Header. Eine leere Liste bedeutet „jeder Origin“. Da der Session-Endpunkt aus Ihrem Backend aufgerufen werden soll, trägt ein Server-zu-Server-Aufruf keinen Origin-Header und wird nicht geprüft.

Einstellungen

SchlüsselTypStandardWirkung
placeholderstringSearch the docs…Platzhalter des Eingabefelds
perPagenumber8Treffer pro Seite
queryBystringtitle,contentquery_by jeder Suche
facetsstring[][]Facettenfelder als Checkbox-Listen (die Konsole erlaubt höchstens 6)
showStatsbooleantrueZeile mit der Trefferzahl
showRecentbooleantrueChips mit letzten Anfragen, lokal pro Index gespeichert
showVoicebooleanfalseSpracheingabe des Browsers über InstantSearch voiceSearch
showImagebooleanfalseTrefferbild anzeigen, wenn das Dokument eines hat
showRelatedbooleanfalse„Für Sie“-Leiste unter den Ergebnissen (Empfehlungen müssen am Index aktiviert sein)
accentstring#2563ebAkzentfarbe für Buttons, Fokusring und Links
darkbooleanfalseDunkle Palette
sortOptionsarrayRelevanz + created_at:descSortier-Dropdown; der erste Eintrag muss default nutzen

Fehler

{
	"error": {
		"code": "UNAUTHORIZED",
		"message": "Send the API key as an Authorization header; embed sessions cannot be minted from a query parameter",
		"request_id": "req_7b9d1f3a5c7e9b1d3f5a7c9e"
	}
}
StatusCodeWann
401UNAUTHORIZEDSchlüssel fehlt, ist fehlerhaft, unbekannt oder widerrufen; Schlüssel als Query-Parameter gesendet
403ORIGIN_NOT_ALLOWEDBrowser-Origin außerhalb der allowedOrigins des Schlüssels
404INDEX_NOT_FOUNDFür den Schlüssel ist kein Index verfügbar, oder index nennt einen Index, den der Schlüssel nicht nutzen kann
422VALIDATION_ERRORUngültiger Body
429RATE_LIMITEDAdressbezogenes Limit auf /embed/* (anonymer Embed-Traffic hat ein kleineres Budget)

Endpunkte, die das Token akzeptieren

Hält die Seite ein Token, spricht das Widget nur noch mit diesen Endpunkten. Alle authentifizieren sich mit dem Token — im JSON-Body (token) oder, wo angegeben, als Authorization: Bearer aac_sess_… — nie mit einem API-Schlüssel. Jeder beantwortet außerdem einen CORS-Preflight (OPTIONS) mit 204.

EndpunktZweck
POST /api/v1/embed/configEinstellungen zu einem bereits ausgestellten Token: { "token": "…" } liefert index, scope, expires_at und settings
POST /api/v1/embed/searchSuch-Proxy. Body { token, index, client_id?, personalize?, searches: [...] } mit bis zu 5 Suchen; das Token geht auch als Bearer-Header. page ≤ 20, per_page wird auf 50 gekappt
POST /api/v1/embed/eventsVerhaltensereignisse: type ist view, click, conversion, add_to_cart oder impression (das Widget selbst sendet view, click und conversion), mit document_id, position, query, query_id, session_id, value_cents, items
POST /api/v1/embed/recommendationsVerwandte und personalisierte Einträge für einen Besucher: client_id, seed_document_id, seed_query, limit (≤ 40)
POST /api/v1/embed/widget-sessionFür gespeicherte Widgets der Konsole: eine öffentliche Widget-ID (wgt_…) plus erlaubter Origin liefert eine Session — ganz ohne Schlüssel auf der Seite

Die Suche über den Proxy durchläuft dieselbe Pipeline wie die öffentliche API (Query-Log, Regeln, Defaults, Relaxation, Did-you-mean); die Analytics sehen also den Widget-Traffic. Jede Embed-Suche zählt gegen das searches-Kontingent des Mandanten.

Token-Fehler an diesen Endpunkten:

StatusCodeBedeutung
401EMBED_SESSION_REQUIREDEs wurde kein Token gesendet
401EMBED_SESSION_EXPIREDDie Laufzeit des Tokens ist abgelaufen — neues ausstellen
401EMBED_SESSION_INVALIDFehlerhaftes oder manipuliertes Token
403FORBIDDENDem Token fehlt der Scope search:read
403INDEX_MISMATCHDie Anfrage nennt einen anderen Index als das Token

Browserzugriff

Verwenden Sie POST /embed/session und /embed/search für das Widget oder eine eigene Browseroberfläche. Ihr Server tauscht den API-Schlüssel gegen ein kurzlebiges Token; der Browser erhält keine Infrastruktur-Zugangsdaten oder Speichernamen. Der erweiterte Endpunkt /scoped-key wird vom Widget nicht verwendet und ersetzt die Such-API der Plattform nicht.

On this page