Ir al contenido

Webhooks

RolChat entrega los eventos a tus sistemas como peticiones HTTP POST firmadas. Esta página describe los webhooks de plugin; los webhooks que envía una regla de Automatización difieren en reintentos, tiempo de espera y rotación del secreto, consulta Webhooks de automatización. Las mismas reglas se aplican en sentido contrario cuando tu sistema, un plugin o un proveedor envían datos a RolChat. Verifica cada envío en el orden indicado abajo antes de actuar.

POST /your/endpoint HTTP/1.1
Content-Type: application/json
User-Agent: RolChat-Webhook/1.0
X-RolChat-Timestamp: 1713615825
X-RolChat-Signature: sha256=a1b2c3…
X-RolChat-Nonce: nonce_01HKQN9…
X-RolChat-Event-Id: evt_01HKQN9…
{ "id": "evt_01HKQN9…", "type": "conversation.created", "occurred_at": "…", "data": { … } }
Cabecera Significado
X-RolChat-Timestamp Segundos Unix en el momento del envío. Forma parte del mensaje firmado.
X-RolChat-Signature sha256=<hex>. El prefijo nombra el algoritmo para poder cambiarlo más adelante.
X-RolChat-Nonce Un ULID único para esta petición HTTP. Un reintento recibe un nonce nuevo.
X-RolChat-Event-Id El ID propio del evento. Estable entre reintentos; úsalo para deduplicar.

Los envíos salientes solo van a endpoints HTTPS. Una URL HTTP se rechaza al crear la suscripción.

El mensaje firmado es la marca de tiempo, un punto literal y el cuerpo sin procesar de la petición, byte a byte:

canonical = "<timestamp>.<body>"
signature = hex( HMAC-SHA256( secret, canonical ) )

Firma los bytes que recibiste, no una copia reserializada del JSON analizado. Los cambios de espacios o del orden de las claves rompen la firma. SHA-256 es el único algoritmo aceptado.

Haz estas cinco comprobaciones en orden. Hay ejemplos en Python, Node.js, Go, Ruby y PHP en la página de ejemplos de verificación.

  1. Vigencia. Rechaza si |now − X-RolChat-Timestamp| > 300 segundos (400). Cinco minutos toleran el desfase de reloj y hacen que una petición capturada no sirva de nada pasado ese tiempo. Mantén tu servidor sincronizado por NTP.
  2. Firma. Calcula el valor esperado y compáralo con una comparación en tiempo constante (hmac.compare_digest, crypto.timingSafeEqual, hash_equals). Rechaza con 401 si no coincide. Una comparación de cadenas normal filtra información de tiempos y no es aceptable.
  3. Nonce. Guarda X-RolChat-Nonce con un TTL de 10 minutos mediante una operación atómica de escribir si no existe (SET NX EX 600). Si ya existe, rechaza con 409: la petición es un reenvío. Si tu almacén de nonces no está disponible, falla de forma cerrada con 503 para que RolChat reintente; nunca recurras a “aceptar”.
  4. Analiza el cuerpo solo en este momento.
  5. Deduplica por ID de evento. Los reintentos llevan un nonce nuevo, pero el mismo X-RolChat-Event-Id. Si ya procesaste ese ID en los últimos siete días, responde 200 sin volver a procesarlo.

Responde 2xx en cuanto el envío esté aceptado de forma segura; haz el trabajo de forma asíncrona. RolChat espera una respuesta durante 15 segundos.

  • Un secreto de webhook son 64 bytes aleatorios codificados en base64url (unos 86 caracteres). Se genera al crear la suscripción o el plugin y se muestra una vez.
  • Guárdalo en tu propio almacén de secretos o en variables de entorno; RolChat solo conserva una copia cifrada.
  • Se recomienda rotarlo a los 90 días; el producto muestra un recordatorio, pero nunca desactiva una suscripción por no rotarlo.
  • La rotación usa una ventana de solapamiento: tras POST /api/v1/plugins/{id}/webhook-secret/rotate, tanto el secreto antiguo como el nuevo sirven para verificar durante siete días, los envíos nuevos se firman con el nuevo y el antiguo se elimina al terminar la ventana. Nada se rompe en el momento de rotar.
  • Si un secreto se filtra, POST /api/v1/plugins/{id}/webhook-secret/revoke lo invalida de inmediato, emite uno nuevo, envía un email a los administradores de la cuenta y escribe una entrada de auditoría.

Una respuesta que no sea 2xx o un fallo de red programa un reintento:

Intento Espera desde el anterior
1 inmediatamente
2 15 segundos
3 1 minuto
4 5 minutos
5 30 minutos
6 2 horas
7 8 horas
8 24 horas

Se reintentan 408, 429, 5xx y los errores de red. 400, 401, 403, 404 y 410 no: el envío va directamente a la cola de mensajes fallidos, porque reintentar una firma rechazada o un endpoint inexistente no sirve de nada. Tras ocho intentos fallidos, el envío también pasa a la cola de mensajes fallidos.

Los mensajes fallidos se conservan 30 días y son visibles en Configuración → Plugins → {plugin} → Registro de webhooks → DLQ, donde un administrador puede volver a enviar uno (POST /api/v1/plugins/{id}/webhook-dlq/{entry_id}/replay).

  • Cuerpo saliente: 1 MB por defecto (configurable por plugin). Cuerpo entrante en RolChat: 5 MB. Si es mayor, 413.
  • Un plugin puede declarar allowed_source_ips; RolChat aplica esa lista de IP permitidas antes de verificar.
  • Puedes fijar el user agent RolChat-Webhook/1.0 como comprobación adicional de coherencia. No es un control de seguridad.

Los proveedores envían datos a RolChat en /api/v1/webhooks/{category}/{adapter} con sus propios esquemas de firma (Twilio, Telnyx, Bandwidth, Meta para WhatsApp, Stripe). Cada adaptador verifica la firma de su proveedor, normaliza el contenido y lo vuelve a publicar en el bus de eventos interno con una firma de RolChat. Tu propio sistema puede enviar datos a RolChat con las mismas cabeceras X-RolChat-* descritas arriba, firmadas con el secreto del plugin al que pertenece el endpoint.

La acción Enviar petición HTTP del módulo Automatización tiene sus propias reglas de envío:

  • Un secreto por cuenta. Muéstralo o rótalo en la pantalla de Automatización (Propietario y Administrador). La rotación surte efecto de inmediato: no hay ventana de solapamiento, el secreto anterior deja de verificarse al instante, así que actualiza primero tu receptor o acepta un corte breve.
  • Tiempo de espera: RolChat espera 10 segundos una respuesta.
  • Reintentos: hasta 6 intentos en total. La pausa antes del intento 2 es de 30 segundos, y después de unos 2 minutos, 8 minutos, 32 minutos y 2 horas 8 minutos, cada una con una variación de hasta el 20 %. Una sola pausa nunca supera las 6 horas.
  • Qué se reintenta: errores de red, tiempos de espera agotados, 5xx, 408, 425 y 429. Otras respuestas 4xx, una dirección bloqueada o un cuerpo demasiado grande no se reintentan: el envío pasa directamente a la cola de mensajes fallidos, igual que tras el último intento fallido.
  • Cabeceras: X-RolChat-Signature, X-RolChat-Signature-V2, X-RolChat-Timestamp, X-RolChat-Delivery-Id, X-RolChat-Attempt.

POST /api/v1/webhooks/test-signature envía un evento sintético firmado al endpoint del plugin que hace la llamada, para que puedas verificar tu implementación de principio a fin antes de que llegue tráfico real.

  • Verificar contra el JSON analizado y recodificado en lugar de los bytes sin procesar.
  • Usar == para comparar firmas.
  • Deduplicar por nonce (cada reintento tiene uno nuevo) en lugar de por ID de evento.
  • Un reloj desfasado más de cinco minutos.
  • Hacer trabajo lento antes de responder, agotar el plazo de 15 segundos y volver a recibir el mismo evento.