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:
| Rol | Descripción |
|---|---|
user | Un visitante del sitio web en un chat. |
admin | Un agente humano que gestiona sesiones de chat en vivo. |
widget | El 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
- Abre el socket y envía
client:joincon tuchatbotId,sessionIdyas. - 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 delivechat:status. - Envía
client:messagepara publicar; recibelivechat:messagepara cada mensaje nuevo. - Envía
client:typing/ recibelivechat:typingpara los indicadores de escritura. - Finaliza con
client:end, o recibelivechat:endedcuando 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
}
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
chatbotId | string | Sí | El UUID de tu chatbot. Para un administrador que monitoriza todos los bots, el valor especial "all" se une sin una sala específica. |
sessionId | string | Sí | El ID de sesión de chat. |
as | string | Sí | user, admin o widget. |
lang | string | No | Código de idioma preferido (por ejemplo, en, de, fr). Define el destino de la traducción. |
translateEnabled | boolean | No | Habilita la traducción automática para esta sesión (predeterminado: habilitado). |
retranslateBacklog | boolean | No | Vuelve 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"
}
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
chatbotId | string | Sí | El UUID de tu chatbot. |
sessionId | string | Sí | El ID de sesión de chat. |
sender | string | Sí | user o admin. |
content | string | Sí | El texto del mensaje. Si content está vacío o falta, se descarta. |
lang | string | No | Indicació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"
}
| Campo | Tipo | Descripción |
|---|---|---|
status | string | waiting (aún sin agente), open (agente conectado) o closed. |
mode | string | bot o human. |
userName | string | null | Nombre del visitante, si se ha recopilado a través de Leads. |
userEmail | string | null | Correo electrónico del visitante, si se ha recopilado. |
userLanguage | string | null | Idioma 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
}
| Campo | Tipo | Descripción |
|---|---|---|
id | number | ID del mensaje (coincide con el id del historial REST). |
sender | string | user, admin o system. |
content | string | Texto del mensaje. Para clientes admin con traducción activada, ya está traducido al idioma del administrador. |
country | string | null | Código de país del remitente, si se detecta. |
createdAt | string | Marca de tiempo ISO 8601. |
file | object | null | Metadatos del archivo adjunto (uploadId, name, mimeType, size, url, isImage) cuando el mensaje es una subida. |
audience | string | null | "admin" en la copia del mensaje dirigida al administrador. La copia dirigida al usuario lo omite. |
historical | boolean | true para mensajes del historial acumulado reproducidos al unirse. |
Mensajes del sistema: cuando
senderessystem,contentes 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
| Evento | Payload | Propó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: truey definelangcon 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
}));
}
