Documentación

Webhooks

Recibe eventos de la plataforma firmados y en tiempo real en tus propios endpoints HTTPS, con verificación de firma y reintentos automáticos.

Qué son los webhooks

Los webhooks te envían los eventos en el momento en que ocurren, en lugar de que tengas que consultar la API REST una y otra vez. Registra un endpoint HTTPS y CrunchJunkie enviará por POST una carga JSON firmada cada vez que se dispare un evento al que estés suscrito. Así puedes lanzar una alerta en Slack cuando baje la visibilidad, poner en marcha un flujo de trabajo cuando termine un escaneo o replicar los eventos en tu propia base de datos sin un cron propio. Cada envío va firmado (para que puedas comprobar que viene de nosotros), se reintenta automáticamente si tu endpoint no está disponible durante un rato y queda registrado. Los webhooks están disponibles en los planes Pro, Agency y Scale, y solo el propietario o un administrador del espacio de trabajo puede gestionarlos. Si el espacio de trabajo ya no tiene un plan Pro, Agency o Scale activo, no se envía nada (cada envío queda registrado como omitido), y el propietario o un administrador sigue pudiendo desactivar los endpoints o eliminarlos.

Añadir un endpoint

Abre Ajustes → Webhooks y añade la URL HTTPS de tu receptor (http:// se rechaza). Elige qué eventos debe recibir, todos o solo un subconjunto, y, si quieres, una etiqueta. Al guardar te mostramos el secreto de firma una sola vez. Tiene este aspecto: whsec_…. Cópialo ahora en tu receptor: no podemos volver a mostrarlo, solo rotarlo para generar uno nuevo. Usa el botón «Enviar prueba» para lanzar un evento de ejemplo a tu endpoint y comprobar que acepta y verifica el envío antes de depender de él.

La carga del evento

Enviamos por POST un sobre JSON con el formato de Standard Webhooks: { "id": "msg_…", "type": "signal.created", "timestamp": "2026-08-28T10:00:00.000Z", "api_version": "2026-08-01", "data": { … } } • id: un identificador único del mensaje, que también se envía en la cabecera webhook-id. Úsalo como clave de idempotencia para que un reintento nunca se procese dos veces. • type: el tipo de evento (ver más abajo). • data: el objeto completo del evento, así que rara vez necesitarás otra llamada a la API. Devuelve cualquier estado 2xx para confirmar la recepción. Cualquier otra respuesta (o un tiempo de espera superior a 15 segundos) se trata como un fallo y se reintenta.

Verificar las firmas

Tres cabeceras acompañan a cada envío: webhook-id, webhook-timestamp (segundos Unix) y webhook-signature. La firma es un HMAC-SHA256 sobre la cadena `{id}.{timestamp}.{body}`, codificado en base64 y con el prefijo v1,. Es el esquema de Standard Webhooks, así que cualquier biblioteca compatible con svix lo verifica. También puedes verificarlo a mano: import crypto from "node:crypto"; function verify(secret, headers, body) { const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64"); const signed = `${headers["webhook-id"]}.${headers["webhook-timestamp"]}.${body}`; const expected = "v1," + crypto.createHmac("sha256", key).update(signed).digest("base64"); return headers["webhook-signature"].split(" ").some(s => crypto.timingSafeEqual(Buffer.from(s), Buffer.from(expected))); } Verifica siempre contra el cuerpo SIN PROCESAR de la petición (antes de interpretar el JSON) y rechaza los envíos cuyo webhook-timestamp tenga más de cinco minutos, para evitar repeticiones.

Eventos, reintentos y desactivación automática

Tipos de evento actuales: • signal.created: se ha detectado una señal nueva (caída de visibilidad, un competidor toma la delantera, caída de la puntuación GEO, fuente muerta, multicanal, una cuenta publicitaria de Meta que ha dejado de entregar). Solo se disparan las señales realmente nuevas; un hallazgo que se mantiene cierto no te inunda de avisos. La carga incluye n con nUnit (lo que cuenta) y una confidence solo cuando una prueba estadística la calculó (confidenceKind tested; null para un hecho contado). title y detail son las palabras en inglés guardadas con la señal, tal como se guardaron; text ({ lang, title, detail }) añade las mismas palabras en el idioma del espacio de trabajo, redactadas a partir de las pruebas de la señal. La acción de webhook de una automatización envía el mismo texto junto a title y detail. • scan.completed: ha terminado un escaneo de visibilidad en IA, y data.status indica cómo: done (todas las comprobaciones guardadas), error (terminó con comprobaciones que fallaron de forma definitiva) o stopped (alguien lo detuvo, con el botón Detener o eliminando su cliente, o lo pausó el presupuesto de Managed AI). Un escaneo que continúa otro no envía ningún evento propio: el escaneo que lo sustituyó (un «Iniciar escaneo» pulsado por una persona que sustituye al primer escaneo automático o a un escaneo que no había empezado) o que tomó el relevo (un escaneo en cola que continúa uno que se impulsó y no avanzó) envía uno cuando termina, con los identificadores de todos los escaneos que continuó en data.replaced. No se envía ningún evento por un escaneo en cola cancelado antes de empezar (nunca llegó a ejecutarse), por un escaneo que termina la comprobación de escaneos atascados (sin progreso durante horas, o con una semana de antigüedad) ni por un escaneo que la programación sustituye después de llevar 6 horas ejecutándose sin terminar. Si un envío falla, lo reintentamos con retroceso exponencial: a los 5 s, y luego a los 5 min, 30 min, 2 h, 5 h y 10 h, hasta ocho intentos repartidos en más de un día. El mismo webhook-id se reutiliza en todos los reintentos. Tras muchos fallos consecutivos, el endpoint se desactiva automáticamente (el motivo aparece en Ajustes), de modo que una URL muerta para siempre deja de generar tráfico; vuelve a activarlo cuando esté arreglado. Los eventos que seguían en cola para un endpoint cuando se desactiva se cierran como omitidos y no se reenvían al reactivarlo. Puedes rotar el secreto de firma en cualquier momento desde la misma pantalla: el secreto anterior deja de funcionar de inmediato, así que actualiza tu receptor a la vez.