Справочник Integration API
Это полный технический референс единственного контракта, который реально нужен внешнему
разработчику — эндпоинтов /integration/v1/*, публичных ссылок (/api/v1/links/*) и
аккаунтов посетителей (/api/v1/chat-visitors/*). Управленческий API личного кабинета
(/api/v1/assistants, /api/v1/chat/prompts и т.д.) здесь не описан — он предназначен для
самого ЛК, не для внешней интеграции.
Обзорная проза с объяснением концепций — в «Интеграция по API» и «Ссылка на чат». Здесь — по каждому эндпоинту: заголовки, параметры, форма ответа, коды ошибок и пример вызова на cURL, JavaScript, Python, PHP и C#.
Единый конверт ответа для всех эндпоинтов ниже:
{ "meta": { "request": "...", "unique": "...", "timestamp": "...", "milliseconds": 0 }, "data": { }, "errors": [] }При ошибке data — null, errors — непустой массив { "code": "...", "message": "...", "property": "..." }.
Обзор эндпоинтов
| Метод | Путь | Назначение |
|---|---|---|
GET | /integration/v1/assistant | Проверить ключ, получить имя ассистента |
POST | /integration/v1/chats | Явно создать новый чат |
GET | /integration/v1/chats/current | Прочитать текущий чат по X-Chat-Token |
POST | /integration/v1/messages | Отправить сообщение (основной эндпоинт) |
GET | /integration/v1/chats/current/messages | История сообщений текущего чата |
GET | /api/v1/links/check-slug | Проверить занятость slug ссылки |
GET | /api/v1/links/{slug}/access-mode | Узнать режим доступа ссылки |
POST | /api/v1/links/{slug}/unlock | Разблокировать Password-режим |
POST | /api/v1/links/{slug}/chats | Создать чат через публичную ссылку |
POST | /api/v1/links/{slug}/messages | Отправить сообщение через публичную ссылку |
GET | /api/v1/links/{slug}/chats/current/messages | История чата через публичную ссылку |
POST | /api/v1/chat-visitors/register | Регистрация посетителя (режим RegisteredUsers) |
POST | /api/v1/chat-visitors/login | Вход посетителя (режим RegisteredUsers) |
Аутентификация
Два независимых механизма, не смешивать:
| Заголовок | Где используется | Значение |
|---|---|---|
X-Assistant-Key | все /integration/v1/* | Публичный (pk_) или приватный (sk_) ключ ассистента |
X-Chat-Token | продолжение чата, все /integration/v1/* и /api/v1/links/* | Токен конкретного разговора (ct_...), выдаётся при создании чата |
X-Link-Unlock-Token | /api/v1/links/{slug}/* в режиме Password | Короткоживущий токен из ответа .../unlock |
X-Visitor-Token | /api/v1/links/{slug}/* в режиме RegisteredUsers | JWT посетителя из ответа .../chat-visitors/register или .../login |
?key= (query) | /api/v1/links/{slug}/* в режиме KeyInUrl | Секрет ссылки, показанный один раз при создании |
Для Open и WebhookConfirmed режимов публичной ссылки дополнительный заголовок не нужен —
WebhookConfirmed сервер проверяет сам, синхронным запросом на ваш URL (см.
«Ссылка на чат»).
GET /integration/v1/assistant
Проверка ключа — получить имя ассистента до того, как показывать интерфейс чата.
Заголовки: X-Assistant-Key (обязателен).
Ответ (200):
{ "data": { "name": "Ассистент поддержки" } }Ошибки: 401 — ключ отсутствует/недействителен/отозван. 403 — тенант заблокирован
или Origin не входит в AllowedOrigins ключа.
curl https://<ваш-домен>/integration/v1/assistant \
-H "X-Assistant-Key: pk_ваш_ключ"POST /integration/v1/chats
Явно создать новый чат (не дожидаясь первого сообщения) — удобно, если интерфейсу нужен
chatToken заранее (например, чтобы сразу показать пустое окно диалога).
Заголовки: X-Assistant-Key (обязателен).
Тело запроса:
{
"customer": { "externalId": "user-42", "phone": null, "name": null, "email": "user@example.com", "custom": {} },
"context": { "fingerprint": "...", "url": "https://example.com/support", "referrer": "..." }
}Оба поля необязательны. customer — только для приватного (sk_) ключа; с публичным
ключом сервер ответит 422. Все поля customer необязательны, custom — произвольный
словарь строк для вашей аналитики. context собирается автоматически по режиму
DataCollectionMode тенанта — эти поля можно не передавать вовсе, если вызов серверный.
Ответ (200):
{ "data": { "chatToken": "ct_...", "chat": { "kind": "Guest", "title": null, "messageCount": 0 } } }Ошибки: 401/403 — как выше. 422 — customer передан с публичным ключом либо не
прошёл валидацию.
curl -X POST https://<ваш-домен>/integration/v1/chats \
-H "Content-Type: application/json" \
-H "X-Assistant-Key: sk_ваш_приватный_ключ" \
-d '{ "customer": { "externalId": "user-42" } }'GET /integration/v1/chats/current
Прочитать метаданные текущего чата (не сообщения) — узнать kind/title/messageCount.
Заголовки: X-Assistant-Key, X-Chat-Token (оба обязательны).
Ответ (200): { "data": { "kind": "Guest", "title": "...", "messageCount": 4 } }
Ошибки: 404 — X-Chat-Token не найден, просрочен или принадлежит другому ассистенту
(сервер намеренно не различает эти случаи — анти-оракул).
curl https://<ваш-домен>/integration/v1/chats/current \
-H "X-Assistant-Key: pk_ваш_ключ" \
-H "X-Chat-Token: ct_..."POST /integration/v1/messages
Основной эндпоинт — отправить сообщение. Один запрос одновременно продолжает чат (если
передан X-Chat-Token) или лениво создаёт новый (если заголовок не передан).
Заголовки: X-Assistant-Key (обязателен), X-Chat-Token (для продолжения).
Тело запроса: { "text": "...", "customer"?: {...}, "context"?: {...} } — text
обязателен, остальное — как в POST /chats выше.
Ответ (200):
{
"data": {
"chatToken": "ct_...",
"chat": { "kind": "Guest", "title": null, "messageCount": 2 },
"userMessage": { "id": "...", "role": "User", "text": "...", "sequence": 0, "createdAt": "..." },
"assistantMessage": { "id": "...", "role": "Assistant", "text": "...", "sequence": 1, "createdAt": "..." }
}
}chatToken присутствует только когда чат создан этим же запросом — сохраните и
передавайте дальше в X-Chat-Token. Ответ — синхронный, 5–25 секунд, без стриминга (см.
«Сколько ждать ответа»).
Ошибки: 401/403/422 — как выше. 404 — невалидный X-Chat-Token. 429 — превышен
requestsPerMinute (общий лимит на всех посетителей ассистента, без Retry-After).
curl -X POST https://<ваш-домен>/integration/v1/messages \
-H "Content-Type: application/json" \
-H "X-Assistant-Key: pk_ваш_ключ" \
-H "X-Chat-Token: ct_..." \
-d '{ "text": "Расскажите про тарифы" }'GET /integration/v1/chats/current/messages
История сообщений текущего чата, постранично, от старых к новым.
Заголовки: X-Assistant-Key, X-Chat-Token (оба обязательны).
Query: page (по умолчанию 1), pageSize (по умолчанию 20, максимум 100).
Ответ (200, с пагинацией):
{
"data": {
"items": [{ "role": "User", "text": "...", "sequence": 0, "createdAt": "..." }],
"pagination": { "currentPage": 1, "pageSize": 20, "totalItems": 2, "totalPages": 1 }
}
}Элементы истории не содержат id — при сопоставлении с уже показанными сообщениями
ориентируйтесь на sequence, а не на id (он есть только в ответе на отправку сообщения).
curl "https://<ваш-домен>/integration/v1/chats/current/messages?page=1&pageSize=50" \
-H "X-Assistant-Key: pk_ваш_ключ" \
-H "X-Chat-Token: ct_..."Публичные ссылки (/api/v1/links/{slug}/*)
Тот же протокол сообщений, что у /integration/v1/* (chatToken/sequence/JSON-конверт), но
авторизация — по slug из URL + режим-специфичное доказательство доступа вместо
X-Assistant-Key. Полное описание пяти режимов — в «Ссылка на чат».
GET /api/v1/links/check-slug
Публичный, без владения — просто «занято/свободно» (slug уникален глобально, не в рамках одного ассистента). Используется формой создания ссылки в ЛК для live-проверки при вводе.
Query: slug (обязателен).
Ответ: { "data": { "available": true } }
curl "https://<ваш-домен>/api/v1/links/check-slug?slug=my-support-chat"GET /api/v1/links/{slug}/access-mode
Публичный — отдаёт только режим доступа, без секретов, чтобы страница /c/{slug} могла
показать нужную форму (пароль/логин/просто чат) до попытки достучаться до самого чата.
Ответ: { "data": { "accessMode": "Password" } } — одно из Open/KeyInUrl/
RegisteredUsers/Password/WebhookConfirmed.
Ошибки: 404 — slug не существует или ссылка отозвана (сервер не различает эти случаи).
curl "https://<ваш-домен>/api/v1/links/my-support-chat/access-mode"POST /api/v1/links/{slug}/unlock
Только для режима Password. Проверяет пароль и выдаёт короткоживущий (4 часа) unlock-токен
— сам пароль передаётся один раз здесь, не на каждый последующий запрос к чату.
Тело: { "password": "..." }
Ответ: { "data": { "unlockToken": "..." } } — далее передавайте его в заголовке
X-Link-Unlock-Token на все запросы .../chats/.../messages этой ссылки.
Ошибки: 404 — ссылка не в режиме Password/не существует. 422 — неверный пароль
(rate-limited отдельной политикой LinkUnlock, партиция по IP+slug).
curl -X POST https://<ваш-домен>/api/v1/links/my-support-chat/unlock \
-H "Content-Type: application/json" \
-d '{ "password": "секрет" }'POST /api/v1/links/{slug}/chats и POST /api/v1/links/{slug}/messages
Полные аналоги POST /integration/v1/chats и POST /integration/v1/messages — те же тело
запроса и форма ответа, но X-Assistant-Key заменяется на доказательство режима доступа
ссылки (см. таблицу заголовков выше: ?key= для KeyInUrl, X-Visitor-Token для
RegisteredUsers, X-Link-Unlock-Token для Password, ничего — для Open/WebhookConfirmed).
# Пример для режима Password — X-Link-Unlock-Token из предыдущего шага
curl -X POST https://<ваш-домен>/api/v1/links/my-support-chat/messages \
-H "Content-Type: application/json" \
-H "X-Link-Unlock-Token: <unlockToken>" \
-d '{ "text": "Здравствуйте!" }'# Пример для режима KeyInUrl — секрет в query, не в заголовке
curl -X POST "https://<ваш-домен>/api/v1/links/my-support-chat/messages?key=<секрет_ссылки>" \
-H "Content-Type: application/json" \
-d '{ "text": "Здравствуйте!" }'Ошибки: 401 — доказательство доступа отсутствует/неверно. 403 — тенант заблокирован
либо WebhookConfirmed-сервер отказал (fail-closed: недоступность вашего сервера
подтверждения тоже считается отказом). 404 — slug не существует/отозван. 422/429 — как
у /integration/v1/*.
GET /api/v1/links/{slug}/chats/current/messages
Аналог GET /integration/v1/chats/current/messages — те же page/pageSize, тот же формат
ответа, авторизация — тем же доказательством режима доступа + X-Chat-Token.
Аккаунты посетителей (/api/v1/chat-visitors/*)
Используются только режимом RegisteredUsers публичной ссылки. Это отдельная от вашего
личного кабинета ось идентичности — посетитель регистрируется на самой платформе NextAi, не
у вас; полученный токен передаётся в заголовке X-Visitor-Token (см. таблицу выше).
POST /api/v1/chat-visitors/register
Тело: { "email": "...", "password": "..." }
Ответ: { "data": { "token": "...", "visitor": { "id": "...", "email": "..." } } }
Ошибки: 422 — email уже зарегистрирован (code: "NotUnique") либо не прошёл валидацию.
Rate-limited политикой Auth.
POST /api/v1/chat-visitors/login
Тело: { "email": "...", "password": "..." }
Ответ: та же форма, что у register.
Ошибки: 422 — неверный email или пароль (code: "IncorrectCredentials", сервер не
уточняет, что именно неверно — анти-оракул).
curl -X POST https://<ваш-домен>/api/v1/chat-visitors/login \
-H "Content-Type: application/json" \
-d '{ "email": "visitor@example.com", "password": "..." }'Сводная таблица кодов ошибок
code | Типичный HTTP-статус | Смысл |
|---|---|---|
IncorrectValue | 422 | Поле не прошло валидацию (формат/диапазон) |
IncorrectCredentials | 422 | Неверный пароль/email при unlock, login посетителя |
NotFound | 404 | Ресурс не найден (chatToken/slug/ссылка) |
NotUnique | 422 | Email посетителя уже зарегистрирован |
HeaderRequired | 422 | Обязательный заголовок отсутствует |
UnprocessableEntity | 422 | Общая ошибка бизнес-валидации (например customer с публичным ключом) |
— (без кода, 429) | 429 | Превышен rate limit — errors[0].message без Retry-After |
code — открытое множество строк, не закрытый enum: не проверяйте его через switch
без default-ветки на будущее.