# Códigos (/docs/errores/codigos)

## Códigos de la API [#códigos-de-la-api]

Agrupados por dónde te los vas a encontrar.

### Autenticación y permisos [#autenticación-y-permisos]

| Código                        | HTTP | Causa                                                                              |
| ----------------------------- | ---- | ---------------------------------------------------------------------------------- |
| `insufficient_scope`          | 403  | A la llave le falta un scope; `error.message` nombra cuál                          |
| `empresa_required`            | 400  | Falta el header `Facturia-Empresa` en una llamada con alcance de empresa           |
| `empresa_not_allowed`         | 403  | La empresa está fuera de la lista blanca de la llave                               |
| `empresa_mismatch`            | 400  | Mandaste `Facturia-Empresa` con un token de empresa y no coincide                  |
| `privilege_escalation`        | 403  | Una llave minteada pedía más scopes o empresas que su minteadora                   |
| `api_key_roll_conflict`       | 409  | Dos rotaciones simultáneas de la misma llave; ganó la otra y su secreto es el vivo |
| `email_verification_required` | 403  | Minteo de una llave `sk_live_` desde una cuenta sin verificar                      |
| `test_mode_only`              | 403  | Un endpoint de `/v1/test_helpers` llamado con una llave live                       |

### Emisión [#emisión]

| Código                                      | HTTP | Causa                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| ------------------------------------------- | ---- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `receptor_incomplete`                       | 400  | Al receptor le faltan `giro`/`address` y ningún documento anterior de esta empresa al mismo RUT los tiene. `param` nombra el campo                                                                                                                                                                                                                                                                                                                                                     |
| `totals_mismatch`                           | 422  | Los `totals` que enviaste como aserción no coinciden con nuestro cálculo. No se emitió nada                                                                                                                                                                                                                                                                                                                                                                                            |
| `test_field_in_live_mode`                   | 400  | El objeto `test` viajó con una llave live                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `external_id_exists`                        | 409  | Ya existe un documento con ese `external_id` en esta empresa; `error.existing_id` lo nombra                                                                                                                                                                                                                                                                                                                                                                                            |
| `idempotency_key_reused`                    | 409  | Misma `Idempotency-Key`, cuerpo distinto                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| `idempotency_in_progress`                   | 409  | Un request con esa llave sigue en vuelo; reintenta en un momento                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `artifact_not_ready`                        | 409  | Pediste el XML de un documento que sigue en `queued`                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| `artifact_not_available`                    | 409  | El documento se emitió directo en el portal del SII (SFG); su XML nunca estuvo bajo custodia de Facturia y solo se recupera con la descarga manual «Respaldo de DTE y/o IECV» del portal                                                                                                                                                                                                                                                                                               |
| `cedible_not_available`                     | 422  | `copy=cedible` en un tipo que no es factura (solo 33 y 34)                                                                                                                                                                                                                                                                                                                                                                                                                             |
| `cedible_not_available_for_channel`         | 422  | `copy=cedible` en un documento `emission_channel=sfg`; el SII firma y timbra su propio PDF, sin variante cedible                                                                                                                                                                                                                                                                                                                                                                       |
| `cesion_not_applicable`                     | 422  | Pediste la cesibilidad de un tipo que no la tiene: el registro del SII responde solo por 33, 34 y 43                                                                                                                                                                                                                                                                                                                                                                                   |
| `cesion_status_not_available`               | 409  | Pediste la cesibilidad de un documento que el SII todavía no tiene registrado (`queued`, `sent`) o que nunca va a tener (`failed`, `rejected`)                                                                                                                                                                                                                                                                                                                                         |
| `certificate_expired`                       | 422  | El certificado de la empresa venció; la empresa está `suspended`                                                                                                                                                                                                                                                                                                                                                                                                                       |
| `caf_belongs_to_another_empresa`            | 422  | El `<RE>` del CAF que subiste a `POST /cafs` nombra otro RUT. El SII emite un CAF a un solo emisor: todo documento sacado del rango de otra empresa se rechaza, y para entonces el folio ya se gastó                                                                                                                                                                                                                                                                                   |
| `caf_expired`                               | 422  | El rango de folios se pasó de vigencia: un CAF vale seis meses corridos desde su `<FA>` (Res. Ex. SII N° 58 de 2017) y el SII rechaza al recibir cualquier documento sacado de uno vencido. La emisión se rechaza antes de gastar el folio. Pide folios nuevos y anula los sin usar del rango vencido                                                                                                                                                                                  |
| `tipo_not_available_for_channel`            | 422  | El canal de la empresa no emite ese tipo: `sfg` emite 33/34/52/56/61 y sólo rechaza la 46 (el propio portal del SII no abre el formulario sin autorización de agente retenedor); `mercado` emite todos los tipos publicados. Las boletas 39/41 **no** llegan acá: salen por el motor propio de Facturia diga lo que diga el canal, y lo que las condiciona es la habilitación de boletas del SII — una empresa sin ella recibe `empresa_not_emitting` nombrando el paso `habilitacion` |
| `dispatch_required`                         | 400  | Guía de despacho (52) sin bloque `dispatch`                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| `dispatch_incomplete`                       | 422  | El `dispatch` no trae `transfer_type` (el IndTraslado), que define si la guía constituye venta                                                                                                                                                                                                                                                                                                                                                                                         |
| `dispatch_not_applicable`                   | 422  | Mandaste `dispatch.transfer_type` (IndTraslado) o `dispatch.dispatch_type` (TipoDespacho) en un tipo que no es guía                                                                                                                                                                                                                                                                                                                                                                    |
| `dispatch_not_available_for_channel`        | 422  | `dispatch.destination` o `dispatch.dispatch_type` en una empresa `sfg`: el formulario del portal lleva una sola dirección — la del receptor — y no tiene campo de TipoDespacho. En `mercado` los dos se aceptan                                                                                                                                                                                                                                                                        |
| `sfg_guia_zero_amount`                      | 422  | Una guía (52) con una línea en `unit_price` 0 o total 0 en una empresa `sfg`: el portal valida la guía con las validaciones de la factura y exige precio mayor que 0 en toda clase de traslado. En `mercado` el monto cero se acepta                                                                                                                                                                                                                                                   |
| `line_discount_not_available_for_channel`   | 422  | `items[].discount_percent` mayor que 0 en una empresa `sfg`: el formulario del portal no tiene campo de descuento por línea en ninguna captura nuestra, así que aceptarlo te cotizaría un total con descuento y emitiría el documento sin él. Métele el descuento al `unit_price`, o emite por `emission_channel=mercado`                                                                                                                                                              |
| `global_discount_not_available_for_channel` | 422  | `global_discounts` en una empresa `sfg`: el formulario del portal tiene sus entradas de descuento comentadas, no hay dónde ponerlo. Mismo remedio que el de línea                                                                                                                                                                                                                                                                                                                      |
| `invalid_field`                             | 400  | Un valor de filtro o de enum no reconocido; el mensaje lista los válidos                                                                                                                                                                                                                                                                                                                                                                                                               |
| `field_too_long`                            | 400  | Un campo excede el `maxLength` que el XSD del SII le pone al elemento en que se convierte (`receptor.giro` → `GiroRecep` 40, `receptor.legal_name` → `RznSocRecep` 100, `receptor.address.street` → `DirRecep` 70, `dispatch.carrier.plate` → `Patente` 8, …). Se rechaza, nunca se trunca                                                                                                                                                                                             |

### Recepción [#recepción]

| Código                                   | HTTP | Causa                                                             |
| ---------------------------------------- | ---- | ----------------------------------------------------------------- |
| `commercial_response_not_applicable`     | 422  | El tipo de documento no lleva respuesta comercial (solo 33/34/43) |
| `commercial_response_window_closed`      | 422  | Pasaron los 8 días corridos. `deadline_at` viene en el error      |
| `commercial_response_already_registered` | 409  | Ya se registró una acción sobre ese documento; es de un solo tiro |

### Impuestos [#impuestos]

| Código                             | HTTP | Causa                                                        |
| ---------------------------------- | ---- | ------------------------------------------------------------ |
| `fx_rate_required`                 | 400  | `currency` no es `CLP` y no mandaste `fx_rate`               |
| `f29_amount_confirmation_mismatch` | 422  | `confirm_total_payable` no coincide con la propuesta vigente |

### Plataforma [#plataforma]

| Código                  | HTTP | Causa                                                                                                                                                                                                                                                                                                                                                                             |
| ----------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `plan_limit_reached`    | 402  | Declarado y sin emisor: el plan es plano y con documentos ilimitados, así que hoy nada devuelve este código. Está publicado para que un cliente que ya maneja `402` tenga contra qué programar                                                                                                                                                                                    |
| `subscription_required` | 402  | Esa empresa no tiene suscripción activa y el acto es real (emisión, nota de crédito, folios, envío, puesta en marcha). Se cobra por empresa: las demás siguen                                                                                                                                                                                                                     |
| `payload_too_large`     | 413  | El cuerpo supera el tope de la superficie (2 MB en JSON, 9 MB en `multipart/form-data`). El mensaje nombra el tope en bytes. Se responde **antes** de revisar la llave, así que puede llegar sin autenticación; no se leyó ni se guardó nada. Si lo estás topando con JSON, casi siempre es un archivo mandado como base64: los endpoints de subida reciben `multipart/form-data` |

## Códigos de rechazo del SII [#códigos-de-rechazo-del-sii]

Cuando un documento termina en `rejected` o `reparo`, `rejection_reasons` trae una lista
estructurada:

```json
"rejection_reasons": [
  {
    "code": "ted_signature_invalid",
    "sii_code": "TED-2-510",
    "message": "Firma del timbre electrónico incorrecta",
    "hint": "El DD del timbre fue alterado entre la firma y el envío.",
    "retriable": false
  }
]
```

| Código Facturia           | Código SII                  | Causa                                                             |
| ------------------------- | --------------------------- | ----------------------------------------------------------------- |
| `schema_invalid`          | `SCH-00001`                 | Esquema del sobre rechazado                                       |
| `caratula_invalid`        | `RCT`                       | Datos de la carátula mal (frecuentemente `FchResol` / `NroResol`) |
| `ted_signature_invalid`   | `TED-2-510`                 | La firma del timbre no coincide                                   |
| `field_invalid`           | `HED-3-211`                 | Un campo de cabecera lleva un valor que el SII rechaza            |
| `signer_not_authorized`   | envío estado 1 / `ESTADO 6` | El certificado firmante no es usuario autorizado de la empresa    |
| `emisor_not_authorized`   | `EMP`                       | Empresa no autorizada a emitir este tipo de documento             |
| `document_not_authorized` | `FNA`                       | Folio fuera de un CAF autorizado, o CAF revocado                  |
| `totals_mismatch`         | `DNK`                       | Los montos enviados difieren de los que calculó el SII            |

> **`retriable` es la única señal que importa al reintentar**
>
> Un rechazo con `retriable: false` no cambia de resultado por volver a intentarlo: el documento tiene
> un problema de datos o de autorización. Un `retriable: true` sí puede pasar la próxima vez.
>
> No infieras la respuesta del código HTTP: un `502 sii_error` puede ser cualquiera de los dos, y la
> lista de motivos es lo que lo distingue.

## La copia legible por máquina [#la-copia-legible-por-máquina]

```bash
curl https://api.facturia.cl/v1/error_codes
```

Sin autenticación. Devuelve cada código de Facturia, su contraparte del SII y su `retriable`, para
que tu propio manejo de errores no tenga que transcribir esta tabla a mano.
