Skip to main content

Webhooks

En lugar de hacer polling a GET /api/v1/invoices/{id}/status, registra una URL y CUCU te notifica en tiempo real cada vez que ocurre un evento relevante: una factura se valida o rechaza, se abre o cierra una contingencia, o cambia el estado de la conexión con el SIAT.

Registrar un endpoint

POST /api/v1/webhooks/endpoints
ParametroUbicacionTipoReqDescripcion
X-API-KeyHeaderstringSiTu API Key
urlBodystringSiURL https:// que recibirá las entregas
eventsBodyarray<string>SiEventos a suscribir. Acepta *, namespace.* (ej. contingency.*) o el tipo exacto
descriptionBodystringNoNota interna para identificar el endpoint
curl -X POST https://sandbox.cucu.bo/api/v1/webhooks/endpoints \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "url": "https://tuservidor.com/webhooks/cucu",
    "events": ["invoice.validated", "invoice.rejected", "contingency.*"],
    "description": "Sincronizacion con ERP"
  }'
Respuesta (201):
{
  "success": true,
  "data": {
    "id": "wh_ep_a1b2c3d4",
    "url": "https://tuservidor.com/webhooks/cucu",
    "events": ["invoice.validated", "invoice.rejected", "contingency.*"],
    "secret": "whsec_...",
    "active": true,
    "createdAt": "2026-07-01T10:00:00"
  }
}
El secret solo se muestra completo en este momento (y al rotarlo). Guárdalo de forma segura — lo necesitas para verificar la firma de cada entrega.

Gestionar endpoints

AccionEndpoint
Listar endpointsGET /api/v1/webhooks/endpoints
Ver un endpointGET /api/v1/webhooks/endpoints/{id}
Actualizar (url, events, activo)PUT /api/v1/webhooks/endpoints/{id}
EliminarDELETE /api/v1/webhooks/endpoints/{id}
Rotar secretoPOST /api/v1/webhooks/endpoints/{id}/rotate-secret
Todas requieren el header X-API-Key.
Cada tenant puede registrar un máximo de 20 endpoints. Si necesitas más, contacta a soporte.

Catálogo de eventos

EventoDescripción
invoice.*Un evento por cada cambio de estado de una factura (validada, rechazada, anulada), reflejando los mismos estados documentados en el ciclo de vida de la factura
contingency.openedSe activó contingencia offline en un punto de venta
contingency.closedLa contingencia finalizó y las facturas se sincronizaron con el SIAT
contingency.package_rejectedEl SIAT rechazó el paquete de facturas enviado al reconectar
siat.connection_lostCUCU detectó que el SIAT dejó de responder
siat.connection_restoredLa conexión con el SIAT se restableció
siat.token_expiringEl token de sesión SIAT está por expirar
certificate.expiringEl certificado digital del tenant está por vencer
cufd.renewal_failedFalló la renovación automática del CUFD
cuis.renewal_failedFalló la renovación automática del CUIS
Al registrar un endpoint puedes suscribirte a * (todos los eventos), a un namespace completo (contingency.*, siat.*) o a un tipo exacto. La suscripción se valida contra este mismo catálogo, así que nunca puedes suscribirte a un evento inexistente.

Seguridad

  • HTTPS obligatorio. Solo se aceptan URLs https://.
  • Anti-SSRF. Al registrar o rotar un endpoint, CUCU resuelve el host y rechaza direcciones en rangos privados o de loopback.
  • Firma en cada entrega. Todas las entregas se firman con HMAC-SHA256 siguiendo el estándar Standard Webhooks, para que la verificación sea sencilla y predecible en cualquier lenguaje.

Headers en cada entrega

HeaderDescripción
webhook-idUUID único de esta entrega. Úsalo para deduplicar en tu receptor.
webhook-timestampUNIX timestamp del momento del envío.
webhook-signatureFirma de autenticidad. Formato: v1,<base64(HMAC-SHA256)>.
webhook-eventTipo de evento entregado (ej. invoice.validated).

Verificación de firma

mensaje_a_firmar = "{webhook-id}.{webhook-timestamp}.{raw_body_bytes}"
firma_esperada   = base64( HMAC-SHA256(mensaje_a_firmar, tu_secret) )
Compara firma_esperada con el valor de webhook-signature (después del prefijo v1,) usando una comparación de tiempo constante.

Payload de ejemplo

{
  "type": "invoice.validated",
  "occurredAt": "2026-07-01T10:00:05",
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "cuf": "2872F7294502332E637FABFBC3654EA82202AD48E0969F14EBEB8AF74",
    "invoiceNumber": 42,
    "state": "VALIDATED",
    "amountTotal": 500.00
  }
}

Política de reintentos

Tu endpoint debe responder 2xx dentro del timeout configurado para que la entrega se considere exitosa. Si no responde o responde con error, CUCU reintenta con backoff exponencial hasta 8 intentos. Un dispatcher interno procesa la cola de entregas pendientes cada 10 segundos.
Diseña tu receptor para ser idempotente usando webhook-id — el mismo evento puede llegar más de una vez ante un reintento de red.

Auditoría y reenvío manual

AccionEndpoint
Listar entregas de un endpointGET /api/v1/webhooks/endpoints/{id}/deliveries
Forzar el reenvío de una entregaPOST /api/v1/webhooks/deliveries/{deliveryId}/redeliver
Útil para debugging: revisa el historial de intentos, el código de respuesta recibido y fuerza un reenvío manual sin esperar al backoff automático.