Сессия встраивания
POST /api/v1/embed/session — обмен API-ключа на сервере на короткоживущий токен сессии только для поиска, который безопасно класть на страницу. А также браузерные эндпоинты /embed/*, принимающие этот токен.
POST /api/v1/embed/session
Authorization: Bearer aac_live_…Ключ aac_live_… не должен попадать в браузер. Этот эндпоинт решает именно эту задачу: он обменивает ключ на токен сессии встраивания, привязанный к одному индексу, одному действию (search:read) и сроку жизни. На страницу попадает токен (data-aac-token), ключ остаётся на вашем сервере.
Эндпоинта GET /embed/bootstrap и формы ?key= не существует. Ключ в строке запроса, data--атрибуте или HTML страницы — это именно та утечка, которую эта схема устраняет: эндпоинт читает ключ только из заголовка Authorization, в остальных случаях отвечает 401 UNAUTHORIZED.
Вызывайте его из собственного бэкенда — обработчика маршрута, SSR-прохода или шага сборки — и передавайте полученный token на страницу.
Выпуск сессии
curl -sS -X POST "$AAC_API/embed/session" \
-H "Authorization: Bearer $AAC_KEY" \
-H "Content-Type: application/json" \
-d '{ "index": "documentation", "expires_in": 900 }'| Поле тела | Тип | По умолчанию | Значение |
|---|---|---|---|
index | string ≤ 64 | индекс ключа или самый старый индекс тенанта | Слаг индекса, к которому привязывается сессия. Ключ, привязанный к одному индексу, не может выпустить сессию для соседнего |
expires_in | целое, секунды | 900 (15 минут) | Запрошенный срок жизни, ограничивается диапазоном 60–3600 |
Тело необязательно. Нечисловой expires_in или слишком длинный index — это 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": "Поиск по документации…",
"perPage": 8,
"queryBy": "title,content",
"facets": ["category"],
"showStats": true,
"showRecent": true,
"showVoice": false,
"showImage": false,
"showRelated": false,
"accent": "#2563eb",
"dark": false,
"sortOptions": [
{ "label": "По релевантности", "value": "default" },
{ "label": "Сначала новые", "value": "created_at:desc" }
]
},
"ui": { "name": "AACSearch UI", "version": "1.0.0" },
"request_id": "req_4a6c8e0b2d4f6a8c0e2b4d6f"
}Что гарантирует ответ:
- Токен только для поиска. Он несёт
search:readи ничего больше, поэтому не может писать, удалять или переиндексировать. Компрометация страницы даёт креденшл, который истекает сам и читает только то, что страница и так показывает. - Токен привязан к одному индексу и тенанту. Фильтр тенанта применяется на сервере в каждом запросе; браузер не видит ни инфраструктурного ключа, ни хоста, ни имени коллекции.
- Токен истекает. По умолчанию 900 секунд, максимум 3600. Для долгоживущих страниц выпускайте новый заранее; истёкший токен —
401 EMBED_SESSION_EXPIRED. - Ответ не кешируется. Заголовок
cache-control: no-store; каждый выпуск записывается в журнал аудита (embed.session.issue). - Настройки живые.
settingsберутся изSearchIndex.settings.embed, поэтому изменения в панели оформления консоли применяются при следующей загрузке страницы — без передеплоя.
Список разрешённых origin
Если у ключа заданы allowedOrigins, браузерный вызов с любого другого origin получает 403 ORIGIN_NOT_ALLOWED и не получает CORS-заголовков. Пустой список означает «любой origin». Поскольку эндпоинт сессии предназначен для вызова из вашего бэкенда, серверный вызов не несёт заголовка Origin и проверке не подвергается.
Настройки
| Ключ | Тип | По умолчанию | Действие |
|---|---|---|---|
placeholder | string | Search the docs… | Подсказка в поле ввода |
perPage | number | 8 | Результатов на страницу |
queryBy | string | title,content | query_by в каждом поисковом запросе |
facets | string[] | [] | Поля фасетов в виде списков с чекбоксами (в консоли — не более 6) |
showStats | boolean | true | Строка с числом результатов |
showRecent | boolean | true | Чипы недавних запросов, хранятся локально по индексу |
showVoice | boolean | false | Голосовой ввод браузера через voiceSearch из InstantSearch |
showImage | boolean | false | Показывать изображение результата, если оно есть в документе |
showRelated | boolean | false | Блок «Для вас» под результатами (нужны включённые рекомендации в индексе) |
accent | string | #2563eb | Акцентный цвет кнопок, обводки и ссылок |
dark | boolean | false | Тёмная палитра |
sortOptions | array | релевантность + created_at:desc | Выпадающий список сортировки; первая запись должна иметь default |
Ошибки
{
"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"
}
}| Статус | Код | Когда |
|---|---|---|
| 401 | UNAUTHORIZED | Ключ отсутствует, некорректен, неизвестен или отозван; ключ передан параметром запроса |
| 403 | ORIGIN_NOT_ALLOWED | Браузерный origin вне allowedOrigins ключа |
| 404 | INDEX_NOT_FOUND | Для ключа нет доступного индекса или index указывает на недоступный ключу индекс |
| 422 | VALIDATION_ERROR | Некорректное тело |
| 429 | RATE_LIMITED | Лимит по адресу на /embed/* (у анонимного embed-трафика бюджет меньше) |
Эндпоинты, принимающие токен
Когда на странице есть токен, виджет обращается только к этим эндпоинтам. Все они аутентифицируются токеном — в JSON-теле (token) или, где указано, заголовком Authorization: Bearer aac_sess_… — и никогда API-ключом. Каждый также отвечает на CORS-preflight (OPTIONS) кодом 204.
| Эндпоинт | Назначение |
|---|---|
POST /api/v1/embed/config | Настройки для уже выпущенного токена: { "token": "…" } возвращает index, scope, expires_at и settings |
POST /api/v1/embed/search | Прокси поиска. Тело { token, index, client_id?, personalize?, searches: [...] }, до 5 запросов; токен можно передать и заголовком Bearer. page ≤ 20, per_page обрезается до 50 |
POST /api/v1/embed/events | События поведения: type — view, click, conversion, add_to_cart или impression (сам виджет шлёт view, click и conversion), с document_id, position, query, query_id, session_id, value_cents, items |
POST /api/v1/embed/recommendations | Похожие и персональные элементы для посетителя: client_id, seed_document_id, seed_query, limit (≤ 40) |
POST /api/v1/embed/widget-session | Для сохранённых виджетов из консоли: публичный id виджета (wgt_…) и разрешённый origin дают сессию, ключа на странице нет вообще |
Поиск через прокси проходит тот же конвейер, что и публичный API (журнал запросов, правила, значения по умолчанию, ослабление запроса, did-you-mean), поэтому аналитика видит трафик виджета. Каждый embed-поиск списывается с квоты searches тенанта.
Ошибки токена на этих эндпоинтах:
| Статус | Код | Значение |
|---|---|---|
| 401 | EMBED_SESSION_REQUIRED | Токен не передан |
| 401 | EMBED_SESSION_EXPIRED | Срок токена истёк — выпустите новый |
| 401 | EMBED_SESSION_INVALID | Повреждённый или подделанный токен |
| 403 | FORBIDDEN | У токена нет права search:read |
| 403 | INDEX_MISMATCH | В запросе указан индекс, отличный от индекса токена |
Доступ из браузера
Для виджета и собственного браузерного интерфейса используйте POST /embed/session и /embed/search. Ваш сервер обменивает API-ключ на короткоживущий токен; браузер не получает инфраструктурных ключей и имён хранилищ. Расширенный эндпоинт /scoped-key не используется виджетом и не заменяет поисковый API платформы.