AACSearch
Справочник API

Аутентификация

Bearer-ключи с префиксом aac_live_, модель прав, привязка к индексу, CORS и заголовки, которые возвращает каждый ответ.

Все эндпоинты под /api/v1/indexes/*, /api/v1/analytics/*, /api/v1/billing/*, /api/v1/organization/*, /api/v1/admin/*, /api/v1/jobs/*, /api/v1/api-keys/* и /api/v1/recent требуют API-ключ. Публичны /health, /status, /capabilities, /openapi.json, /embed/* (по токену сессии) и /widget.js.

Как передать ключ

curl -sS "$AAC_API/indexes/documentation/search?q=тарифы" \
  -H "Authorization: Bearer aac_live_9f3c2a1bD4eF6gH8iJ0kL2mN4oP6qR8s"

Заголовок должен начинаться с Bearer , а ключ — соответствовать шаблону ^aac_(live|test)_[A-Za-z0-9_-]{20,}$. Всё остальное отклоняется до обращения к базе:

{
	"error": {
		"code": "UNAUTHORIZED",
		"message": "Missing or invalid API key",
		"request_id": "req_2f8a1c4e6b9d0e3f5a7c8b1d"
	}
}

Тот же 401 возвращается для корректного по форме, но неизвестного или отозванного ключа (у него заполнено revokedAt). Ключи хранятся как SHA-256-хеши, открытое значение существует только в ответе на создание.

Права (scopes)

Ключ несёт список прав. * даёт все. Консоль предлагает следующие:

ПравоЧто открывает
search:read/search, /suggest, /stats, GET /documents/{id}, диалоги, ассистент, answer, voice, image, ограниченные ключи на чтение
documents:readGET /documents/export, GET /snapshots, GET /snapshots/{id}
documents:read_privateПриватные поля в хитах, документах и экспорте (см. Приватные поля)
documents:writePOST /documents, /documents/bulk, DELETE /documents…, /webhook, /docsearch/preview; вместе с settings:write — создание, удаление и восстановление снимков
settings:writePOST /reindex, /scoped-key, GET /conversation-models, POST /api-keys/{keyId}/rotate, чтение и отмена задач reindex, file_import, snapshot, restore
analytics:readЧтение аналитики (обзор также принимает search:read)
analytics:writePOST /events — клики и конверсии
billing:read/billing/usage, /billing/wallet, /billing/invoices, /billing/invoices/{id}[.pdf]

Недостающее право — это 403, а не 404: эндпоинт существует, ключу просто нельзя им пользоваться.

curl -sS -X POST "$AAC_API/indexes/documentation/documents" \
  -H "Authorization: Bearer aac_live_…read_only_key…" \
  -H "Content-Type: application/json" \
  -d '{"documents":[{"external_id":"x","content":"y"}]}'
{
	"error": {
		"code": "FORBIDDEN",
		"message": "Missing scope: documents:write",
		"request_id": "req_7b3e9d2a5c8f1a4b6d0e3c7a"
	}
}

Привязка к индексу

Ключ, созданный для одного индекса (indexId заполнен), может работать только с ним. Обращение к соседнему индексу той же организации возвращает:

{
	"error": {
		"code": "FORBIDDEN",
		"message": "API key is scoped to a different index",
		"request_id": "req_4d8c2a6f0b1e3d5c7a9f2b4e"
	}
}

Слаг, которого нет в организации ключа, даёт 404 INDEX_NOT_FOUND — включая слаги, существующие у другого тенанта. Тенант определяется по ключу, а не по пути или телу запроса.

CORS

API аутентифицируется ключом и не использует cookie, поэтому возвращает полученный Origin и разрешает GET, POST, PUT, DELETE, OPTIONS. Preflight обрабатывается до аутентификации и возвращает 204. Открытые заголовки: x-request-id, x-aac-quota-remaining, x-aac-quota-limit.

Для браузерных ключей ограничивайте список разрешённых origin в консоли, а не полагайтесь только на CORS.

Заголовки ответа

ЗаголовокЗначение
x-request-idИдентификатор запроса; дублируется в теле как request_id
x-ratelimit-limitСколько запросов разрешено ключу в окне (по умолчанию 600)
x-ratelimit-remainingСколько осталось в текущем окне
x-ratelimit-resetМомент сброса окна, Unix-время в секундах
x-aac-quota-limitСколько единиц метрики включено в тариф
x-aac-quota-remainingСколько единиц осталось в периоде
x-aac-indexИндекс, к которому разрешился запрос
x-aac-profileИспользованный профиль поиска или default
x-aac-charged-centsСколько списано с кошелька за превышение

Жизненный цикл ключа

  • Создание — в консоли: имя, права, при необходимости привязка к индексу. Лимит зависит от тарифа: 3 ключа на Free, 10 на Pro, 100 на Enterprise.
  • Ротация — POST /api-keys/{keyId}/rotate (scope settings:write, тело { "grace_days": 7 }) или диалог в консоли. Преемник получает те же права, origins и привязку к индексу; его открытый текст возвращается один раз (201). Старый ключ работает grace_days дней (по умолчанию 7, от 0 до 30), затем получает 401 KEY_ROTATED. Повторная ротация — 409 KEY_ALREADY_ROTATED, ротация отозванного или истёкшего ключа — 409 KEY_NOT_ACTIVE. Ротация никогда не расширяет доступ: ключ не может выпустить преемника с правами или origins, которых у него нет; ключ, привязанный к индексу, ротирует только ключи своего индекса; ключ не может ротировать ключ, который переживёт его самого (403 KEY_LIFETIME_EXCEEDS_CALLER); ключ, сам находящийся в льготном периоде после ротации, не может ротировать ключи и выпускать ограниченные ключи (403 KEY_IN_GRACE).
  • Владельцы получают одно напоминание, когда ключ перестанет работать в течение 7 дней (истечение срока или конец льготного периода ротации).
  • Отзыв — в консоли, действует немедленно: следующий запрос с этим ключом получит 401. Отзыв ключа, находящегося в льготном периоде ротации, завершает и льготный период.
  • lastUsedAt обновляется при каждом аутентифицированном вызове, поэтому «мёртвые» ключи легко найти в консоли.

Администрирование платформы

/api/v1/admin/* и POST /billing/invoices/generate предназначены оператору развёртывания: кроме API-ключа нужен заголовок x-platform-admin-token, равный SEARCH_PLATFORM_ADMIN_TOKEN сервера. Без него (или если переменная не задана) — 403 FORBIDDEN, попытка пишется в аудит.

Ключи для браузера

Никогда не отправляйте aac_live_… в браузер. Используйте POST /indexes/{slug}/scoped-key на сервере (право settings:write) или, лучше, POST /embed/session: он возвращает короткоживущий токен сессии только для поиска (по умолчанию 15 минут, максимум час), который виджет использует через прокси /embed/*, так что и креденшл движка на страницу не попадает. У ограниченного ключа фильтр тенанта и лимит выдачи встроены. Подробнее — в разделе Сессия встраивания.

On this page