Dokumente
Ingest, Update, Löschen und Export von Dokumenten — POST /documents, Massen-Update, TTL, idempotente Wiederholungen und NDJSON-Export.
POST /api/v1/indexes/{slug}/documents
POST /api/v1/indexes/{slug}/documents/bulk
GET /api/v1/indexes/{slug}/documents/{externalId}
DELETE /api/v1/indexes/{slug}/documents/{externalId}
DELETE /api/v1/indexes/{slug}/documents?filter_by=…
GET /api/v1/indexes/{slug}/documents/exportSchreiben erfordert documents:write, das Lesen eines einzelnen Dokuments search:read, der Export documents:read.
Aufbau eines Dokuments
| Feld | Pflicht | Hinweis |
|---|---|---|
external_id | ja | 1–256 Zeichen; Ihr Primärschlüssel im Index |
content | ja | Indizierter Text; bis SEARCH_MAX_CONTENT_LENGTH (Standard 200.000 Zeichen) |
title | nein | ≤ 1000 Zeichen; Teil des Standard-query_by |
url | nein | ≤ 2048 Zeichen, gespeichert, nicht indiziert |
source_type | nein | ≤ 64 Zeichen; facettierbar, trennt api, webhook, connector |
tags | nein | Bis 50 Strings mit je ≤ 64 Zeichen |
metadata | nein | Beliebiges JSON, als String gespeichert, nicht durchsuchbar |
expires_at | nein | ISO-8601-Datum; danach wird das Dokument aus dem Index entfernt |
| eigene Felder | nein | Jedes im Indexschema deklarierte Feld wird durchgereicht |
Batch-Upsert
curl -sS -X POST "$AAC_API/indexes/documentation/documents" \
-H "Authorization: Bearer $AAC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: import-2026-10-23-01" \
-d '{
"documents": [
{ "external_id": "pricing", "title": "Preise", "content": "Pro kostet 29 USD im Monat.", "url": "https://example.com/pricing", "tags": ["billing"] },
{ "external_id": "limits", "title": "Limits", "content": "600 Requests pro Minute und Schlüssel.", "tags": ["api"], "expires_at": "2026-12-31T23:59:59Z" }
],
"action": "upsert"
}'{
"index": "documentation",
"indexed": 2,
"failed": [],
"usage": {
"plan": "pro",
"period": "2026-10",
"resetsAt": "2026-11-01T00:00:00.000Z",
"searches": { "used": 4120, "limit": 500000 },
"documents": { "used": 139, "limit": 50000 }
},
"request_id": "req_2a6c8e0b4d1f3a5c7e9b1d3f"
}action bestimmt den Umgang mit vorhandenen Dokumenten:
| Aktion | Verhalten |
|---|---|
upsert (Standard) | Vorhandenes Dokument ersetzen, neues einfügen |
create | Nur einfügen; eine vorhandene external_id scheitert für dieses Dokument |
update | Teil-Update — nur gesendete Felder ändern sich |
emplace | Einfügen oder zusammenführen, ohne ausgelassene Felder zu leeren |
Ein Batch ist nicht atomar. Abgelehnte Dokumente kommen in failed zurück, der Rest wird indiziert:
{
"index": "documentation",
"indexed": 1,
"failed": [{ "external_id": "draft-1", "error": "Document content is required" }],
"usage": { "documents": { "used": 140, "limit": 50000 } },
"request_id": "req_7d1e3b5a9c0f2a4d6b8e0c2a"
}Limits: maximal 500 Dokumente pro Request und 200.000 Zeichen pro content. Wird eines überschritten, folgt 422 INVALID_DOCUMENT mit Details:
{
"error": {
"code": "INVALID_DOCUMENT",
"message": "Too many documents in a single request",
"request_id": "req_4c8a0e2b6d1f3a5c7b9d1e3f",
"details": { "max": 500, "received": 812 }
}
}Idempotente Wiederholungen
Mit Idempotency-Key auf POST /documents liefert eine Wiederholung desselben Schreibvorgangs die ursprüngliche Antwort, statt Dokumente doppelt zu zählen:
curl -sS -i -X POST "$AAC_API/indexes/documentation/documents" \
-H "Authorization: Bearer $AAC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: import-2026-10-23-01" \
-d '{"documents":[{"external_id":"pricing","content":"Pro kostet 29 USD im Monat."}]}'HTTP/1.1 200 OK
idempotent-replayed: trueReplay-Einträge leben 10 Minuten: in Redis (instanzübergreifend) oder im Prozessspeicher, wenn Redis nicht konfiguriert ist.
So wird ein Schlüssel zugeordnet:
- Schlüssel gelten pro Index: derselbe Schlüssel auf zwei Indizes sind zwei getrennte Schreibvorgänge.
- Der Eintrag speichert einen Fingerabdruck aus Methode, Pfad und JSON-Body. Wird ein Schlüssel für einen anderen Body wiederverwendet, antwortet die API mit
422 IDEMPOTENCY_KEY_REUSED, statt die alte Antwort zu wiederholen und den neuen Schreibvorgang still zu verwerfen. - Solange der erste Request noch läuft, erhält ein paralleles Duplikat
409 IDEMPOTENCY_IN_FLIGHT; kurz warten und erneut senden. Die In-Flight-Markierung läuft nach 120 Sekunden ab. - Ein fehlgeschlagener Schreibvorgang wird nicht gespeichert; derselbe Schlüssel kann sofort erneut verwendet werden.
- Nur eine erfolgreiche Antwort (
200) wird wiederholt, byte-genau einschließlich der ursprünglichenrequest_id.
Lesen, Ändern, Löschen
curl -sS "$AAC_API/indexes/documentation/documents/pricing" \
-H "Authorization: Bearer $AAC_KEY"{
"document": {
"id": "pricing",
"external_id": "pricing",
"title": "Preise",
"content": "Pro kostet 29 USD im Monat.",
"url": "https://example.com/pricing",
"source_type": "api",
"organization_id": "org_01h9",
"tags": ["billing"],
"indexed_at": 1761214364
},
"request_id": "req_9e2b4d6a8c0f1e3b5d7a9c1e"
}curl -sS -X DELETE "$AAC_API/indexes/documentation/documents/pricing" \
-H "Authorization: Bearer $AAC_KEY"{
"deleted": true,
"external_id": "pricing",
"request_id": "req_1a3c5e7b9d0f2a4c6e8b0d1f"
}Ein fehlendes Dokument ist 404 DOCUMENT_NOT_FOUND:
{
"error": {
"code": "DOCUMENT_NOT_FOUND",
"message": "Document \"pricing\" was not found",
"request_id": "req_6b0d2f4a8c1e3b5d7f9a1c3e"
}
}Massen-Update und Löschen per Filter
curl -sS -X POST "$AAC_API/indexes/documentation/documents/bulk" \
-H "Authorization: Bearer $AAC_KEY" \
-H "Content-Type: application/json" \
-d '{ "filter_by": "tags:=[billing]", "document": { "category": "pricing" } }'{
"index": "documentation",
"updated": 12,
"filter_by": "tags:=[billing]",
"request_id": "req_3d5f7b9a1c2e4a6b8d0f2a4c"
}curl -sS -X DELETE "$AAC_API/indexes/documentation/documents" \
-H "Authorization: Bearer $AAC_KEY" \
-G --data-urlencode "filter_by=source_type:=connector && indexed_at:<1761214364"{
"index": "documentation",
"deleted": 348,
"filter_by": "source_type:=connector && indexed_at:<1761214364",
"request_id": "req_8f0b2d4a6c8e1b3d5f7a9c1e"
}Für das filterbasierte Löschen ist filter_by Pflicht; ohne den Parameter kommt 400 INVALID_QUERY mit der Meldung filter_by query parameter is required. Der Mandantenfilter wird wie bei der Suche injiziert.
Export
curl -sS "$AAC_API/indexes/documentation/documents/export" \
-H "Authorization: Bearer $AAC_KEY" \
-o documentation.ndjsonDie Antwort ist application/x-ndjson mit content-disposition: attachment; filename="documentation-export.ndjson", ein JSON-Dokument pro Zeile — genau das Format, das der Import akzeptiert, ein Export lässt sich also in einen anderen Index zurückspielen.
Ablaufende Dokumente
expires_at wird mit dem Dokument gespeichert und vom Retention-Job durchgesetzt, der abgelaufene Dokumente aus der Collection entfernt. Das ist der günstigste Weg, zeitlich begrenzte Inhalte (Events, Releases, Aktionen) aus den Ergebnissen zu halten, ohne einen Delete-Aufruf. Der Lauf gehört zum Scheduler; mit POST /admin/jobs/run?job=retention stoßen Sie ihn selbst an.
Schreiben per Webhook
Kommen Dokumente aus einem anderen System, nimmt POST /indexes/{slug}/webhook dasselbe Dokument-Array mit HMAC-Signatur entgegen und erlaubt bis zu 1000 Dokumente pro Aufruf. Siehe Webhooks.
Feed vor dem Import prüfen
POST /indexes/{indexSlug}/feed-preview (Scope documents:write) liest einen XML-, YAML-, CSV- oder JSON-Feed von einer öffentlichen URL und liefert erkannte Felder, ein vorgeschlagenes Mapping, ein gemapptes Beispiel und einen Schema-Vorschlag. Es wird nichts in den Index geschrieben. Mit mapping ({ "rules": [{ "source", "target", "transforms" }] }) lassen sich eigene Regeln testen. Transformationen: strip_html, to_number, to_bool, split, join, default, lowercase, date_to_unix, first_non_empty. Ein nicht lesbarer Feed ergibt 422 FEED_UNREADABLE.
Suggest
GET /api/v1/indexes/{slug}/suggest und POST /api/v1/indexes/suggest/multi — Präfix-Autocomplete mit populären Suchanfragen, ETag-validiert und nie abgerechnet.
Analytics
Übersicht, CSV-Export, langsame Abfragen, Trends, Null-Ergebnis-Alerts, verwandte Anfragen, Experimente und letzte Suchen — alles aus dem Query-Log.