Guías por flujo
Forecast, watch y webhooks
Suscribirse, recibir la alerta, verificar la firma HMAC, manejar retries y DLQ.
Fuente del diagrama (mermaid)
flowchart LR
W[POST /v1/watch/subscriptions] --> A[Alerta]
A --> E[Evento de webhook]
E --> D1[Intento 1]
D1 -- 2xx --> OK[delivered]
D1 -- 5xx --> D2[retry_scheduled]
D2 --> D3[Intento 3]
D3 -- falla --> DLQ[dlq]
DLQ --> RP[POST .../replay]
RP --> OK
Verificar la firma
Cada entrega trae estos headers:
| Header | Qué es |
|---|---|
x-ucotron-event-id | El id del evento |
x-ucotron-signature-timestamp | Cuándo se firmó |
x-ucotron-payload-digest | SHA-256 del payload canónico |
x-ucotron-signature | HMAC-SHA256 de eventId.timestamp.digest |
Verificá en este orden: id, ventana de tiempo (300 s), duplicado, digest,
firma. Comparar la firma con === en vez de en tiempo constante convierte tu
receptor en un oráculo.
Retries y DLQ
Tres intentos como máximo, con backoff determinista (1 s, 5 s, 15 s). Sólo se reintentan 408, 429, 500, 502, 503 y 504: un 400 no se arregla reintentando.
curl -sS "$SBOX/v1/webhooks/deliveries?limit=250" -H "authorization: Bearer $TOKEN"
curl -sS "$SBOX/v1/webhooks/deliveries/<deliveryId>/replay" -X POST \
-H "authorization: Bearer $TOKEN" -H "idempotency-key: replay-demo-1"El sandbox siembra una entrega en cada estado final —delivered,
retry_scheduled y dlq— a propósito. Si sólo pudieras ejercitar el 200,
escribirías el manejo de reintentos mirando esta página.
Lo que se rompe
- Sólo se reintenta lo que quedó en DLQ. Reintentar algo ya entregado
duplicaría el evento del lado del receptor:
409 delivery_not_replayable. - Un endpoint que apunta a una IP privada o al metadata del cloud se rechaza con
ssrf_blockedantes de cualquier intento. - El mismo evento entregado dos veces se detecta como
replay_detected. Tu receptor tiene que ser idempotente igual: la red no promete entrega única.