Chatbot WebSocket API (Live Chat)

WebSocket API

Используйте WebSocket API для живого чата в реальном времени: мгновенная доставка сообщений, индикаторы набора текста, статус присутствия, автоперевод и управление жизненным циклом сессии. Один и тот же сокет обслуживает виджеты посетителей и панель агента, поэтому вы можете создать собственную консоль оператора или управлять живым чатом из своего бэкенда.

Эндпоинт

wss://webchatagent.com/api/livechat

Весь трафик передается в формате JSON. Вы отправляете события client:*, а сервер возвращает события livechat:*. Каждое сообщение содержит поле type.

Роли подключения

При подключении вы указываете роль в поле as:

РольОписание
userПосетитель сайта в чате.
adminОператор человек, управляющий сессиями живого чата.
widgetВстроенный виджет чата в режиме мониторинга (до перехвата диалога).

Роль определяет, какие данные вы получаете: клиенты admin получают полную историю сообщений и события только для администраторов, а клиенты user получают только новые текущие события (посетители загружают свою историю через REST эндпоинт истории, а не через сокет).

Краткая схема работы

  1. Откройте сокет и отправьте client:join, указав ваши chatbotId, sessionId и as.
  2. Сервер ответит сообщением { "type": "livechat:status", "ok": true } для подтверждения входа. Затем администраторы получат историю сообщений и текущий снимок livechat:status.
  3. Отправляйте client:message для публикации и получайте livechat:message для каждого нового сообщения.
  4. Отправляйте client:typing и получайте livechat:typing для индикации набора текста.
  5. Завершите диалог с помощью client:end или получите livechat:ended, когда другая сторона закроет чат.

Клиентские события (вы отправляете)

client:join

Первое событие после подключения. Выполняет вход в комнату сессии (а для администраторов также в комнату чат-бота).

{
  "type": "client:join",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "as": "user",
  "lang": "en",
  "translateEnabled": true,
  "retranslateBacklog": false
}
ПолеТипОбязательноОписание
chatbotIdstringДаUUID вашего чат-бота. Для администратора, отслеживающего всех ботов, специальное значение "all" выполняет подключение без привязки к конкретной комнате.
sessionIdstringДаID сессии чата.
asstringДаuser, admin или widget.
langstringНетПредпочитаемый код языка (например, en, de, fr). Задает целевой язык перевода.
translateEnabledbooleanНетВключить автоперевод для этой сессии (по умолчанию: включен).
retranslateBacklogbooleanНетПовторно переводить существующие сообщения из истории на язык lang при входе (для admin).

client:message

Отправка сообщения в сессию. Сервер сохраняет его, переводит при включенной функции и рассылает событие livechat:message.

{
  "type": "client:message",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "sender": "user",
  "content": "I need help with my order",
  "lang": "en"
}
ПолеТипОбязательноОписание
chatbotIdstringДаUUID вашего чат-бота.
sessionIdstringДаID сессии чата.
senderstringДаuser или admin.
contentstringДаТекст сообщения. Пустой или отсутствующий content игнорируется.
langstringНетПодсказка языка сообщения для перевода.

Первое сообщение от admin в сессии со статусом waiting открывает ее (статус → open) и автоматически добавляет системное уведомление о подключении оператора.

client:typing

Рассылка индикатора набора текста всем участникам сессии.

{
  "type": "client:typing",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "sender": "user",
  "isTyping": true
}

client:meta

Обновление метаданных сессии (текущая страница), чтобы операторы видели, где находится посетитель.

{
  "type": "client:meta",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "pageUrl": "https://example.com/pricing",
  "pageTitle": "Pricing - Example",
  "referrer": "https://google.com",
  "browserLanguage": "en-US"
}

client:agent_takeover

Оператор превентивно перехватывает сессию у AI (переводит ее в open / human). Доступно только для роли admin.

{
  "type": "client:agent_takeover",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID"
}

client:end

Завершение сессии.

{
  "type": "client:end",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "reason": "resolved"
}

client:widget_open / client:widget_close

Отправляется виджетом для регистрации или отмены регистрации активной сессии для отображения у администратора (именно это заполняет livechat:widget_sessions).

{
  "type": "client:widget_open",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "pageUrl": "https://example.com",
  "pageTitle": "Home",
  "browserLanguage": "en-US"
}

Серверные события (вы получаете)

livechat:status

Две формы: простое подтверждение входа { "type": "livechat:status", "ok": true } и снимок статуса сессии (ниже).

{
  "type": "livechat:status",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "status": "open",
  "mode": "human",
  "userName": "John",
  "userEmail": "john@example.com",
  "userLanguage": "en"
}
ПолеТипОписание
statusstringwaiting (оператор еще не подключился), open (оператор подключен) или closed.
modestringbot или human.
userNamestring | nullИмя посетителя, если оно получено через раздел Лиды.
userEmailstring | nullЭл. почта посетителя, если она получена.
userLanguagestring | nullОпределенный язык посетителя.

livechat:message

Новое сообщение (или сообщение из истории).

{
  "type": "livechat:message",
  "id": 1024,
  "sessionId": "SESSION_ID",
  "sender": "admin",
  "content": "Hello! How can I help you today?",
  "country": "DE",
  "createdAt": "2025-01-15T10:30:00Z",
  "file": null,
  "audience": "admin",
  "historical": false
}
ПолеТипОписание
idnumberID сообщения (соответствует id в истории REST).
senderstringuser, admin или system.
contentstringТекст сообщения. Для клиентов admin с включенным переводом текст уже переведен на язык оператора.
countrystring | nullКод страны отправителя, если определен.
createdAtstringВременная метка ISO 8601.
fileobject | nullМетаданные прикрепленного файла (uploadId, name, mimeType, size, url, isImage), если сообщение содержит загрузку.
audiencestring | nullЗначение "admin" для копии сообщения, предназначенной оператору. В копии для пользователя это поле опущено.
historicalbooleanЗначение true для сообщений из истории, воспроизводимых при подключении.

Системные сообщения: когда sender имеет значение system, поле content содержит токен, который ваш клиент должен локализовать, а не отображать буквально: __agent_joined__, __livechat_ended__ или __livechat_timeout__.

livechat:typing

Индикатор набора текста от другого участника: { type, chatbotId, sessionId, sender, isTyping }.

livechat:presence

Статус онлайн/оффлайн посетителя в сессии: { type, chatbotId, sessionId, online } (boolean).

livechat:meta

Обновленные метаданные сессии (текущая страница, заголовок, реферер), только для администратора.

livechat:ended

Сессия была закрыта.

{
  "type": "livechat:ended",
  "sessionId": "SESSION_ID",
  "reason": "admin_closed"
}

Поле reason принимает одно из значений: admin_closed, already_closed или timeout.

События только для администраторов

СобытиеПолезная нагрузкаНазначение
livechat:active_count{ chatbotId, count }Активные сессии (ожидание + открытые).
livechat:waiting_count{ chatbotId, count }Сессии в ожидании (бейдж для чатов без ответа).
livechat:new_request{ chatbotId, sessionId, status, mode, ... }Для нового живого чата требуется оператор.
livechat:widget_sessions{ chatbotId, chatbotName, sessions }Текущий список активных сессий виджета.
livechat:notification{ chatbotId, sessionId, content, sender }Новое сообщение, пока оператор находится в другой части панели управления.

Автоперевод

Сокет может автоматически переводить сообщения между языками посетителя и оператора:

  • Подключитесь с параметром translateEnabled: true и укажите в lang ваш язык.
  • Сообщения от собеседника приходят уже переведенными на ваш lang. Каждая сторона сохраняет исходный текст, а переведенная копия доставляется другому участнику.
  • Перевод выполняется с помощью Gemini, благодаря чему оператор может общаться с посетителем на любом языке без ручного перевода.

Пример: собственный клиент живого чата

const ws = new WebSocket('wss://webchatagent.com/api/livechat');

ws.onopen = () => {
  ws.send(JSON.stringify({
    type: 'client:join',
    chatbotId: 'YOUR_CHATBOT_ID',
    sessionId: 'SESSION_ID',
    as: 'user',
    lang: 'en'
  }));
};

ws.onmessage = (event) => {
  const data = JSON.parse(event.data);

  switch (data.type) {
    case 'livechat:status':
      // Join ack ({ ok: true }) or a session snapshot ({ status, mode, ... })
      if (data.ok) console.log('Joined');
      else console.log(`Status: ${data.status}, mode: ${data.mode}`);
      break;
    case 'livechat:message':
      if (data.sender === 'system') {
        // Localize tokens like __agent_joined__ / __livechat_ended__
        console.log('[system]', data.content);
      } else {
        console.log(`${data.sender}: ${data.content}`);
      }
      break;
    case 'livechat:typing':
      console.log(`${data.sender} is typing: ${data.isTyping}`);
      break;
    case 'livechat:ended':
      console.log(`Session ended: ${data.reason}`);
      ws.close();
      break;
  }
};

function sendMessage(text) {
  ws.send(JSON.stringify({
    type: 'client:message',
    chatbotId: 'YOUR_CHATBOT_ID',
    sessionId: 'SESSION_ID',
    sender: 'user',
    content: text,
    lang: 'en'
  }));
}

function sendTyping(isTyping) {
  ws.send(JSON.stringify({
    type: 'client:typing',
    chatbotId: 'YOUR_CHATBOT_ID',
    sessionId: 'SESSION_ID',
    sender: 'user',
    isTyping
  }));
}