BonggaBongga bongga← Inicio

Centro de ayuda

Primeros pasos

Bandeja de entradaAgentes de IA

Ventas

Embudo de ventasCampañas de WhatsAppAgenda y disponibilidadCampos personalizados y puntaje de leadsFormularios de capturaCotizaciones

Automatización

Flujos de automatizaciónConector de datos del negocio en vivoWebhooks: que Bongga le avise a tu sistemaAPI: crear y consultar leads desde tu sistemaAPI pública: enviar mensajes desde tu sistema

Reportes

Dashboard y métricas

Tu equipo

Roles y permisos de tu equipo

Operación

Directorio

Configuración

Tu marca y tus sedes

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.received y message.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.