La petición
Cada entrega es unPOST HTTPS con cuerpo JSON y estas cabeceras:
Cuerpo
El cuerpo es fino a propósito: dice qué cambió, no cómo. Lee el recurso
actual por la API REST con tus propias credenciales — así además ves el
último estado y no el que había al publicar.
Cómo se calcula la firma
secretes el valorwhsec_…devuelto una vez por create o rotate-secret.tes la hora Unix (segundos) en que el worker firmó la petición.- El cuerpo crudo es la secuencia exacta de bytes enviada; cualquier cambio de espacios u orden de claves invalida el digest.
Reglas de verificación
1
Lee el cuerpo crudo
Captura el cuerpo antes de que un middleware JSON lo parsee.
Reserializar el objeto parseado cambia los bytes.
2
Parsea la cabecera
Espera exactamente
t=<dígitos>,v1=<64 hex>. Rechaza cualquier otra cosa.3
Comprueba la marca de tiempo
Rechaza cuando
|ahora - t| > 300 segundos. Esto acota el replay de una
petición capturada; mantén el reloj sincronizado (NTP).4
Compara en tiempo constante
Recalcula el HMAC y compáralo con una función timing-safe.
5
Deduplica y confirma
Reintentos y replays reutilizan
id. Registra los ids procesados,
responde 2xx en menos de 10 segundos y haz el trabajo real de forma
asíncrona.Implementaciones de referencia
- Node.js
- Python
Node.js
verifyOutboundWebhookSignature en
backend/horizon-api/lib/webhook/outbound/webhook-signature.ts, que es lo
que también usa el sink de pruebas integrado.
Respuesta
Detalles en Reintentos y fallos.