# Consultar estado de folios (/docs/referencia/caf/estado-folios)

`POST /v1/caf/{rut}/estado-folios/{tipoDocumento}/{folioInicial}/{folioFinal}`

Cuenta los folios de un rango según el SII, en el ambiente que indique `ambiente`: cuántos el SII
todavía no recibió ni anuló (`Disponibles`), cuántos ya no permite anular, en la práctica los de
documentos que el SII recibió (`Utilizados`), y cuántos se anularon (`Anulados`). Es una lectura:
no anula nada, y repetirla no cambia nada en el SII.

El rango tiene que estar contenido entero en un solo CAF de los que lista caf_v1_listar: tome
`FolioInicial` y `FolioFinal` de uno de esos CAF, o un subrango. `Disponibles` y `Anulados` son
los que informa el SII; `Utilizados` no lo informa el SII: se calcula como `Cantidad` -
`Disponibles` - `Anulados`. `Disponibles` no es la cantidad de folios libres para emitir: puede
incluir folios que usted ya usó en documentos que aún no envió al SII; para decidir qué folio
emitir, use su propio foliado. Si los conteos del SII no cuadran con el rango, la respuesta es un
error, nunca un 200 con ceros.

**Cuál usar.** Para saber el último folio emitido, use caf_v1_consulta; esta operación cuenta un
rango. Consulte bajo demanda, un CAF a la vez: cada llamada es una consulta completa al SII, y
recorrer todos los CAF de caf_v1_listar consume una llamada por CAF del límite de requests. Para
varios CAF, una llamada por CAF y en secuencia. La suma de los subrangos de un CAF no tiene por
qué coincidir con una sola consulta del CAF entero si entre una y otra se emitieron o anularon
folios.

**Permisos.** Como caf_v1_listar, verifica en el SII del mismo ambiente que el titular del
certificado esté autorizado por la empresa para operar con folios (CAF); no hace falta que
administre usuarios. Consulta la opción de anulación masiva del SII: una empresa que no está
habilitada ahí recibe `CONTRIBUYENTE_SIN_PERMISO`. Las boletas (39 y 41) solo se pueden consultar
en certificación (`ambiente=0`).

**Tiempos.** Hace varias llamadas al SII en serie, más que caf_v1_listar, y puede tardar decenas
de segundos: configure un timeout de cliente de al menos 70 segundos. Si tarda más de 60
segundos, la capa de entrada de la API responde 504 con una página HTML, sin código: es una
lectura, repítala. `SII_ERROR_CXN` es frecuente e intermitente en el SII de producción: reintente
respetando `Retry-After` (30 segundos), con espera exponencial (30, 60 y 120 segundos) y un tope
de 3 intentos; cada intento puede tardar decenas de segundos.

**Sesión del SII entre ambientes (sin verificar).** La sesión del SII se reusa 15 minutos por
certificado, en los dos ambientes. Si alterna `ambiente=0` y `ambiente=1` con el mismo certificado
en menos de 15 minutos, el SII podría rechazar la sesión. Desde la versión 1.5.3 la respuesta es
`SII_ERROR_CXN`, reintentable (antes, `SII_RESPUESTA_INESPERADA`): si persiste después de los
reintentos, espere 15 minutos y repita antes de contactar a soporte.

**Para probar.** Con el RUT 1-9 o un RUT de prueba del cliente no se consulta al SII ni se valida
el certificado: cualquier rango válido responde 200 con todos sus folios disponibles, sin
contrastarlo con el CAF de ejemplo de caf_v1_listar (del folio 1 al 10). `PARAMETRO_FUERA_DE_RANGO`
y `NO_SOPORTADO_BOLETAS` sí llegan con el RUT de prueba, porque se revisan antes. El RUT de prueba
no simula los errores del SII: `CAF_NO_ENCONTRADO`, `SII_ERROR_CXN` y los rechazos solo se ven
contra el SII; `CAF_NO_ENCONTRADO`, con una empresa real en certificación.

## Parámetros

| Nombre | En | Tipo | Requerido | Descripción |
|---|---|---|---|---|
| `rut` | path | string | sí | RUT de la empresa. |
| `tipoDocumento` | path | integer | sí | Tipo del documento DTE, con el código del SII: 33 factura, 34 factura exenta, 39 y 41 boletas, 56 nota de débito, 61 nota de crédito, entre otros. 39 y 41 solo en certificación (`ambiente=0`). |
| `folioInicial` | path | integer | sí | Primer folio del rango: un entero mayor o igual a 1, no mayor que `folioFinal`. Tome el `FolioInicial` de un CAF de caf_v1_listar, o un folio dentro de ese CAF. Un valor menor que 1, o mayor que `folioFinal`, responde `PARAMETRO_FUERA_DE_RANGO` sin tocar el certificado ni el SII. |
| `folioFinal` | path | integer | sí | Último folio del rango, incluido: un entero mayor o igual a 1, no menor que `folioInicial`, y del mismo CAF de caf_v1_listar. Un valor menor que 1, o menor que `folioInicial`, responde `PARAMETRO_FUERA_DE_RANGO` sin tocar el certificado ni el SII. |
| `ambiente` | query | integer | no | Ambiente del SII: 0 = Homologación (certificación), 1 = Producción. Si se omite, opera en **producción**: páselo siempre explícito. Un valor que no se reconoce no da error: la operación corre en producción. Un número distinto de 0 y 1 no da error y corre en homologación. En caf_v1_reobtener, ese mismo número corre en producción: use 0 o 1 en las dos. |

## Cuerpo

```json
{
  "Contrasenna": "********",
  "Data": "MIIC"
}
```

## Respuestas

### 200

El estado del rango según el SII: `Rut`, `TipoDocumento`, `FolioInicial`, `FolioFinal`, `Cantidad`, `Disponibles`, `Utilizados` y `Anulados`, con `Cantidad` = `FolioFinal` - `FolioInicial` + 1 = `Disponibles` + `Utilizados` + `Anulados`, siempre. `Disponibles`: los que el SII todavía no recibió ni anuló, que pueden incluir folios que usted usó en documentos que aún no envió al SII. `Utilizados`: los que el SII ya no permite anular; se calcula. `Anulados`: los anulados en el SII. Si los conteos del SII no cuadran con el rango, la respuesta es un error, nunca un 200 con ceros. Con el RUT 1-9 o un RUT de prueba del cliente, el rango pedido con todos sus folios disponibles.

| Campo | Tipo | Descripción |
|---|---|---|
| `Anulados` | integer | Folios del rango anulados en el SII. |
| `Cantidad` | integer | Folios del rango: `FolioFinal` - `FolioInicial` + 1. |
| `Disponibles` | integer | Folios del rango que el SII todavía no recibió ni anuló: puede incluir folios que usted ya usó en documentos que aún no envió al SII. No use este número para decidir qué folios emitir: use su propio foliado. |
| `FolioFinal` | integer | Último folio del rango consultado, incluido. |
| `FolioInicial` | integer | Primer folio del rango consultado. |
| `Rut` | string o null | RUT de la empresa consultada, normalizado con guion y dígito verificador. |
| `TipoDocumento` | integer | Tipo del documento DTE consultado. |
| `Utilizados` | integer | Folios del rango que el SII ya no permite anular: en la práctica, los de documentos que el SII recibió. No viene del SII: se calcula como `Cantidad` - `Disponibles` - `Anulados`. El conteo de recibidos del SII no se usa porque no es confiable. |

Ejemplo:

```json
{
  "Anulados": 2,
  "Cantidad": 100,
  "Disponibles": 60,
  "FolioFinal": 1100,
  "FolioInicial": 1001,
  "Rut": "11111111-1",
  "TipoDocumento": 33,
  "Utilizados": 38
}
```

### 400

Un parámetro numérico de la ruta (o de la query) sin valor por omisión no se pudo convertir: no es un número, o no cabe en el tipo. Lo responde el framework, después de autenticar y antes de ejecutar la operación. `MessageDetail` depende de la configuración del servidor (no verificado): no dependa de él.

### 401

No autenticado.

### 404

Esta operación no tiene un 404 de negocio. Un 404 es una URL que no corresponde a ninguna operación (una ruta mal escrita, un segmento de más o de menos): en general lo responde el servidor web con una página HTML, sin los headers de la API; si la URL llega a la API, es un JSON del framework con `Message`. Inferido del código, no verificado contra el servidor desplegado. Revise la URL: repetir el mismo request da el mismo 404. El texto plano sigue declarado para no romper el contrato publicado, pero esta operación nunca responde un 404 en texto plano.

### 409

Se superó el rate limit: **409 Conflict**, no 429. El request no se ejecutó.

### 500

Error de negocio en texto plano, `CODIGO:mensaje`, con los headers `X-Codigo-Error`,
`X-Reintentable` y, si vale reintentar, `Retry-After`; ante una falla interna, un error del
framework en JSON. Esta operación no responde desde la memoria de rechazos: nunca trae
`X-Respuesta-De-Memoria`.

Un RUT que no es válido responde antes que nada `ERROR_GENERAL:El rut … no es valido.`:
corríjalo, no lo reintente.

Después, antes de validar el certificado o consultar al SII, también con el RUT de prueba:

- `folioInicial` o `folioFinal` menor que 1, o `folioInicial` mayor que `folioFinal`:
  `PARAMETRO_FUERA_DE_RANGO`.
- Tipos 39 y 41 en producción: `NO_SOPORTADO_BOLETAS` (en certificación, con `ambiente=0`, sí se
  consultan).

Después:

- Sin el cuerpo del POST, o sin `Data` o sin `Contrasenna`: `CERT_REQUERIDO:Los datos del
  certificado son requeridos.`.
- El certificado no se pudo validar: el error de la validación con su propio código
  (`CERT_EXPIRADO`, `CERT_REVOCADO`, `CERT_NO_VALIDO`, `CERT_NO_CONFIGURADO_AUTH`,
  `CERT_AUTH_NOT_CONFIGURED`, `CERT_ERROR`…).
- El SII dice que el titular del certificado no está autorizado por la empresa para operar con
  folios: `CERT_SIN_PERMISO`.
- La empresa no puede operar en esa modalidad (MiPyme): `SEC_EMP_NOT_AUTHORIZED`.
- La empresa no está habilitada en la opción de anulación masiva del SII:
  `CONTRIBUYENTE_SIN_PERMISO`.
- El rango no está contenido en un solo CAF del listado del SII: `CAF_NO_ENCONTRADO`.
- El SII pide intentarlo más tarde, falló la comunicación con el SII o, desde la versión 1.5.3,
  el listado de CAF del SII pide volver a iniciar sesión: `SII_ERROR_CXN`, reintentable.
- La página del listado de CAF del SII no dice si el certificado tiene permiso, el SII contestó
  algo que no se pudo interpretar o conteos que no cuadran con el rango:
  `SII_RESPUESTA_INESPERADA`, no reintentable.
- Además pueden llegar otros rechazos del SII: `SEC_USER_BOLSII`, `SEC_USER_NOT_AUTHENTICATED`
  y, al autenticar el certificado, `CERT_REVOCADO` o `CERT_EXPIRADO`.

Ejemplos en `text/plain`:

**El rango no cabe entero en un solo CAF** (`CAF_NO_ENCONTRADO`)

```text
CAF_NO_ENCONTRADO:El rango de folios 1001-1200 del tipo 33 no está contenido en un solo CAF de la empresa 11111111-1 según el listado del SII.
```

**Boletas (39 o 41) en producción** (`NO_SOPORTADO_BOLETAS`)

```text
NO_SOPORTADO_BOLETAS:El estado de folios de boletas (tipos 39 y 41) no está disponible en producción. En certificación sí se puede consultar.
```

**Un folio menor que 1, o el rango invertido** (`PARAMETRO_FUERA_DE_RANGO`)

```text
PARAMETRO_FUERA_DE_RANGO:folioInicial y folioFinal tienen que ser mayores que 0, y folioInicial no puede ser mayor que folioFinal.
```

**El SII pidió intentarlo más tarde (reintentable)** (`SII_ERROR_CXN`)

```text
SII_ERROR_CXN:Error de comunicacion con el SII, intente nuevamente.
```

## Códigos de error

| Status | Código | Mensaje |
|---|---|---|
| 500 | `CERT_SIN_PERMISO` | «El certificado no está autorizado por la empresa {rut} para operar con folios (CAF) en el SII.»; o «El certificado no tiene permisos para la empresa {rut}.»; o «El certificado no tiene permisos para la empresa.» |
| 500 | `NO_SOPORTADO_BOLETAS` | «El estado de folios de boletas (tipos 39 y 41) no está disponible en producción. En certificación sí se puede consultar.» |
| 500 | `PARAMETRO_FUERA_DE_RANGO` | «folioInicial y folioFinal tienen que ser mayores que 0, y folioInicial no puede ser mayor que folioFinal.» |

## Reintentos e idempotencia

**Idempotente: sí.** Repetirla con los mismos datos no duplica nada.

| Qué hacer | Códigos y status |
|---|---|
| Reintentar solo, con espera (`automatico`) | `409`, [`SII_ERROR_CXN`](/docs/errores-y-reintentos/#error-SII_ERROR_CXN) |
| Consultar el estado antes de repetir (`manual`) | [`CERT_ERROR`](/docs/errores-y-reintentos/#error-CERT_ERROR), [`ERROR_GENERAL`](/docs/errores-y-reintentos/#error-ERROR_GENERAL), [`SEC_USER_NOT_AUTHENTICATED`](/docs/errores-y-reintentos/#error-SEC_USER_NOT_AUTHENTICATED) |
| No repetir: corregir la causa (`nunca`) | [`CAF_NO_ENCONTRADO`](/docs/errores-y-reintentos/#error-CAF_NO_ENCONTRADO), [`CERT_AUTH_NOT_CONFIGURED`](/docs/errores-y-reintentos/#error-CERT_AUTH_NOT_CONFIGURED), [`CERT_EXPIRADO`](/docs/errores-y-reintentos/#error-CERT_EXPIRADO), [`CERT_NO_CONFIGURADO_AUTH`](/docs/errores-y-reintentos/#error-CERT_NO_CONFIGURADO_AUTH), [`CERT_NO_VALIDO`](/docs/errores-y-reintentos/#error-CERT_NO_VALIDO), [`CERT_REQUERIDO`](/docs/errores-y-reintentos/#error-CERT_REQUERIDO), [`CERT_REVOCADO`](/docs/errores-y-reintentos/#error-CERT_REVOCADO), [`CERT_SIN_PERMISO`](/docs/errores-y-reintentos/#error-CERT_SIN_PERMISO), [`CONTRIBUYENTE_SIN_PERMISO`](/docs/errores-y-reintentos/#error-CONTRIBUYENTE_SIN_PERMISO), [`NO_SOPORTADO_BOLETAS`](/docs/errores-y-reintentos/#error-NO_SOPORTADO_BOLETAS), [`PARAMETRO_FUERA_DE_RANGO`](/docs/errores-y-reintentos/#error-PARAMETRO_FUERA_DE_RANGO), [`SEC_EMP_NOT_AUTHORIZED`](/docs/errores-y-reintentos/#error-SEC_EMP_NOT_AUTHORIZED), [`SEC_USER_BOLSII`](/docs/errores-y-reintentos/#error-SEC_USER_BOLSII), [`SII_RESPUESTA_INESPERADA`](/docs/errores-y-reintentos/#error-SII_RESPUESTA_INESPERADA) |

Un código que no figura en esta tabla se resuelve con la [regla de respaldo](/docs/errores-y-reintentos/#la-regla-de-respaldo).

## Ejemplo

```bash
curl --request POST \
  --url 'https://api.enrolamiento.cl/v1/caf/1-9/estado-folios/33/1001/1100?ambiente=0' \
  --header 'Accept: application/json' \
  --header 'Authorization: Basic <base64 de usuario:apikey>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "Contrasenna": "********",
  "Data": "MIIC"
}
'
```