Справочник 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#.

Единый конверт ответа для всех эндпоинтов ниже:

JSON
{ "meta": { "request": "...", "unique": "...", "timestamp": "...", "milliseconds": 0 }, "data": { }, "errors": [] }

При ошибке datanull, 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}/* в режиме RegisteredUsersJWT посетителя из ответа .../chat-visitors/register или .../login
?key= (query)/api/v1/links/{slug}/* в режиме KeyInUrlСекрет ссылки, показанный один раз при создании

Для Open и WebhookConfirmed режимов публичной ссылки дополнительный заголовок не нужен — WebhookConfirmed сервер проверяет сам, синхронным запросом на ваш URL (см. «Ссылка на чат»).


GET /integration/v1/assistant

Проверка ключа — получить имя ассистента до того, как показывать интерфейс чата.

Заголовки: X-Assistant-Key (обязателен).

Ответ (200):

JSON
{ "data": { "name": "Ассистент поддержки" } }

Ошибки: 401 — ключ отсутствует/недействителен/отозван. 403 — тенант заблокирован или Origin не входит в AllowedOrigins ключа.

cURL
curl https://<ваш-домен>/integration/v1/assistant \
  -H "X-Assistant-Key: pk_ваш_ключ"

POST /integration/v1/chats

Явно создать новый чат (не дожидаясь первого сообщения) — удобно, если интерфейсу нужен chatToken заранее (например, чтобы сразу показать пустое окно диалога).

Заголовки: X-Assistant-Key (обязателен).

Тело запроса:

JSON
{
  "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):

JSON
{ "data": { "chatToken": "ct_...", "chat": { "kind": "Guest", "title": null, "messageCount": 0 } } }

Ошибки: 401/403 — как выше. 422customer передан с публичным ключом либо не прошёл валидацию.

cURL
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 } }

Ошибки: 404X-Chat-Token не найден, просрочен или принадлежит другому ассистенту (сервер намеренно не различает эти случаи — анти-оракул).

cURL
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):

JSON
{
  "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
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, с пагинацией):

JSON
{
  "data": {
    "items": [{ "role": "User", "text": "...", "sequence": 0, "createdAt": "..." }],
    "pagination": { "currentPage": 1, "pageSize": 20, "totalItems": 2, "totalPages": 1 }
  }
}

Элементы истории не содержат id — при сопоставлении с уже показанными сообщениями ориентируйтесь на sequence, а не на id (он есть только в ответе на отправку сообщения).

cURL
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
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
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
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).

cURL
# Пример для режима 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": "Здравствуйте!" }'
cURL
# Пример для режима 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
curl -X POST https://<ваш-домен>/api/v1/chat-visitors/login \
  -H "Content-Type: application/json" \
  -d '{ "email": "visitor@example.com", "password": "..." }'

Сводная таблица кодов ошибок

codeТипичный HTTP-статусСмысл
IncorrectValue422Поле не прошло валидацию (формат/диапазон)
IncorrectCredentials422Неверный пароль/email при unlock, login посетителя
NotFound404Ресурс не найден (chatToken/slug/ссылка)
NotUnique422Email посетителя уже зарегистрирован
HeaderRequired422Обязательный заголовок отсутствует
UnprocessableEntity422Общая ошибка бизнес-валидации (например customer с публичным ключом)
— (без кода, 429)429Превышен rate limit — errors[0].message без Retry-After

code — открытое множество строк, не закрытый enum: не проверяйте его через switch без default-ветки на будущее.