Webhooks: que Bongga le avise a tu sistema
Un webhook es lo contrario de la API: en vez de que tu sistema le pregunte a Bongga, Bongga le avisa a tu sistema en cuanto algo pasa. Se configuran en Configuración → API (/configuracion/api).
Eventos disponibles
lead.created: entra un lead nuevo, venga de donde venga.lead.stage_changed: un lead se mueve de etapa en el embudo.contact.created: aparece un contacto nuevo.message.receivedymessage.sent: mensajes entrantes y salientes.conversation.assigned: se asigna una conversación a alguien del equipo.conversation.handoff: la IA pide que entre un humano.appointment.booked: se agenda una cita.quote.answered: un cliente acepta o rechaza una cotización.
Qué llega a tu servidor
Un POST con este cuerpo:
{
"id": "whd_a1b2c3",
"type": "lead.created",
"createdAt": "2026-08-24T15:04:05.000Z",
"organizationId": "org_x1y2",
"data": { "contactId": "ct_...", "name": "Ana Pérez", "phone": "573001112233" }
}Verifica la firma antes de confiar
Cada entrega va firmada con el secreto que te mostramos al crear el webhook (solo se muestra una vez). Sin verificar la firma, cualquiera que sepa tu URL puede inventarse eventos.
const crypto = require('node:crypto')
function esValido(cuerpoCrudo, cabeceras, secreto) {
const ts = Number(cabeceras['x-bongga-timestamp'])
// Rechaza lo viejo: sin esto, una entrega capturada se puede repetir siempre.
if (!ts || Math.abs(Date.now() / 1000 - ts) > 300) return false
const esperada = 'sha256=' + crypto
.createHmac('sha256', secreto)
.update(`${ts}.${cuerpoCrudo}`)
.digest('hex')
const a = Buffer.from(cabeceras['x-bongga-signature'] ?? '')
const b = Buffer.from(esperada)
return a.length === b.length && crypto.timingSafeEqual(a, b)
}Firma el cuerpo crudo, tal como llegó. Si lo parseas y lo vuelves a serializar, el texto cambia y la firma no coincide.
Reintentos y duplicados
Si tu servidor no responde con un código 2xx, reintentamos hasta seis veces (al minuto, a los 5 minutos, 30 minutos, 2 horas y 6 horas). Un error 4xx no se reintenta, porque significa que el problema no se va a arreglar solo; un 429 o un 408 sí.
Puede llegarte la misma entrega dos veces (por ejemplo si tu servidor respondió tarde pero bien). Usa el campo id, que es el mismo en todos los reintentos, para ignorar lo que ya procesaste.
Si tu servidor falla 20 veces seguidas, apagamos el webhook y te avisamos, para no seguir golpeando un destino roto. Lo reactivas desde el panel cuando lo arregles.
Probar sin esperar
Cada webhook tiene un botón de envío de prueba que manda un lead.created de mentira con data.test: true. Aparece en el historial de entregas como cualquier otra, pero no cuenta para el apagado automático.