Saltar al contenido principal
Version: 1.0.0

Webhooks

Los webhooks proporcionan notificaciones HTTP push en tiempo real cuando ocurren eventos de análisis, eliminando la necesidad de polling. Cuando un análisis se completa, falla o desencadena otros eventos, la plataforma Cert-IX envía una solicitud HTTP POST a su URL registrada con el payload del evento.

¿Por qué usar webhooks?

  • Notificaciones instantáneas — Sin retardo de polling
  • Reducción de llamadas API — Sin cuota consumida para verificaciones de estado
  • Arquitectura basada en eventos — Active automáticamente gates CI/CD, notificaciones, creación de tickets
  • Entrega confiable — Reintentos automáticos con backoff exponencial

Registrar un webhook

Endpoint

POST /api/v1/webhooks

Alcance requerido: webhooks:create

Solicitud

curl -X POST https://api.cert-ix.com/scan-api/api/v1/webhooks \
-H "X-API-Key: $CERTIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Notificaciones CI/CD",
"url": "https://su-servidor.example.com/webhooks/certix",
"events": ["scan.completed", "scan.failed"]
}'

Parámetros de la solicitud

CampoTipoRequeridoDescripción
namestringNombre legible del webhook (máx. 255 caracteres)
urlstringEndpoint HTTPS para recibir eventos (máx. 2048 caracteres)
eventsstring[]NoTipos de eventos a suscribir (predeterminado: scan.completed, scan.failed)

Respuesta (201 Created)

{
"success": true,
"data": {
"id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"name": "Notificaciones CI/CD",
"url": "https://su-servidor.example.com/webhooks/certix",
"secret": "whsec_a8b2f1d92ffb23344a943df2b6a001fb1028d002e3f4a5b6c7d8",
"events": ["scan.completed", "scan.failed"],
"isActive": true,
"isHealthy": true,
"createdAt": "2026-03-06T10:00:00Z"
}
}
Almacene el secreto

El campo secret se devuelve solo al momento de la creación. Almacénelo de forma segura — lo necesitará para verificar las firmas de webhooks.

Eventos webhook

EventoDisparadorDescripción
scan.completedEl análisis termina exitosamenteLos resultados están listos para ser obtenidos
scan.failedEl análisis encuentra un error fatalDetalles del error incluidos en el payload
scan.startedEl análisis comienza la ejecuciónTransición de queued a running
scan.cancelledEl análisis es canceladoResultados parciales pueden estar disponibles

Formato del payload

Encabezados

Content-Type: application/json
X-Webhook-Signature: sha256=a1b2c3d4e5f6...
X-Webhook-Event: scan.completed
X-Webhook-Delivery: del-uuid-aqui
X-Webhook-Timestamp: 2026-03-06T10:02:15Z

Cuerpo

{
"event": "scan.completed",
"timestamp": "2026-03-06T10:02:15Z",
"tenantId": "7b5b0610-2947-412f-a869-4683da321fcf",
"data": {
"scanId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"scanType": "nmap",
"name": "Auditoría de red semanal",
"target": "example.com",
"status": "completed",
"progress": 100,
"resultCount": 12,
"durationMs": 135000
}
}

Verificación de firma

Cada entrega de webhook está firmada con su secreto de webhook usando HMAC-SHA256. Verifique siempre las firmas para asegurarse de que la solicitud proviene de Cert-IX y no ha sido alterada.

Algoritmo de verificación

  1. Extraer el encabezado X-Webhook-Signature
  2. Obtener el cuerpo crudo de la solicitud (antes de cualquier análisis JSON)
  3. Calcular HMAC-SHA256(secreto, cuerpo) y codificar en hexadecimal
  4. Comparar con la firma del encabezado (usar comparación en tiempo constante)

Ejemplo Python

import hmac
import hashlib

def verificar_webhook(cuerpo_solicitud: bytes, encabezado_firma: str, secreto: str) -> bool:
"""Verificar la firma del webhook de Cert-IX."""
if not encabezado_firma.startswith("sha256="):
return False
recibido = encabezado_firma[7:]
esperado = hmac.new(
secreto.encode("utf-8"),
cuerpo_solicitud,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(recibido, esperado)

Ejemplo Go

func verificarWebhook(body []byte, signatureHeader, secret string) bool {
if !strings.HasPrefix(signatureHeader, "sha256=") {
return false
}
recibido := signatureHeader[7:]
mac := hmac.New(sha256.New, []byte(secret))
mac.Write(body)
esperado := hex.EncodeToString(mac.Sum(nil))
return hmac.Equal([]byte(recibido), []byte(esperado))
}

Ejemplo Node.js

const crypto = require("crypto");

function verificarWebhook(body, signatureHeader, secret) {
if (!signatureHeader.startsWith("sha256=")) return false;
const recibido = signatureHeader.slice(7);
const esperado = crypto.createHmac("sha256", secret).update(body).digest("hex");
return crypto.timingSafeEqual(Buffer.from(recibido), Buffer.from(esperado));
}
Seguridad

Use siempre funciones de comparación en tiempo constante para prevenir ataques de temporización.

Gestionar webhooks

OperaciónEndpointAlcance
ListarGET /api/v1/webhookswebhooks:read
ObtenerGET /api/v1/webhooks/:webhookIdwebhooks:read
ActualizarPATCH /api/v1/webhooks/:webhookIdwebhooks:update
EliminarDELETE /api/v1/webhooks/:webhookIdwebhooks:delete
ProbarPOST /api/v1/webhooks/:webhookId/testwebhooks:create
Registros de entregaGET /api/v1/webhooks/:webhookId/deliverieswebhooks:read

Lógica de reintentos

Las entregas fallidas se reintentan automáticamente con backoff exponencial:

IntentoRetrasoTiempo total transcurrido
1Inmediato0
260 segundos1 minuto
3120 segundos3 minutos
4 (final)240 segundos7 minutos

Una entrega se considera fallida si:

  • Su endpoint devuelve un código HTTP no 2xx
  • La conexión expira (timeout de 30 segundos)
  • La resolución DNS falla
  • El handshake TLS falla

Monitoreo de salud

La plataforma rastrea la salud de los webhooks basada en el éxito de las entregas:

CampoDescripción
isHealthytrue si las entregas recientes fueron exitosas
consecutiveFailuresNúmero de fallos consecutivos
lastTriggeredAtMarca de tiempo del último intento
lastStatusCodeCódigo HTTP de la última entrega

Desactivación automática

Si un webhook acumula 10 fallos consecutivos, se desactiva automáticamente (isActive: false). Para reactivarlo:

  1. Corrija el problema con su endpoint
  2. Reactive vía PATCH con {"isActive": true}
  3. Envíe un evento de prueba para verificar

Mejores prácticas

  • Use solo HTTPS — Las URL de webhook deben usar https://
  • Verifique las firmas en cada solicitud
  • Devuelva 200 rápidamente — Procese los eventos de forma asíncrona
  • Implemente idempotencia — El mismo evento puede entregarse más de una vez durante reintentos
  • Valide el tipo de evento — Solo procese los eventos esperados

Próximos pasos: