WebSocket API de Chatbot (Chat en vivo)

WebSocket API

Usa la WebSocket API para chat en vivo en tiempo real: entrega instantánea de mensajes, indicadores de escritura, presencia, traducción automática y ciclo de vida de la sesión. El mismo socket alimenta los widgets de visitantes y el panel de agentes, por lo que puedes crear una consola de agentes personalizada o gestionar el chat en vivo desde tu propio backend.

Endpoint

wss://webchatagent.com/api/livechat

Todo el tráfico es JSON. Envías eventos client:*; el servidor devuelve eventos livechat:*. Cada mensaje incluye un campo type.

Roles de conexión

Cuando te unes, declaras un rol con el campo as:

RolDescripción
userUn visitante del sitio web en un chat.
adminUn agente humano que gestiona sesiones de chat en vivo.
widgetEl widget de chat integrado en modo de monitorización (antes de una toma de control).

El rol determina lo que recibes: los clientes admin reciben todo el historial acumulado de mensajes y los eventos exclusivos de administración; los clientes user reciben únicamente los nuevos eventos en vivo (los visitantes cargan su propio historial a través del endpoint de historial REST, no mediante el socket).

Flujo rápido

  1. Abre el socket y envía client:join con tu chatbotId, sessionId y as.
  2. El servidor responde con { "type": "livechat:status", "ok": true } para confirmar la unión. A continuación, los administradores reciben el historial de mensajes y una instantánea actual de livechat:status.
  3. Envía client:message para publicar; recibe livechat:message para cada mensaje nuevo.
  4. Envía client:typing / recibe livechat:typing para los indicadores de escritura.
  5. Finaliza con client:end, o recibe livechat:ended cuando la otra parte cierre la sesión.

Eventos de cliente (los que envías)

client:join

El primer evento tras la conexión. Se une a la sala de la sesión (y, en el caso de los administradores, a la sala del chatbot).

{
  "type": "client:join",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "as": "user",
  "lang": "en",
  "translateEnabled": true,
  "retranslateBacklog": false
}
CampoTipoObligatorioDescripción
chatbotIdstringEl UUID de tu chatbot. Para un administrador que monitoriza todos los bots, el valor especial "all" se une sin una sala específica.
sessionIdstringEl ID de sesión de chat.
asstringuser, admin o widget.
langstringNoCódigo de idioma preferido (por ejemplo, en, de, fr). Define el destino de la traducción.
translateEnabledbooleanNoHabilita la traducción automática para esta sesión (predeterminado: habilitado).
retranslateBacklogbooleanNoVuelve a traducir los mensajes existentes del historial acumulado al lang al unirse (admin).

client:message

Publica un mensaje en la sesión. El servidor lo almacena, lo traduce si está habilitado y transmite livechat:message.

{
  "type": "client:message",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "sender": "user",
  "content": "I need help with my order",
  "lang": "en"
}
CampoTipoObligatorioDescripción
chatbotIdstringEl UUID de tu chatbot.
sessionIdstringEl ID de sesión de chat.
senderstringuser o admin.
contentstringEl texto del mensaje. Si content está vacío o falta, se descarta.
langstringNoIndicación del idioma del mensaje para la traducción.

El primer mensaje de admin en una sesión waiting la abre (estado → open) e inserta automáticamente un aviso del sistema de agente incorporado.

client:typing

Transmite un indicador de escritura a todos los participantes en la sesión.

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

client:meta

Actualiza los metadatos de la sesión (página actual) para que los agentes vean dónde está el visitante.

{
  "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

El administrador toma el control de forma proactiva de una sesión de IA (la establece en open / human). Solo administradores.

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

client:end

Finaliza la sesión.

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

client:widget_open / client:widget_close

Enviado por el widget para registrar o anular el registro de una sesión activa para la visibilidad del administrador (esto es lo que rellena livechat:widget_sessions).

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

Eventos del servidor (los que recibes)

livechat:status

Dos formatos: una confirmación básica de unión { "type": "livechat:status", "ok": true } y una instantánea del estado de la sesión (a continuación).

{
  "type": "livechat:status",
  "chatbotId": "YOUR_CHATBOT_ID",
  "sessionId": "SESSION_ID",
  "status": "open",
  "mode": "human",
  "userName": "John",
  "userEmail": "john@example.com",
  "userLanguage": "en"
}
CampoTipoDescripción
statusstringwaiting (aún sin agente), open (agente conectado) o closed.
modestringbot o human.
userNamestring | nullNombre del visitante, si se ha recopilado a través de Leads.
userEmailstring | nullCorreo electrónico del visitante, si se ha recopilado.
userLanguagestring | nullIdioma detectado del visitante.

livechat:message

Un mensaje nuevo (o del historial acumulado).

{
  "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
}
CampoTipoDescripción
idnumberID del mensaje (coincide con el id del historial REST).
senderstringuser, admin o system.
contentstringTexto del mensaje. Para clientes admin con traducción activada, ya está traducido al idioma del administrador.
countrystring | nullCódigo de país del remitente, si se detecta.
createdAtstringMarca de tiempo ISO 8601.
fileobject | nullMetadatos del archivo adjunto (uploadId, name, mimeType, size, url, isImage) cuando el mensaje es una subida.
audiencestring | null"admin" en la copia del mensaje dirigida al administrador. La copia dirigida al usuario lo omite.
historicalbooleantrue para mensajes del historial acumulado reproducidos al unirse.

Mensajes del sistema: cuando sender es system, content es un token que tu cliente debe localizar, no mostrar textualmente: __agent_joined__, __livechat_ended__ o __livechat_timeout__.

livechat:typing

Indicador de escritura de otro participante: { type, chatbotId, sessionId, sender, isTyping }.

livechat:presence

Estado en línea/sin conexión del visitante en una sesión: { type, chatbotId, sessionId, online } (boolean).

livechat:meta

Metadatos de sesión actualizados (página actual, título, origen de referencia), solo para administradores.

livechat:ended

La sesión se cerró.

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

reason es uno de los siguientes: admin_closed, already_closed o timeout.

Eventos solo para administradores

EventoPayloadPropósito
livechat:active_count{ chatbotId, count }Sesiones activas (en espera + abiertas).
livechat:waiting_count{ chatbotId, count }Sesiones en espera (distintivo para chats sin respuesta).
livechat:new_request{ chatbotId, sessionId, status, mode, ... }Un nuevo chat en vivo necesita un agente.
livechat:widget_sessions{ chatbotId, chatbotName, sessions }Lista actual de sesiones de widget activas.
livechat:notification{ chatbotId, sessionId, content, sender }Nuevo mensaje mientras el agente está en otra parte del panel.

Traducción automática

El socket puede traducir automáticamente entre los idiomas del visitante y del agente:

  • Únete con translateEnabled: true y define lang con tu idioma.
  • Los mensajes de la otra parte llegan ya traducidos a tu lang. Cada parte conserva su texto original; la copia traducida se entrega al otro extremo.
  • La traducción se ejecuta a través de Gemini, por lo que un agente puede chatear con un visitante en cualquier idioma sin tener que traducir manualmente.

Ejemplo: Cliente de chat en vivo personalizado

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
  }));
}