Webhooks salientes
Qué resuelve
Sección titulada «Qué resuelve»Cuando algo pasa en Chats, Smarty se lo cuenta a tu sistema: un mensaje que llega, una conversación que se resuelve, una que pasa a otra persona. Sirve para alimentar tu CRM, tu hoja de control o cualquier automatización propia sin que nadie tenga que copiar datos a mano.
Cómo se configura
Sección titulada «Cómo se configura»- En el panel, entrá a Chats → Integraciones → Webhooks.
- Cargá la URL de tu sistema (tiene que ser
https). - Elegí qué eventos querés recibir.
- Guardá el secreto que se muestra una sola vez: con él vas a verificar que cada aviso viene de Smarty.
Los eventos
Sección titulada «Los eventos»| Evento | Cuándo se manda |
|---|---|
message.received | Llegó un mensaje del cliente. |
message.sent | Alguien del equipo, o la IA, le mandó un mensaje al cliente. |
conversation.created | Nació una conversación nueva. |
conversation.resolved | La conversación se marcó como resuelta. |
conversation.reopened | Una conversación resuelta volvió a abrirse. |
conversation.assigned | La conversación pasó a otra persona (incluye la primera asignación). |
conversation.sla_breached | Se venció el tiempo de primera respuesta o de resolución. |
Las notas internas del equipo no se mandan nunca.
Qué llega
Sección titulada «Qué llega»Cada aviso es un POST con un JSON:
{ "id": "evt_…", "type": "message.received", "timestamp": "2026-09-06T15:04:05Z", "data": { "message_id": "…", "conversation_id": "…", "phone_line_id": "…", "direction": "inbound", "type": "text", "body": "Hola, ¿tienen stock?", "sender_type": "customer", "wa_message_id": "…", "has_media": false, "created_at": "2026-09-06T15:04:05Z" }}Los eventos de conversación traen conversation_id, display_id, status,
contact_phone, contact_name, assigned_agent_id, team_id, tags y
crm_lead_id. conversation.resolved agrega resolved_by y resolved_at;
conversation.assigned agrega previous_agent_id; conversation.sla_breached
agrega sla (first_response o resolution) y due_at.
Cómo verificar la firma
Sección titulada «Cómo verificar la firma»Smarty firma con el estándar Standard Webhooks. Cada pedido trae tres cabeceras:
| Cabecera | Contenido |
|---|---|
webhook-id | Id único del aviso. Si te llega dos veces, es el mismo. |
webhook-timestamp | Segundos desde 1970 en que se mandó. |
webhook-signature | v1,<firma en base64>. Puede traer más de una separada por espacio. |
La firma es un HMAC-SHA256 del texto webhook-id.webhook-timestamp.cuerpo
con tu secreto. Rechazá el aviso si la firma no coincide o si el
webhook-timestamp tiene más de 5 minutos.
import { createHmac, timingSafeEqual } from 'node:crypto';
function esDeSmarty(req, cuerpoCrudo, secreto) { const id = req.headers['webhook-id']; const ts = req.headers['webhook-timestamp']; const esperada = createHmac('sha256', Buffer.from(secreto, 'base64')) .update(`${id}.${ts}.${cuerpoCrudo}`).digest('base64'); return req.headers['webhook-signature'].split(' ') .some((f) => f === `v1,${esperada}`);}Reintentos
Sección titulada «Reintentos»Respondé 2xx en menos de 15 segundos. Si tu sistema no contesta o devuelve
error, Smarty vuelve a intentar durante unas 76 horas (a los 5 segundos,
5 minutos, 30 minutos, 2 horas, y así). Un endpoint que falla 5 días seguidos
se apaga solo; si contestás 410 Gone, se apaga en el acto. Los avisos que
no se pudieron entregar quedan en el panel y se pueden reenviar con un clic.
Cada aviso puede llegar más de una vez: usá webhook-id para no procesar
dos veces el mismo.
¿Te sirvió esta página?
Gracias. Lo tenemos en cuenta.