Administrar webhooks por API
CRUD de webhooks con API key: /api/v1/contribuyente/webhooks para registrar la URL, elegir eventos, rotar el secreto y consultar las entregas sin entrar al panel.
Una integración puede registrar su propia URL de webhooks con la API key, sin pasar por el panel. Los endpoints administran los webhooks descritos en la referencia de webhooks: mismos eventos, misma firma y mismos reintentos.
Autenticación y alcance
Authorization: Bearer {api-key} — requerido
La API key determina el contribuyente y el ambiente. Los endpoints no aceptan RUC, ID de contribuyente ni ambiente en el path, query o body: una clave sk_sandbox_ sólo ve y modifica webhooks de Sandbox, una sk_test_ los de pruebas con SIFEN y una sk_live_ los de producción. Un webhook de otro ambiente responde 404, igual que uno inexistente.
Se aplican las mismas reglas que en el panel:
- La URL debe ser HTTPS, apuntar a una dirección pública y tener hasta 2048 caracteres, sin credenciales ni fragmentos. No se siguen redirects.
- Hasta cinco webhooks activos por contribuyente y ambiente.
- No puede haber dos webhooks activos con la misma URL en el mismo ambiente.
- El ambiente de un webhook no cambia.
Los endpoints del panel siguen funcionando igual. Los webhooks creados por API aparecen en Webhooks del panel y viceversa.
Endpoints
| Método y ruta | Qué hace |
|---|---|
GET /api/v1/contribuyente/webhooks | Lista los webhooks del ambiente de la clave |
POST /api/v1/contribuyente/webhooks | Crea un webhook y devuelve su secreto |
GET /api/v1/contribuyente/webhooks/{webhookId} | Consulta un webhook |
PUT /api/v1/contribuyente/webhooks/{webhookId} | Actualiza URL, eventos y estado |
DELETE /api/v1/contribuyente/webhooks/{webhookId} | Elimina el webhook |
POST /api/v1/contribuyente/webhooks/{webhookId}/rotar | Genera un secreto nuevo |
GET /api/v1/contribuyente/webhooks/{webhookId}/entregas | Lista las entregas del webhook |
Las respuestas son el objeto directamente, sin envelope.
Registrar un webhook
curl -X POST https://api.sifende.com.py/api/v1/contribuyente/webhooks \
-H "Authorization: Bearer $SIFENDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://erp.ejemplo.com.py/sifende/webhook",
"eventos": ["documento.aprobado", "documento.rechazado"]
}'Status: 201 Created, con Location hacia la consulta del webhook.
{
"endpoint": {
"id": 42,
"url": "https://erp.ejemplo.com.py/sifende/webhook",
"ambiente": "PROD",
"eventos": ["documento.aprobado", "documento.rechazado"],
"activo": true,
"fechaCreacion": "2026-10-20T14:03:11Z",
"fechaEdicion": "2026-10-20T14:03:11Z",
"fechaRotacionSecreto": "2026-10-20T14:03:11Z"
},
"secreto": "whsec_8Kq2m5N0vXrT1bYc3LdWz9AeJfHpU4sG"
}El secreto se devuelve sólo al crear y al rotar. Ni el listado ni la consulta lo incluyen. Guardalo en un gestor de secretos antes de seguir: lo necesitás para verificar la firma de cada notificación.
Campos del body
| Campo | Tipo | Descripción |
|---|---|---|
url | string | URL HTTPS que recibe los eventos |
eventos | string[] | Uno o más de documento.aprobado, documento.rechazado, documento.cancelado y lote.procesado; no puede ir vacío |
Campos del webhook
| Campo | Tipo | Descripción |
|---|---|---|
id | integer | Identificador del webhook |
url | string | URL de entrega |
ambiente | string | DEV, PROD o SANDBOX; el de la API key |
eventos | string[] | Eventos suscritos |
activo | boolean | false si está pausado |
fechaCreacion, fechaEdicion | string (RFC 3339) | Alta y última modificación |
fechaRotacionSecreto | string (RFC 3339) | Último cambio del secreto |
Listar y consultar
curl https://api.sifende.com.py/api/v1/contribuyente/webhooks \
-H "Authorization: Bearer $SIFENDE_API_KEY"Devuelve un arreglo con los webhooks del ambiente de la clave, los más recientes primero. Si tu integración se reinicia o no recibió la respuesta de la creación, usalo para saber si la URL ya quedó registrada.
GET /api/v1/contribuyente/webhooks/{webhookId} devuelve un único webhook con la misma forma, sin envolverlo.
Actualizar
PUT reemplaza la URL, los eventos y el estado; enviá los tres campos.
curl -X PUT https://api.sifende.com.py/api/v1/contribuyente/webhooks/42 \
-H "Authorization: Bearer $SIFENDE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://erp.ejemplo.com.py/sifende/webhook",
"eventos": ["documento.aprobado", "documento.rechazado", "documento.cancelado"],
"activo": true
}'Responde 200 OK con el webhook actualizado. El secreto no cambia.
activo: falsepausa el webhook y cancela sus entregas pendientes.- Reactivar un webhook pausado cuenta contra el límite de cinco activos del ambiente.
- Cambiar la URL o los eventos también aplica a las entregas pendientes.
Eliminar
curl -X DELETE https://api.sifende.com.py/api/v1/contribuyente/webhooks/42 \
-H "Authorization: Bearer $SIFENDE_API_KEY"Responde 204 No Content. Cancela las entregas pendientes y libera un lugar del límite. No se puede deshacer.
Rotar el secreto
curl -X POST https://api.sifende.com.py/api/v1/contribuyente/webhooks/42/rotar \
-H "Authorization: Bearer $SIFENDE_API_KEY"Responde 200 OK con la misma forma que la creación, incluido el secreto nuevo. Desde ese momento las notificaciones, también las pendientes, se firman con el secreto nuevo: actualizalo en tu receptor.
Consultar las entregas
curl "https://api.sifende.com.py/api/v1/contribuyente/webhooks/42/entregas?estado=FALLIDA&size=10" \
-H "Authorization: Bearer $SIFENDE_API_KEY"| Parámetro | Descripción |
|---|---|
page | Página, base 0. Por defecto 0 |
size | Tamaño de página, de 1 a 100. Por defecto 20 |
estado | PENDIENTE, ENCOLADA, ENVIANDO, REINTENTANDO, ENTREGADA, FALLIDA o CANCELADA |
tipoEvento | Un tipo de evento, por ejemplo documento.aprobado |
{
"content": [
{
"id": "6f1d2c1e-6a77-4a4a-8d56-3f5a3a2b9c10",
"eventId": "d44f9f47-380f-4f51-b5c9-4fa335711e18",
"tipoEvento": "documento.aprobado",
"endpointId": 42,
"endpointUrl": "https://erp.ejemplo.com.py/sifende/webhook",
"estado": "ENTREGADA",
"cantidadIntentos": 1,
"ultimoHttpStatus": 200,
"ultimoErrorCodigo": null,
"ultimoErrorMensaje": null,
"fechaCreacion": "2026-10-20T15:00:00Z",
"fechaUltimoIntento": "2026-10-20T15:00:01Z",
"fechaEntrega": "2026-10-20T15:00:01Z",
"fechaFallo": null
}
],
"page": 0,
"size": 20,
"totalElements": 1,
"totalPages": 1
}eventId es el valor del header X-Sifende-Event-Id que recibe tu receptor. El historial se conserva 90 días.
Reintentos y duplicados
Crear y rotar no admiten Idempotency-Key: el POST con ese header se rechaza con 400 idempotency-not-supported en lugar de ignorarse. En el resto de los endpoints el header se ignora. Para reintentar con seguridad:
- Crear: si no recibiste la respuesta, listá los webhooks. Si la URL figura, ya existe, pero no tenés su secreto: rotalo. Reintentar el
POSTcon la misma URL responde400 validation-errorporque ya hay un webhook activo con ella. - Rotar: cada llamada genera un secreto distinto. Si no recibiste la respuesta, rotá otra vez y quedate con el último.
- Actualizar y eliminar: se pueden repetir; eliminar un webhook ya eliminado responde
404.
Errores
| Status | Cuándo |
|---|---|
400 | URL que no es HTTPS o no es pública, eventos vacío o con un valor nulo o desconocido, URL repetida, límite de cinco webhooks activos, page o size fuera de rango |
401 | API key ausente, inválida o revocada |
403 | El plan del contribuyente no incluye la API de integración: plan-operation-not-allowed |
404 | webhook-not-found: el webhook no existe, fue eliminado o pertenece a otro ambiente |
500 | Error interno |
Los errores usan application/problem+json, como el resto de la API. Ver Errores.
Webhooks
Webhooks de Sifende: eventos de documentos y lotes, verificación de la firma HMAC, reintentos de entrega e historial para integrar tu sistema.
Enumeraciones SIFEN (Endpoint)
GET /api/v1/public/enums — endpoint público que lista en tiempo real todos los valores válidos de las enumeraciones SIFEN, con su name, label y código.