Catálogo de errores
Referencia de los códigos que emite la API, con next_action accionable por código y request_id para correlacionar con soporte.
Todos los errores Notta siguen el shape { code, message, request_id, hint?, next_action?, detail?, docs_url? }. El campo next_action es enumerable y está diseñado para que un agente LLM pueda razonar qué hacer sin necesidad de leer el message.
Estructura
Incluye el request_id al contactar soporte: es el identificador que correlaciona tu request con los logs del servidor.
Códigos por dominio
Cuando un código no trae next_action (marcado con —), la corrección sale del code más el detail.
Autenticación y permisos
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
unauthorized | 401 | Falta el header Authorization: Bearer | send_bearer_token |
invalid_api_key | 401 | La API key no matchea ninguna key activa | regenerate_api_key |
api_key_expired | 401 | API key expirada | regenerate_api_key |
api_key_revoked | 401 | API key revocada | regenerate_api_key |
forbidden | 403 | La key no tiene el scope requerido (dte:read / dte:write) | use_api_key_with_required_scope |
cert_id_missing | 400 | Falta el header X-Cert-Id en un verbo que firma | send_cert_id_header |
cert_id_ambiguous | 400 | La org tiene varios certificados vigentes — especifica cuál firma con X-Cert-Id | send_cert_id_header |
org.required | 412 | La sesión de dashboard no tiene organización — completa el onboarding de org (aplica a /certificates, /caf y /api-keys) | — |
org.rut_missing | 412 | La organización de la sesión no tiene RUT registrado — complétalo en el onboarding antes de sincronizar el RCV | — |
onboarding_production_not_authorized | 403 | La org todavía no está habilitada para emitir en producción (palena) | — |
csrf_origin_mismatch | 403 | Origin no permitido para esta acción (protección CSRF de la sesión de dashboard; no aplica al camino Authorization: Bearer) | — |
Validación del payload
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
validation_failed | 400 | El body no pasa el schema — revisa issues[] campo por campo | fix_body_and_retry |
invalid_json | 400 | El body no es JSON válido | fix_json_body_and_retry |
idempotency_key_missing | 400 | Falta el header Idempotency-Key (obligatorio en todo POST de emisión) | send_idempotency_key_header |
receptor_rut_invalid | 400 | RUT receptor con DV inválido | — |
emisor_rut_mismatch | 422 | El rut_emisor del body no coincide con el RUT del certificado | — |
emisor.profile_incompleto | 422 | Faltan datos del perfil del emisor para emitir (detail.missing) | complete_emisor_profile |
items_empty | 400 | items vacío | — |
items_exceed_max | 400 | items supera el máximo (límite SII; detail.count) | — |
amount_arithmetic | 400 | Los montos declarados no cuadran aritméticamente | — |
references_required | 400 | El tipo_dte exige references y no vienen | — |
reference_invalid_cod_ref | 400 | cod_ref fuera del enum 1/2/3 | — |
text_correction_must_be_zero | 400 | NC de corrección de texto (cod_ref 2) debe llevar montos en cero | — |
dte.tipo_not_supported | 400 | tipo_dte no soportado por este pipeline | fix_tipo_dte_and_retry |
dte.34.invalid_exenta | 422 | DTE 34 (Factura Exenta) con items afectos | fix_tipo_dte_and_retry |
dte.41.afecto_not_allowed | 422 | Boleta Exenta 41 con items afectos | fix_tipo_dte_and_retry |
dte.46.invalid_afecta | 422 | DTE 46 (Factura de Compra) con items exentos — es una operación 100% afecta (cambio de sujeto) | remove_exento_items_and_retry |
dte.mixed_retencion_references | 422 | Una NC/ND mezcla una referencia con retención total de IVA (Factura de Compra 46) y otra sin retención — no hay un total coherente para todo el documento | split_into_separate_documents_by_retencion |
dte.type.prod_not_certified | 422 | El tipo de DTE aún no está certificado para producción (gate N1 por tipo); emítelo en certificación (maullin) mientras se completa la cert ante el SII | emit_dte_in_cert |
idempotency_conflict | 409 | Mismo Idempotency-Key con otro body — detail.existingDteId apunta al DTE original | — |
Lectura y estado del DTE
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
not_found | 404 | El recurso no existe o pertenece a otra org (DTEs y boletas) | — |
dte.xml.not_yet_available | 404 | El DTE todavía no tiene XML — el workflow de firma sigue corriendo | poll_self |
dte.pdf.not_signed | 409 | El DTE existe pero no está firmado — el PDF requiere el TED (síguelo en xml_url) | poll_self |
dte.refresh_status.no_track_id | 409 | El DTE aún no fue subido al SII — no hay track_id que consultar | wait_for_emit_workflow |
dte.refresh_status.no_cert | 409 | La org no tiene certificado activo para autenticar la consulta de estado | — |
dte.resend_delivery.not_wired | 501 | El reenvío del DTE al receptor no está disponible en este entorno | — |
dte.resend_delivery.tipo_not_supported | 422 | El tipo_dte no se envía al receptor (las boletas 39/41 van a consumidores por el pipeline REST) | — |
dte.resend_delivery.no_email | 422 | El DTE no tiene correo del receptor — incluye correo_receptor en el body para reenviar | provide_correo_receptor |
Muestras impresas (certificación)
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
dte.muestras.empty | 422 | No hay DTEs firmados (33/34/56/61) para armar el lote de muestras | emit_and_sign_dtes_first |
dte.muestras.no_samples | 422 | No hay DTEs firmados para enviar como muestras al SII | emit_and_sign_dtes_first |
dte.muestras.too_large | 422 | El lote supera el límite de 3 MB del SII | paginate_into_multiple_emails |
dte.muestras.send_not_configured | 422 | El remitente de email no está configurado en el servidor | contact_support |
dte.muestras.not_sent | 422 | El envío no salió por una razón no mapeada — message trae el motivo | — |
dte.muestras.send_not_wired | 501 | El envío de muestras no está disponible en este entorno | — |
Certificado y folios (CAF) en la emisión
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
cert_not_found | 404 | No hay certificado digital cargado para la org | — |
cert_expired | 422 | Certificado expirado (detail.expiredAt) | — |
cert_subject_mismatch | 422 | El RUT del certificado no corresponde al emisor | — |
cert.kms.auth_failed | 422 | Falló el descifrado del certificado (detail.phase) — rotación de KEK o seed inconsistente | reseed_certificate |
caf_not_found | 404 | No hay CAF cargado para ese tipo de DTE (detail.tipoDte) | — |
caf_expired | 422 | CAF vencido (detail.expiredAt) | — |
caf_exhausted | 422 | CAF sin folios disponibles | — |
sii_env_mismatch | 422 | El CAF corresponde a otro ambiente SII (certificación vs producción) que el del DTE | — |
dte.production_resolucion_missing | 409 | Falta la Resolución Exenta del SII (NroResol/FchResol) para emitir a producción — se ingiere del email del SII a la casilla del emisor | capture_sii_resolucion |
dte.46.prod_not_certified | 422 | DTE 46 (Factura de Compra) habilitado solo en certificación (maullin) — la certificación oficial del tipo 46 para producción está en curso | emit_dte_46_in_cert |
Gestión de certificados (/certificates)
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
cert.invalid_request | 400 | Falta file, password o label en el form-data | — |
cert.invalid | 422 | No se pudo leer el .p12 (corrupto, sin llave privada, o clave equivocada) | — |
cert.duplicate | 409 | Ese certificado (misma huella SHA-256) ya está cargado para la org | — |
cert.not_found | 404 | El certificado no existe para la org | — |
cert.expired | 409 | El certificado está vencido; no puede quedar como predeterminado | — |
Gestión de CAF (/caf)
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
caf.invalid_request | 400 | Falta file en el form-data | — |
caf.parse_error | 422 | El XML del CAF no trae los campos requeridos (RE/TD/D/H) | — |
caf.wrong_tipo | 422 | El CAF subido no corresponde al tipo_esperado del recuadro | — |
caf.no_certificate | 422 | No hay certificado cargado — sube el certificado antes del CAF | — |
caf.duplicate | 409 | Ese rango de folios ya está registrado | — |
caf.not_found | 404 | El CAF no existe para la org | — |
caf.has_accepted_dtes | 409 | No se puede eliminar: tiene DTEs aceptados por el SII (retención legal de 6 años) | — |
caf.has_ceded_dtes | 409 | No se puede eliminar: un DTE del CAF fue cedido vía RPETC | — |
caf.request_in_flight | 409 | Ya hay una solicitud reciente de folios para este tipo — espera unos minutos antes de reintentar | — |
caf.request_failed | 502 | La solicitud de folios al SII falló — message trae el motivo | — |
caf.grant_rejected | 502 | El SII no concedió el folio (rechazo del timbraje) — message/data traen el detalle | — |
caf.cert_not_authorized | 502 | El certificado activo no está autorizado a solicitar folios (timbrar) para esta empresa en el SII — revisa los usuarios autorizados en Mi SII o cambia el certificado activo | — |
caf.type_not_prod_certified | 409 | Este tipo de documento aún no está certificado para producción. Completa la certificación por-tipo antes de solicitar folios. | — |
Notas de crédito y débito (compliance)
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
dte.nota_credito.fuera_plazo | 422 | NC fuera del plazo legal de 6 meses (Ley 21.398) | consult_lawyer_or_use_correction_path |
nc.over_cedida.blocked | 422 | Factura referenciada cedida vía RPETC con aceptación irrevocable ≥8 días (Corte Suprema 2025) | confirm_override_and_retry |
dte.nota_credito.cedida_override_required | 409 | Mismo bloqueo de cesión, detectado por el chequeo de emisión: requiere override explícito | confirm_override_and_retry |
dte.nota_credito.invalid_cod_ref | 422 | cod_ref inválido para NC — usa 1 (anula), 2 (corrige texto), 3 (corrige montos) | fix_cod_ref_and_retry |
dte.nota_credito.reference_tipo_unsupported | 422 | NC 61 solo referencia facturas 33 o 34 | use_factura_33_or_34_reference |
dte.nota_debito.interese_moratorio_legal | 422 | Intereses moratorios legales no se documentan con DTE (Oficio SII 2011/2020) | consult_oficio_2011_2020 |
dte.nota_debito.invalid_reason | 422 | nd_reason fuera del enum válido (detail.validReasons) | fix_reason_and_retry |
Guía de despacho (52)
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
dte.52.dispatch_required | 400 | DTE 52 requiere el bloque despacho | include_despacho_and_retry |
dte.52.invalid_traslado | 422 | ind_traslado fuera de los valores soportados (detail.supported) | fix_ind_traslado_and_retry |
dte.52.transportista_required | 422 | Falta el transportista (detail.field) — Res. 154/2025 | — |
dte.52.conductor_required | 422 | Falta el conductor (detail.field) — Res. 154/2025 | — |
dte.52.vehiculo_required | 422 | Falta el vehículo (detail.field) — Res. 154/2025 | — |
dte.52.parent_invalid | 500 | Inconsistencia interna con el documento padre referenciado | — |
SII y errores transitorios
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
sii_rejection | 422 | El SII rechazó el DTE — detail.code y detail.glosa traen el veredicto | — |
sii_unavailable | 503 | SII caído transitorio (detail.retryAfterSec) | — |
sii_invalid_track_id | 502 | El SII no reconoce el track id del envío | — |
rate_limit | 429 | Límite de tasa superado (detail.retryAfterSec) — ver Límites de tasa | — |
internal_error | 500 | Error no mapeado; el detalle queda en los logs del servidor | — |
Boletas
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
boleta.credentials.not_found | 404 | Falta la clave tributaria SII de la org | configure_sii_credentials |
boleta.rest.unavailable | 502 | Endpoint REST de boletas del SII no disponible (detail.retryAfterSec) | retry_with_backoff |
boleta.rest.token_expired | 401 | Token del pipeline REST expirado | reauthenticate |
boleta.rest.pipeline_error | 500 | El pipeline REST falló en una fase interna (detail.phase) | operator_review |
boleta.xml.not_yet_available | 404 | La boleta todavía no tiene XML — el pipeline sigue corriendo | poll_self |
validation_error | 422 | El payload del batch de boletas no pasa el schema — revisa errors[] | — |
boleta.batch.exceeds_max | 422 | El batch supera el máximo (detail.max) | split_batch |
boleta.batch.idempotency_conflict | 409 | Posición del batch ya ocupada (detail.batchId) | poll_existing_or_change_key |
boleta.batch.not_found | 404 | El batchId no existe para la org | verify_batch_id |
BHE
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
bhe.credential.invalid | 401 | Clave tributaria BHE no encontrada o rechazada (detail.reason) | configure_bhe_credential |
bhe.plazo_anulacion.expired | 422 | BHE fuera del plazo de 3 meses para anular | consult_sii_or_manual_rectification |
bhe.retencion.mismatch | 422 | La retención enviada no concuerda con la tasa legal del año (detail.expected) | use_calculated_retencion |
bhe.receptor.tipo_invalid | 422 | Tipo de receptor inválido para BHE | fix_receptor_and_retry |
bhe.rest.unavailable | 502 | Endpoint BHE del SII (loa.sii.cl) no disponible (detail.retryAfterSec) | retry_with_backoff |
bhe.rest.token_expired | 401 | Token del pipeline BHE expirado | reauthenticate |
bhe.rest.pipeline_error | 500 | El pipeline BHE falló en una fase interna (detail.phase) | operator_review |
bhe.not_found | 404 | La BHE no existe para la org | — |
Billing
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
billing.free_tier_exceeded | 402 | Cuota mensual del plan alcanzada (detail.usedThisMonth / detail.limit) — suscribite a un plan superior o espera al próximo período | upgrade_plan |
Infraestructura (transitorios del servidor)
Reintenta con backoff; si persisten, contacta soporte con el request_id.
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
db.unavailable | 503 | La base de datos no está disponible | — |
db.pool_exhausted | 503 | El pool de conexiones a la base de datos está saturado — reintenta | — |
cert.kms_unavailable | 503 | El KMS que cifra certificados no está disponible | — |
caf.kms_unavailable | 503 | El KMS que cifra CAFs no está disponible | — |
cert.insert_failed | 500 | Falló la persistencia del certificado | — |
caf.insert_failed | 500 | Falló la persistencia del CAF | — |
RCV y RCOF
| Código | HTTP | Descripción | next_action |
|---|---|---|---|
rcv.sync.failed | 502 | El sync del RCV falló contra el SII (detail.periodo) | retry_sync |
rcv.unauthorized | 401 | Clave tributaria rechazada por el SII para RCV | configure_sii_credential |
rcv.period.invalid | 422 | Periodo inválido — debe ser YYYY-MM y no estar en el futuro (detail.reason) | fix_period_and_retry |
rcof.no_data | 422 | Sin boletas 39/41 emitidas en esa fecha — no se genera RCOF (detail.fecha) | verify_fecha |
rcof.aggregation_error | 500 | Falló la agregación de boletas del día para el RCOF | — |
rcof.build_error | 500 | Falló la construcción del XML del RCOF | — |
rcof.upload_error | 502 | El envío del RCOF al SII falló (detail.phase) | retry_resend |
Ejemplo: factura cedida
Rechazos del SII (al subir el DTE)
Cuando el SII recibe el EnvioDTE corre una cascada de validadores: XSD → schema → firma → carátula → timbre. Cada validador enmascara al siguiente, así que corregir un rechazo suele destapar el próximo en ese mismo orden.
El getEstUp del SII devuelve solo el código de cabecera (RFR/RCT/EPR); el sub-código accionable (p. ej. CRT-3-19, TED-2-510) llega por email del SII. Notta lo expone en sii_glosa.
| Rechazo | Significado | Acción |
|---|---|---|
RFR | Rechazado por Error en Firma (canonicalización c14n / xmlns heredado / charset de la firma) | Re-firmar el DTE con la canonicalización y el encoding correctos |
CHR-00002 | Línea muy larga o encoding latin1 — aflora como RFR/RSC | Corregir el encoding/largo de línea y re-firmar |
RCT | Rechazado por Error en Carátula | Corregir la Carátula y reenviar |
CRT-3-19 | Sub-código de RCT: Fecha/Número de Resolución inválido (FchResol/NroResol) | Corregir la resolución y reenviar |
TED-2-510 | Reparo: Firma del Timbre Electrónico (TED/FRMT) incorrecta — el DTE queda en EPR con reparo | Re-firmar el timbre sobre el DD canónico y reenviar |
RFR — Rechazado por Error en Firma
La firma se rompió porque los bytes canónicos que el SII verifica no son los que se firmaron: un xmlns heredado que el c14n omite al firmar e incluye al verificar, o un XML re-serializado después de firmar.
Cómo verificarlo: ejecuta un roundtrip local de firma + verificación sobre los bytes exactos que van al wire. Si el elemento firmado (SetDTE/Documento) solo hereda el namespace sin declararlo, el self-verify falla — redeclara xmlns explícito y firma con c14n-20010315 (el c14n exclusivo lo rechaza el XSD del SII).
CHR-00002 — línea muy larga o charset inválido
El validador de charset cortó el envío porque alguna línea del XML supera los 4090 caracteres o los bytes no van en ISO-8859-1.
Cómo verificarlo: mide el largo de línea máximo del XML enviado y confirma que el wire va como latin1, con saltos de línea entre las secciones mayores (Encabezado, Detalle, TED).
RCT — Rechazado por Error en Carátula
La carátula declara datos que el SII no tiene registrados para el emisor: RutEmisor/RutEnvia que no corresponden, o una resolución (FchResol/NroResol) inválida.
Cómo verificarlo: el sub-código del email del SII apunta al campo exacto (p. ej. CRT-3-19 es la resolución). Compara cada campo de la carátula contra lo registrado para la empresa en el SII antes de reenviar.
CRT-3-19 — Fecha/Número de Resolución inválido
La FchResol no es la fecha que el SII tiene registrada para tu empresa: en certificación el comodín 2014-08-22 no sirve para empresas recién postuladas — el SII espera la fecha real de postulación.
Cómo verificarlo: reenvía con FchResol = fecha en que la empresa postuló como emisor electrónico en maullin y NroResol = 0 (válido para todo emisor en certificación). Si el envío pasa, el comodín era el problema.
TED-2-510 — firma del timbre incorrecta
La firma FRMT se calculó sobre los bytes literales del DD, pero el SII la verifica sobre el DD canónico con el whitespace entre elementos colapsado.
Cómo verificarlo: verifica la FRMT localmente contra la clave pública del CAF usando dd.replace(/>\s+</g, "><") como input. Si verifica con la forma canónica y falla con la literal, re-firma el timbre sobre la canónica (preservando los bytes literales del CAF en el wire).
Corrección automática
Notta corrige la mayoría de estos rechazos automáticamente; este catálogo te ayuda a entender el sii_glosa cuando un DTE queda en un estado de rechazo.
Cómo manejar errores en código
Buenas prácticas
- Decide por
error.code(ynext_actioncuando viene), nunca por string-matching delmessage: el texto puede cambiar, los códigos no. next_actiones enumerable y estable — los valores existentes no cambian de semántica; solo se agregan nuevos.- No reintentes los
4xxsalvo429: un400/422va a fallar igual hasta que corrijas el payload. Los502/503transitorios sí se reintentan con backoff. - Loguea el
request_idde cada error en tu sistema: acelera cualquier diagnóstico con soporte.
Próximos pasos
- Límites de tasa — el detalle del
429y el patrón de backoff para errores transitorios. - Referencia API de DTEs — los endpoints que emiten estos códigos.
- Nota de crédito (61) — el flujo completo detrás de
nc.over_cedida.blockedy el plazo de 6 meses. - Webhooks — el contrato de eventos para reaccionar a rechazos sin polling.
Última actualización