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
2xxpara 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
}