API: Folios (CAF)
Carga, inventario y eliminación de los archivos CAF que autorizan tus rangos de folios por tipo de DTE, con alerta de folios bajos
El recurso /caf administra los CAF (Código de Autorización de Folios) de tu organización: el XML que el SII te entrega con un rango de folios autorizado por tipo de DTE. Notta consume folios secuencialmente de cada CAF al emitir y avisa cuando quedan pocos (low_folios).
Base URL: https://app.notta.cl/api/v1. El CAF se guarda cifrado con la misma envelope encryption de los certificados.
Autenticación: API key Bearer o sesión del dashboard
Los cinco endpoints de /caf aceptan las dos credenciales: Authorization: Bearer ntt_cert_… para consumidores externos (API, CLI, MCP) o la cookie de sesión del dashboard. Las cuatro mutaciones (POST /caf/request, POST /caf, DELETE /caf/:id y PUT /caf/auto) exigen además el scope caf:write en la key y un rol escritor en la organización: una key con solo dte:write, o un viewer, reciben 403 forbidden. Sin organización responden 412 org.required.
Endpoints
POST /caf/request
Le pide al SII un rango nuevo de folios para un tipo, sin que tengas que pasar por el timbraje electrónico del portal. Es el camino programático cuando todavía no tienes ningún CAF: Notta abre la sesión mutual-TLS con tu certificado, completa el wizard de timbraje y guarda el XML cifrado, listo para emitir.
El grant es irreversible
El SII otorga folios reales que no se devuelven ni se anulan, en cert y en producción. Pide la cantidad que vayas a usar. Hay un cooldown anti doble-grant: una segunda llamada mientras la primera sigue en vuelo responde 409 caf.request_in_flight con retry_in_seconds y no vuelve a pegarle al SII.
| Campo (JSON) | Tipo | Requerido | Descripción |
|---|---|---|---|
tipo | int | sí | Tipo de DTE a timbrar. Uno de 33, 34, 46, 52, 56, 61, 110, 112. Las boletas 39/41 tienen pipeline propio y responden 400. |
cantidad | int | no | Cuántos folios pedir (1–1000). Sin él, Notta usa el default por tipo. |
Los folios de exportación (110 y 112) se timbran por esta misma vía, y desde el 19 de agosto de 2026 también se emiten por la API: POST /dtes con tipo_dte: 110 acepta el documento. Lleva su propio cuerpo —moneda, ind_servicio y bloque aduana—; está descrito en Emitir un DTE. Tu organización necesita el tipo autorizado por el SII: sin eso la respuesta es 403.
El ambiente sale de la API key: una ntt_cert_ pide folios en maullin (cert) y una ntt_prod_ en palena. Con sesión del dashboard sale del ambiente activo de tu organización.
Respuesta 201 Created — se solicitó un rango nuevo:
Si ya tienes folios vigentes para ese tipo, la respuesta es 200 OK con requested: false y reason: "no_cafs_missing": no se pidió nada.
Errores posibles:
| Código | HTTP | Qué hacer |
|---|---|---|
caf.invalid_request (tipo no soportado, cantidad fuera de 1–1000) | 400 | — |
forbidden (la key no tiene caf:write, o el rol es viewer) | 403 | Crea la key con ese scope en /app/api-keys |
caf.request_in_flight (cooldown; trae retry_in_seconds) | 409 | Reintenta después de ese plazo |
caf.type_not_prod_certified | 409 | El SII habilita el tipo en producción al aprobar la postulación |
cert.missing | 412 | Sube un certificado vigente primero |
org.required | 412 | — |
caf.cert_not_authorized (el certificado no está autorizado a timbrar) | 502 | Autoriza el certificado en el portal del SII |
caf.grant_rejected (el SII rechazó el grant, con su mensaje) | 502 | — |
caf.request_failed (falló la sesión con el SII) | 502 | — |
db.unavailable · caf.kms_unavailable | 503 | — |
POST /caf
Sube un archivo CAF (multipart/form-data): parsea el XML (RE, TD, D, H), valida el tipo esperado y registra el rango de folios.
| Campo (form) | Tipo | Requerido | Descripción |
|---|---|---|---|
file | archivo | sí | El XML CAF descargado del SII. |
tipo_esperado | int | no | Tipo de DTE que esperas (33, 34, 39, 41, 56, 61); si el XML trae otro, responde 422 caf.wrong_tipo antes de insertar. |
certificate_id | uuid | no | Certificado asociado; default: el primer certificado vigente de la org (sin ninguno → 422 caf.no_certificate). |
A diferencia de /caf/request, el CAF subido queda etiquetado con el ambiente activo de tu organización (cert o prod), no con el de la API key. Si subes un CAF de palena con la organización en cert, la emisión no lo va a encontrar.
Respuesta 201 Created:
La deduplicación es por rango: re-subir el mismo (rut, tipo, folio_desde) responde 409 caf.duplicate.
Errores posibles:
| Código | HTTP | next_action |
|---|---|---|
caf.invalid_request (falta file) | 400 | — |
caf.duplicate | 409 | — |
org.required | 412 | — |
caf.parse_error (XML sin RE/TD/D/H) | 422 | — |
caf.wrong_tipo | 422 | — |
caf.no_certificate | 422 | — |
caf.insert_failed | 500 | — |
db.unavailable · caf.kms_unavailable | 503 | — |
GET /caf
Lista los CAF de tu organización con el consumo de folios de cada rango.
Respuesta 200 OK:
remaining = folio_hasta - next_folio + 1; low_folios se prende con 10 o menos. Errores posibles: 412 org.required, 503 db.unavailable.
DELETE /caf/:id
Elimina un CAF (hard delete, permite re-subir el mismo rango) junto con los DTE del rango que el SII no aceptó; está bloqueado si algún DTE del CAF fue aceptado.
Respuesta 200 OK:
Retención legal de 6 años
Si algún DTE del CAF fue aceptado por el SII (EPR, RPR, DOK, aceptado con reparos), el borrado responde 409 caf.has_accepted_dtes: esos folios quedaron registrados en el SII y los documentos se conservan por obligación legal de 6 años. Lo mismo si un DTE del rango fue cedido vía RPETC (409 caf.has_ceded_dtes).
Errores posibles:
| Código | HTTP | next_action |
|---|---|---|
caf.not_found | 404 | — |
caf.has_accepted_dtes | 409 | — |
caf.has_ceded_dtes | 409 | — |
org.required | 412 | — |
db.unavailable | 503 | — |
PUT /caf/auto
Enciende o apaga el timbraje automático: con él prendido, Notta le pide al SII un rango
nuevo de folios cuando a un tipo de documento le quedan 10 o menos, sin que tengas que
pedirlo. Es el mismo grant irreversible de POST /caf/request, disparado por un barrido
diario en vez de por tu llamada.
Respuesta 200 OK:
umbral es la cantidad de folios restantes que dispara la solicitud: el mismo número que
prende low_folios en GET /caf.
Solo en producción, y cada recarga es irreversible. Mientras tu empresa está en
certificación el toggle responde 409 caf.auto_requires_production: ahí el proceso lo conduce
el asistente de Puesta en Marcha, que además autoriza gestiones que no se deshacen. En
producción, cada recarga automática le pide folios reales al SII y el SII no los devuelve:
prenderlo es autorizar por adelantado esas solicitudes en tu nombre.
Errores posibles:
| Código | HTTP | next_action |
|---|---|---|
caf.invalid_request | 400 | — |
forbidden | 403 | — |
caf.auto_requires_production | 409 | — |
org.required | 412 | — |
db.unavailable | 503 | — |
Próximos pasos
- API: DTEs — con folios cargados, emite tu primera factura por API.
- Onboarding y certificación SII — cómo obtener CAFs en maullin (cert) y palena (prod).
- Conceptos — qué es un CAF y cómo se relaciona con folio, timbre y certificado.
Última actualización