Webhooks
Endpoints, el libro de eventos, inspección de entregas y reintento manual.
Base: https://api.facturia.cl/v1. Todos los endpoints de este capítulo se autentican con Authorization: Bearer salvo que se diga lo contrario, y el sobre de error es el de Errores.
| Método | Ruta | Qué hace |
|---|---|---|
GET | /webhook_endpoints | Lista los endpoints de webhook |
POST | /webhook_endpoints | Registra un endpoint de webhook |
GET | /webhook_endpoints/{webhook_endpoint_id} | Devuelve un endpoint de webhook |
PATCH | /webhook_endpoints/{webhook_endpoint_id} | Actualiza un endpoint de webhook |
DELETE | /webhook_endpoints/{webhook_endpoint_id} | Elimina un endpoint de webhook |
POST | /webhook_endpoints/{webhook_endpoint_id}/ping | Envía un evento sintético para verificar la conexión |
POST | /webhook_endpoints/{webhook_endpoint_id}/rotate_secret | Rota el secreto de firma |
GET | /webhook_endpoints/{webhook_endpoint_id}/deliveries | Inspecciona los intentos de entrega |
POST | /webhook_endpoints/{webhook_endpoint_id}/deliveries/{delivery_id}/retry | Reenvía un evento |
GET | /events | Consulta el libro de eventos (retención de 12 meses) |
GET | /events/{event_id} | Devuelve un evento |
GET /webhook_endpoints
Lista los endpoints de webhook
Los endpoints de webhook configurados para la cuenta, con sus enabled_events y la salud de entrega; los secretos nunca se incluyen.
curl -sS https://api.facturia.cl/v1/webhook_endpoints \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
limit | query | — | integer | |
cursor | query | — | string | Cursor opaco tomado del next_cursor de una respuesta anterior. |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | Una lista de endpoints. | lista de WebhookEndpoint |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
POST /webhook_endpoints
Registra un endpoint de webhook
El secret se devuelve una sola vez, al crearlo, y nunca más.
curl -sS -X POST https://api.facturia.cl/v1/webhook_endpoints \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"url":"https://api.miempresa.cl/hooks/facturia"}'Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
Idempotency-Key | header | — | string | Llave que genera el cliente, única por operación lógica, retenida 24 h y con alcance (cuenta, empresa, endpoint). Un replay devuelve la respuesta original con Facturia-Idempotent-Replay: true. Misma llave y cuerpo distinto → 409. |
Cuerpo
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
url | string | sí | |
description | string | — | |
enabled_events | string[] | — | Tipos de evento, o ["*"] para todo, incluidos los tipos futuros. Por defecto: ["*"]. |
empresas | Rut[] | — | Restringe las entregas a estas empresas. Por defecto, todas las que la llave puede ver. |
| Respuestas |
| Código | Significado | Cuerpo |
|---|---|---|
201 | El endpoint creado, con su secreto de firma. | WebhookEndpointWithSecret |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
GET /webhook_endpoints/{webhook_endpoint_id}
Devuelve un endpoint de webhook
La configuración y la salud de entrega de un endpoint de webhook, sin su secreto de firma.
curl -sS https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | El endpoint. | WebhookEndpoint |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
PATCH /webhook_endpoints/{webhook_endpoint_id}
Actualiza un endpoint de webhook
Actualiza url, enabled_events o description. El secreto de firma no cambia — usa rotate_secret para eso.
curl -sS -X PATCH https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W \
-H "Authorization: Bearer $FACTURIA_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://api.miempresa.cl/hooks/facturia","description":"…"}'Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string |
Cuerpo
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
url | string | — | |
description | string | — | |
enabled_events | string[] | — | |
empresas | Rut[] | — | |
status | enabled · disabled | — | |
| Respuestas |
| Código | Significado | Cuerpo |
|---|---|---|
200 | El endpoint actualizado. | WebhookEndpoint |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
DELETE /webhook_endpoints/{webhook_endpoint_id}
Elimina un endpoint de webhook
Elimina el endpoint y destruye su secreto de firma (el actual y el anterior) en la bóveda; se eliminan juntos para que no quede un secreto huérfano después de borrar la fila.
curl -sS -X DELETE https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
204 | Eliminado. | — |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
POST /webhook_endpoints/{webhook_endpoint_id}/ping
Envía un evento sintético para verificar la conexión
Envía un evento ping sintético a la URL actual del endpoint, para que quien integra pueda verificar la validación de firma antes de depender de un evento real.
curl -sS -X POST https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W/ping \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
202 | El intento de entrega. | WebhookDelivery |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
POST /webhook_endpoints/{webhook_endpoint_id}/rotate_secret
Rota el secreto de firma
El secreto anterior sigue firmando 24 horas, así que puedes desplegar sin corte.
curl -sS -X POST https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W/rotate_secret \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | El endpoint con su secreto nuevo. | WebhookEndpointWithSecret |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
GET /webhook_endpoints/{webhook_endpoint_id}/deliveries
Inspecciona los intentos de entrega
Los intentos de entrega de este endpoint, del más nuevo al más antiguo, con el estado de respuesta de cada uno y si se va a reintentar.
curl -sS https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W/deliveries \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string | |
limit | query | — | integer | |
cursor | query | — | string | Cursor opaco tomado del next_cursor de una respuesta anterior. |
status | query | — | pending · succeeded · failed | |
event_id | query | — | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | Una lista de entregas. | lista de WebhookDelivery |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
POST /webhook_endpoints/{webhook_endpoint_id}/deliveries/{delivery_id}/retry
Reenvía un evento
Limitado a 20/min por cuenta, no por credencial (ticket #152): una llave filtrada convertiría esto en un amplificador gratis de peticiones salientes desde nuestras propias IP. Hay además un techo duro de 20 intentos de entrega por par (endpoint, evento), que se responde como 409 too_many_replays.
curl -sS -X POST https://api.facturia.cl/v1/webhook_endpoints/whe_01K2RF5N8Q2W/deliveries/whd_01K2RG1P4M7X01/retry \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
webhook_endpoint_id | path | sí | string | |
delivery_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
202 | El nuevo intento de entrega. | WebhookDelivery |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
404 | No existe ese objeto bajo esta llave. | ErrorResponse |
409 | Conflicto de estado: reutilización de idempotencia, external_id duplicado o artefacto no listo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
GET /events
Consulta el libro de eventos (retención de 12 meses)
La retención es de 12 meses — a propósito más larga que un libro de webhooks típico, para que un ciclo tributario completo de F29 siga siendo reproducible. La entrega de webhooks es al-menos-una-vez y sin orden garantizado; deduplica por id.
Polling en vez de webhooks. Si no puedes exponer un endpoint HTTPS —un agente personal, un notebook, cualquier cosa detrás de NAT—, este endpoint es el sustituto soportado, y ?after= es el parámetro que lo hace funcionar:
GET /v1/events?after=evt_01K2RG1P4M7X&limit=100
after pagina HACIA ADELANTE: del más antiguo al más nuevo, estrictamente posteriores al id que nombras, con next_cursor alejándose de él. El loop es after = next_cursor ?? after, procesando data en orden; nunca relee una fila y no necesita un conjunto de ids ya vistos. after acepta tanto un id evt_… (el último evento que procesaste) como un valor cur_… de next_cursor, así que tu checkpoint guardado y el token que te entregamos son intercambiables. Cuando has_more es false, next_cursor es null: guarda el id del último evento que procesaste y manda ese la próxima vez.
cursor es la dirección contraria y es el default: del más nuevo al más antiguo, «más viejo que esto», que es lo que quiere un panel leyendo un libro. Mandar los dos es 400 en vez de una precedencia silenciosa: nombran posiciones en órdenes opuestos, y honrar cualquiera de los dos saltaría filas para la mitad de quienes llaman sin decirles nada.
curl -sS https://api.facturia.cl/v1/events \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
limit | query | — | integer | |
cursor | query | — | string | Cursor opaco tomado del next_cursor de una respuesta anterior. |
after | query | — | string | Checkpoint hacia adelante: devuelve los eventos estrictamente POSTERIORES a este, del más antiguo al más nuevo. Un id evt_… o un valor cur_… de una página anterior hacia adelante. Mutuamente excluyente con cursor. |
type | query | — | string | |
empresa_rut | query | — | Rut | |
created_at[gte] | query | — | string | |
created_at[lte] | query | — | string | Cota superior, inclusiva. Se honra desde que el endpoint existe y no estaba declarada hasta ahora, lo que hacía que «dame un mes cerrado del libro» pareciera imposible desde el contrato. |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | Una lista de eventos. | lista de Event |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |
GET /events/{event_id}
Devuelve un evento
Un evento del registro propio de la cuenta — el mismo objeto que lleva una entrega de webhook — para quien concilia por id en vez de por suscripción.
curl -sS https://api.facturia.cl/v1/events/evt_01K2RG1P4M7X \
-H "Authorization: Bearer $FACTURIA_KEY"Parámetros
| Parámetro | En | Requerido | Tipo | Notas |
|---|---|---|---|---|
event_id | path | sí | string |
Respuestas
| Código | Significado | Cuerpo |
|---|---|---|
200 | El evento. | Event |
401 | Llave ausente, mal formada o revocada. | ErrorResponse |
403 | Llave válida pero sin permiso: scope, lista blanca de empresas o modo. | ErrorResponse |
429 | Demasiadas solicitudes. | ErrorResponse |
default | Un error no enumerado aparte para esta operación, en el mismo sobre §5.5 que cualquier otro rechazo. Ramifica por error.code, nunca solo por el estado HTTP ni por error.message — un código que esta operación aún no se ha visto lanzar sigue siendo más seguro para decidir que un texto pensado para una persona. | ErrorResponse |