Download OpenAPI specification:Download
Integración del Chat en Vivo con su propio servidor: cada vez que se produce un mensaje en una conversación le enviamos una petición POST (JSON) a la URL que usted configure, y lo que su servidor responda se aplica en la conversación: contestar al visitante, ofrecerle botones o cerrar el chat.
Así su propia lógica de negocio puede responder en tiempo real: consultar el estado de un pedido en su ERP y contestarlo, identificar al visitante contra su CRM, lanzar una encuesta con botones y guardar la respuesta, o registrar toda la conversación en su sistema de tickets.
No hace falta que responda nada. Si su servidor no contesta, contesta tarde o devuelve algo que no es JSON, la conversación sigue con normalidad y la atiende su agente como siempre. La integración nunca bloquea el chat.
En su panel: Chat → Sitios web, edite el sitio y rellene la sección «Reports a tu servidor»:
- URL (https): debe ser https y un host público. Por seguridad se rechazan las IPs privadas o reservadas (127.0.0.1, 10.x, 192.168.x, ::1…) y no se siguen redirecciones.
- Autenticación: el valor que escriba aquí se envía tal cual en la cabecera Authorization de cada petición (por ejemplo Bearer mi_token_secreto). Compruébelo en su servidor y rechace lo que no cuadre.
La configuración es de la cuenta, no del sitio: se toma la del primer sitio activo que tenga URL, y se aplica a todas las conversaciones de la cuenta, vengan del widget web o de WhatsApp, SMS o email.
Siempre POST con Content-Type: application/json, el cuerpo en JSON y un tiempo máximo de espera de 5 segundos. El campo Evento dice de qué se trata; ignore los eventos que no reconozca (se añadirán nuevos manteniendo el formato).
| Evento | Cuándo se envía | ¿Se aplica su respuesta? |
mensaje-recibido | Mensaje ENTRANTE: lo ha escrito el visitante (Emisor = 0). | Sí. |
mensaje-enviado | Mensaje SALIENTE: lo ha escrito su agente, el asistente de IA o el sistema. Mire Emisor para saber cuál. | No. Se le avisa para que lo registre, pero no se aplica nada: si no, sus propias respuestas dispararian otra respuesta y entraria en bucle. |
pulsacion-chip | El visitante pulsa uno de los chips del mensaje, los [etiqueta|valor]. No navegan a ningún sitio: devuelven un valor a la conversación. | Sí, siempre. |
pulsacion-boton | El visitante pulsa un botón con enlace (un <a class="boton-chat">) de los marcados para seguir. | Sí. |
enlace-pulsado | El visitante pulsa un enlace dentro del texto de los marcados para seguir. | Sí. |
encuesta-cierre | El visitante puntúa la atención con una carita de la encuesta de cierre. | Sí. |
conversacion-cerrada | La conversación se ha cerrado, por un agente o por su propia respuesta. | No. Responder a un cierre reabriría la conversación de hecho, y si su script contesta siempre lo mismo, entraría en bucle. |
Un apunte sobre los tres de pulsación, que es lo que suele costar entender: el chip no lleva URL y su valor vuelve a la conversación como respuesta del visitante; el botón y el enlace sí llevan URL y se le avisa cuando alguien los abre. Separarlos le deja medir qué funciona mejor sin cruzar dos cosas distintas en el mismo contador.
Responda 2xx con un objeto JSON. Todos los campos son opcionales; si responde un cuerpo vacío no se hace nada:
| Campo | Qué hace |
responder | Texto que se publica en la conversación como respuesta al visitante. Admite HTML básico y botones (ver abajo). Máximo 4.000 caracteres. |
ref | Referencia suya (máx. 64 caracteres). Se guarda con el mensaje y vuelve en todos los eventos de pulsación cuando el visitante pulsa un chip, un botón o un enlace de ese mensaje. Es lo que le permite cruzar la pulsación con la petición que la originó. |
html | Fuerza el tratamiento del texto: true lo interpreta como HTML aunque no se reconozca ninguna etiqueta, false lo deja como texto plano aunque las lleve. Si lo omite se decide solo (ver HTML). |
cerrar | true cierra la conversación. |
seguir | true para saber cuándo el visitante abre los enlaces de este mensaje. Ver Seguimiento de enlaces. |
estadistica | Nombre con el que se agrupan los clics de este mensaje para poder contarlos (máx. 40 caracteres). Implica seguir. |
Si quiere enterarse de cuándo alguien abre un enlace suyo, añada "seguir": true. Los enlaces de ese mensaje pasan a apuntar a un redirector nuestro que registra la pulsación y manda al destino, y usted recibe un evento pulsacion-boton o enlace-pulsado.
No se activa nunca por su cuenta, y hay una razón para que usted la valore: con el seguimiento puesto, el visitante ve nuestro dominio al pasar el ratón por encima, no el de destino. Para un enlace a una campaña suele dar igual; para un enlace a su propia web puede restarle confianza.
Enlace por enlace. Lo que ponga en el propio <a> manda sobre lo del mensaje, así que puede activar el seguimiento para todo y dejar uno concreto sin tocar:
<a href="https://suweb.com/oferta" data-seguir="1" data-estadistica="oferta-verano">Ver la oferta</a>
<a href="https://suweb.com/aviso-legal" data-seguir="0">Aviso legal</a>
Sirve igual en las respuestas rápidas que sus agentes tengan guardadas en el panel: basta con escribir el enlace con esos atributos.
Los clics no se almacenan salvo que usted les ponga nombre, con "estadistica": "nombre" o con data-estadistica en el enlace. Sin nombre se le avisa del clic y no se guarda nada: acumular la navegación de sus visitantes sin que nadie lo haya pedido no aporta y son datos personales de por medio.
Use el mismo nombre en varios mensajes para agrupar una campaña entera.
Los botones se escriben dentro del propio texto de responder, con el formato [etiqueta|valor]:
- La etiqueta es lo que ve el visitante (normalmente un emoji, también vale texto).
- El valor es lo que le devolvemos a usted cuando lo pulsa.
- Se admiten hasta 10 botones por mensaje y los marcadores se quitan del texto que se muestra.
- El visitante sólo puede pulsar una vez por mensaje; después los botones quedan desactivados.
Aspecto: si ninguna etiqueta lleva letras ni números (es decir, son emojis o símbolos), los botones se pintan redondos y grandes, como las caritas de la encuesta. En cuanto una etiqueta lleva texto se pintan todos como botones normales. Es automático y no cambia el valor que se devuelve.
Emojis -> redondos: "[😍|5][🙂|4][😐|3][🙁|2][😞|1]"
Texto -> normales: "[Sí|si][No|no]"
Mezcla -> normales: "[😍|5][Prefiero no contestar|x]"
Fuera del chat web no hay botones. En WhatsApp, SMS o email se envía sólo el texto, ya sin los marcadores.
El texto de responder admite HTML básico y siempre se sanea con una lista blanca antes de publicarlo:
- Etiquetas admitidas: b strong i em u s br p ul ol li a code small blockquote. Cualquier otra se descarta pero se conserva su texto.
- Se eliminan por completo (con su contenido) script, style, iframe, img, form y similares, y todos los atributos (style=, onclick=…).
- Los enlaces sólo admiten http, https, mailto y tel, y salen con target="_blank" y rel="noopener noreferrer nofollow".
- Si deja una etiqueta sin cerrar, se cierra sola: un HTML mal formado no rompe el mensaje.
El HTML no hay que pedirlo: si el texto trae alguna etiqueta de las admitidas, se sanea; si no, se trata como texto plano de siempre. Se hace así para que un mensaje corriente como "5 < 10" no se interprete como una etiqueta y pierda ese trozo. Con html puede forzar el criterio en cualquiera de los dos sentidos.
En WhatsApp, SMS o email se envía la versión en texto (los <br> pasan a saltos de línea y los enlaces a texto: url).
Los botones de [etiqueta|valor] devuelven el valor a su servidor, pero a veces lo que hace falta es simplemente llevar al visitante a una página. Para eso, añada la clase boton-chat a un enlace normal:
{
"responder": "<b>Elige tu plan</b><br>Selecciona una opción."
+ "<a href='https://tuweb.com/basico' class='boton-chat'>Plan básico</a>"
+ "<a href='https://tuweb.com/premium' class='boton-chat'>Plan premium</a>"
}
Cada enlace se pinta como un botón de ancho completo, en su propia línea y centrado, con el color que el sitio tenga configurado en el chat (y su contraste, para que con un color claro el texto siga legible). Puede mezclarlos con el resto del HTML: negritas, listas o texto normal.
Diferencias con los botones [etiqueta|valor]:
- Abren una URL en una pestaña nueva; no le envían nada a su servidor ni generan el evento pulsacion-chip.
- No tienen límite de 10 ni se desactivan al pulsarlos: el visitante puede volver a usarlos.
- boton-chat es la única clase que sobrevive al saneado, y sólo en <a>. En cualquier otra etiqueta se descarta, y un enlace cuyo destino no sea http, https, mailto o tel pierde tanto el destino como el aspecto de botón.
- Fuera del chat web salen como el resto de enlaces: texto: url.
1) El visitante escribe su último mensaje («gracias, ya está resuelto») y su servidor recibe mensaje-recibido. Responde con la encuesta y su referencia:
Ojo: la encuesta hay que lanzarla desde un mensaje-recibido. Con mensaje-enviado su respuesta no se aplica (ver la tabla de eventos), así que no sirve para reaccionar a que el agente cierre el chat; para eso está el botón de cerrar con encuesta del panel, que la manda solo.
{
"responder": "Por favor, valore cómo le hemos atendido<br/>[😍|5][🙂|4][😐|3][🙁|2][😞|1]",
"ref": "12345AB"
}
2) El visitante pulsa la primera carita y su servidor recibe el evento encuesta-cierre con su referencia, el valor pulsado y la ficha del visitante:
{
"Evento": "encuesta", "idConversacion": 88, "idMensaje": 1420,
"Canal": "web", "Valor": "5", "Nota": 5,
"Ref": "12345AB", "idAgente": 7, "Fecha": "2026-08-01 12:40:11",
"Visitante": {
"idVisitante": 12, "Nombre": "Ana", "Email": "ana@cliente.com", "Telefono": "",
"IP": "203.0.113.10", "UserAgent": "Mozilla/5.0...",
"Url": "https://sutienda.com/carrito", "Idioma": "es", "Zona": "Europe/Madrid",
"Pais": "Spain", "Ciudad": "Madrid", "Operadora": "Movistar",
"Vars": { "pedido": "8812" },
"idSitio": 3, "Canal": "web", "RefCanal": ""
}
}
3) Su servidor puede aún contestar algo a esa pulsación y cerrar:
{ "responder": "¡Gracias por su valoración!", "cerrar": true }
$esperado = 'Bearer mi_token_secreto';
if (($_SERVER['HTTP_AUTHORIZATION'] ?? '') !== $esperado) { http_response_code(401); exit; }
$d = json_decode(file_get_contents('php://input'), true);
header('Content-Type: application/json');
// Pulsacion de un boton: se cruza con la referencia que enviamos antes
if (($d['Evento'] ?? '') === 'encuesta') {
guardaValoracion($d['Ref'], $d['Valor'], $d['Visitante']['Email'] ?? '');
echo json_encode(['responder' => 'Gracias, lo tendremos en cuenta.', 'cerrar' => true]);
exit;
}
// Mensaje del VISITANTE (Emisor 0). Con los del agente no se responde.
if (($d['Evento'] ?? '') === 'mensaje-recibido') {
if (stripos($d['Cuerpo'], 'pedido') !== false) {
echo json_encode([
'responder' => '<b>Pedido 881</b> enviado. ¿Le ayudo en algo mas? [Sí|si][No|no]',
'ref' => 'PED-881'
]);
exit;
}
}
echo '{}'; // no hacer nada: la conversacion sigue con el agente
Autenticación HTTP Basic. Use su Usuario API como usuario y su API Token como contraseña (los encuentra en su panel, en Tus Datos → Configurar Cuenta). El header resultante es Authorization: Basic base64(UsuarioAPI:APIToken). La mayoría de las librerías HTTP lo construyen automáticamente (curl -u, requests auth=, basic_auth de Ruby, etc.) sin necesidad de codificar el base64 a mano.
basicPETICIÓN POST (JSON) QUE ENVIAMOS A SU URL EN CADA MENSAJE DEL CHAT.
Lleva la cabecera Authorization con el valor que haya configurado en el panel: compruébela y devuelva 401 si no cuadra. Responda 2xx con un JSON (ver «La respuesta de su servidor» en la Introducción) dentro de 5 segundos. Si no responde, la conversación continúa con normalidad y la atiende su agente.
Los campos marcados como propios de los eventos de pulsación (Valor, Nota, Ref, Visitante…) no llegan en los eventos de mensaje, y al revés.
Parámetros recibidos en su script en petición POST con la configuración especificada en su panel de usuario/configuración API.
| Evento required | string Qué ha pasado:
|
| idConversacion required | integer Identificador de la conversación. Es estable durante toda la conversación: úselo para agrupar los mensajes en su sistema. |
| Canal required | string Canal de origen de la conversación: |
| idMensaje required | integer Identificador del mensaje. En los eventos de pulsación es el del mensaje que contenía los botones, no el de la pulsación. |
| Inicio | integer Solo en los eventos de mensaje. |
| Motivo | string Solo en |
| ConEncuesta | integer Solo en |
| Mensajes | integer Solo en |
| Duracion | integer Solo en |
| Destino | string Solo en |
| Estadistica | string Solo en |
| Emisor | integer Sólo en los eventos de mensaje. Quién ha escrito: |
| Cuerpo | string Sólo en los eventos de mensaje. Texto del mensaje. |
| Valor | string Sólo en los eventos de pulsación. El valor del botón pulsado, es decir la parte derecha de su |
| Nota | integer Sólo en los eventos de pulsación. El mismo |
| Texto | string Sólo en los eventos de pulsación. La etiqueta del botón pulsado, tal como la vio el visitante (el emoji o el texto). |
| Ref | string Sólo en los eventos de pulsación. La referencia que usted envió en el campo |
| Visitante | object Sólo en los eventos de pulsación. Ficha de la persona que está chateando:
|
| idAgente | integer Sólo en los eventos de pulsación. Agente que tenía asignada la conversación ( |
| Fecha required | string Fecha y hora del evento, en formato |
{- "Evento": "mensaje-recibido",
- "idConversacion": "88",
- "Canal": "web",
- "idMensaje": "1420",
- "Inicio": "1",
- "Motivo": "agente",
- "ConEncuesta": "0",
- "Mensajes": "14",
- "Duracion": "842",
- "Estadistica": "oferta-verano",
- "Emisor": "0",
- "Cuerpo": "Hola, quiero saber donde esta mi pedido",
- "Valor": "5",
- "Nota": "5",
- "Texto": "😍",
- "Ref": "12345AB",
- "Visitante": "{ \"idVisitante\": 12, \"Nombre\": \"Ana\", \"Email\": \"ana@cliente.com\", \"IP\": \"203.0.113.10\", \"Pais\": \"Spain\", \"Vars\": { \"pedido\": \"8812\" } }",
- "idAgente": "7",
- "Fecha": "2026-08-01 12:40:11"
}