Webhooks
Configuración, eventos, firma HMAC, reintentos e historial de webhooks salientes de Sifende.
Los webhooks notifican cambios de documentos y lotes. Se configuran por contribuyente desde Webhooks en el panel. Mantené las consultas de estado como respaldo operativo: la entrega es at-least-once y un receptor debe tolerar duplicados.
Eventos
| Tipo | Cuándo se emite |
|---|---|
documento.aprobado | SIFEN aprueba un documento. |
documento.rechazado | SIFEN rechaza un documento. |
documento.cancelado | SIFEN acepta la cancelación de un documento. |
lote.procesado | Todos los documentos de un lote alcanzan un resultado final. |
Cada endpoint elige uno o más eventos. Un contribuyente puede tener hasta cinco endpoints activos. La URL debe usar HTTPS; no se siguen redirects.
Sobre del evento
Todos los payloads usan la versión 1:
{
"id": "d44f9f47-380f-4f51-b5c9-4fa335711e18",
"tipo": "documento.aprobado",
"version": "1",
"ocurridoEn": "2026-08-13T15:00:00Z",
"contribuyenteId": 42,
"data": {
"documentoId": "41de310e-1374-4593-bce4-7c27638ee99a",
"cdc": "01800123451001001000000122026042710000000006",
"estado": "APROBADO",
"loteId": 815,
"protocoloAutorizacion": "123456789",
"resultados": []
}
}documento.aprobado y documento.rechazado incluyen documentoId, cdc, estado, loteId, protocoloAutorizacion y resultados. documento.cancelado incluye además eventoSifenId, motivo, codigoRespuesta y mensajeRespuesta. lote.procesado incluye los conteos finales y la lista de documentos del lote.
Headers
| Header | Contenido |
|---|---|
X-Sifende-Event-Id | UUID estable del evento; usalo para deduplicar. |
X-Sifende-Event-Type | Tipo del evento. |
X-Sifende-Delivery-Id | UUID de la entrega a un endpoint. |
X-Sifende-Timestamp | Unix timestamp en segundos usado en la firma. |
X-Sifende-Signature | v1= seguido del HMAC-SHA256 en Base64. |
Verificar la firma
El secreto whsec_… se muestra sólo al crear o rotar el endpoint. Guardalo en un gestor de secretos. La firma se calcula sobre bytes, no sobre un JSON parseado o reserializado:
mensaje = eventId + "." + deliveryId + "." + timestamp + "." + rawBody
firma = "v1=" + Base64(HMAC-SHA256(secret, mensaje))Ejemplo en Node.js:
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verificarWebhook({ rawBody, headers, secret }) {
const eventId = headers['x-sifende-event-id'];
const deliveryId = headers['x-sifende-delivery-id'];
const timestamp = headers['x-sifende-timestamp'];
const recibida = headers['x-sifende-signature'];
const prefijo = Buffer.from(`${eventId}.${deliveryId}.${timestamp}.`);
const mensaje = Buffer.concat([prefijo, rawBody]);
const esperada = `v1=${createHmac('sha256', secret).update(mensaje).digest('base64')}`;
return recibida.length === esperada.length && timingSafeEqual(Buffer.from(recibida), Buffer.from(esperada));
}Validá también que X-Sifende-Timestamp esté dentro de una ventana razonable y rechazá firmas fuera de esa ventana. Capturá el cuerpo crudo antes de cualquier middleware JSON.
Respuestas y reintentos
Respondé rápido con cualquier estado 2xx. Sifende clasifica los resultados así:
| Resultado | Comportamiento |
|---|---|
200–299 | Entrega completada. |
| Error de red, DNS, TLS o timeout | Se reintenta. |
408, 425, 429, 500–599 | Se reintenta con backoff. |
300–399 | Falla permanente; los redirects están bloqueados. |
Otros 400–499 | Falla permanente. |
Los reintentos pueden durar hasta 24 horas, con backoff entre 10 segundos y una hora. Una entrega aceptada por el receptor puede repetirse si el worker cae antes de guardar el 2xx; deduplicá por X-Sifende-Event-Id.
Ciclo de vida e historial
Editar la URL, las suscripciones o el secreto afecta también a las entregas pendientes. Desactivar o eliminar un endpoint cancela sus entregas no terminales. El historial muestra estado, HTTP, error e intentos durante 90 días.
La API administrativa usa una sesión JWT y rutas bajo /api/v1/contribuyentes/{contribuyenteId}/webhooks; no usa API keys de integración.