Webhooks & eventos

DuLabs hace POST a tu endpoint cuando ocurre un evento en un número conectado. Configura la URL por número (dashboard o POST /webhooks); el secreto de firma se muestra una sola vez.

Tipos de evento

  • message.received — llegó un mensaje entrante.
  • message.status — cambió el estado de un mensaje enviado (sent / delivered / read / failed).

Entrega, reintentos y deduplicación

  • Responde 2xx para confirmar. Si no, DuLabs reintenta con backoff exponencial acotado y, tras agotar los intentos, mueve el evento a DLQ.
  • Entrega at-least-once: puedes recibir un evento más de una vez. Deduplica por X-DuLabs-Event-ID.
  • Puedes reintentar manualmente entregas en DLQ/fallidas desde el dashboard (Events).

Verificar la firma

Cada request incluye X-DuLabs-Signature, X-DuLabs-Timestamp y X-DuLabs-Event-ID. La firma es HMAC-SHA256 (hex) de {timestamp}.{cuerpo-crudo} con tu secreto whsec_…. Verifica siempre antes de procesar, con comparación en tiempo constante.

Verificación (Node/TS)
# El endpoint de tu webhook recibe cada evento con estas cabeceras:
#   X-DuLabs-Signature: <hex HMAC-SHA256 de "{timestamp}.{cuerpo-crudo}">
#   X-DuLabs-Timestamp: <unix segundos>
#   X-DuLabs-Event-ID:  <id único del evento>
#
# Recalcula HMAC-SHA256("{timestamp}.{cuerpo-crudo}") con tu whsec_… y compáralo
# en tiempo constante con X-DuLabs-Signature. Rechaza si difiere o si el
# timestamp está fuera de una ventana de ~5 minutos.

Firma el timestamp junto al cuerpo (no solo el cuerpo): así cada envío tiene una firma distinta y puedes rechazar reenvíos viejos. Usa el cuerpo crudo, no el JSON re-serializado.

Forma del evento

{
  "type": "message.received",
  "eventId": "…",            // deduplica con X-DuLabs-Event-ID
  "workspaceId": "…",
  "whatsappNumberId": "…"
  // + datos del evento
}