AMBIENTE DE CERTIFICACIÓN

API de Facturación Electrónica

Contrato técnico de la implementación Node.js + Express + TypeScript para generar, firmar, validar y probar DTE ante el ambiente de certificación del Servicio de Impuestos Internos de Chile.

v0.1.0versión del proyecto
33 · 34 · 52 · 56 · 61tipos DTE implementados
Zod 4validación de entrada
TypeScript173 fuentes verificadas
Solo certificaciónproducción bloqueada
MongoDBpersistencia operativa

Qué tenemos hoy

Verificado

Node.js + TypeScript

Aplicación, scripts, pruebas y Vitest migrados; typecheck, build, 162 pruebas y servidor compilado validados.

Implementado

DTE

Factura 33, factura exenta 34, guía de despacho 52, nota de débito 56 y nota de crédito 61.

Implementado

Artefactos

XML, TED, firma electrónica, XSD, EnvioDTE, PDF417 en modo byte y PDF tributario/cedible.

Reestructurado

Arquitectura API

API y cinco workers activos en EC2; generación 33 y PDF comprobados extremo a extremo con SQS, MongoDB, S3 y Signed URLs de CloudFront.

Implementado

CAF

Importación, validación de emisor, inventario y reserva atómica de folios en MongoDB.

Implementado

Set SII

Sets 5037509 y 5037512, receptores distintos, referencias SET/CASO y herencia de receptor en notas.

Validado

Credenciales TITA

PFX vigente, titular/RutEnvia 15.805.965-7 coherente, CAF 33/34/56/61 con folios 1–50 y autenticación real SII aprobada el 26-08-2026.

Implementado

Libros e intercambio

IECV ventas 5037510, compras 5037511, RespuestaDTE, resultado comercial y recibo Ley 19.983.

Verificado local

Simulación y muestras

Simulación de 10–100 DTE, envío explícito, verificador independiente y preparación de 29 PDF en lotes de máximo 20.

Implementado

Respaldo cifrado

MongoDB se comprime y cifra por stream; admite verificación autenticada y restauración en colecciones aisladas sin escribir un dump plano en disco.

Dato externo pendiente

Antes del upload

Confirmar permisos del firmante, comprobar la casilla de intercambio y revisar los artefactos antes de enviarlos.

Fuera del MVP DTE

No implementado

Producción, boletas 39/41, RVD, exportación y Libro de Guías.

Importante: generar archivos localmente no equivale a estar certificado. La aprobación sólo se confirma cuando el SII recibe y acepta los sets y las demás etapas exigidas al contribuyente.

CAF: el par privado/público y la pertenencia a TITA sí se verifican. La propiedad siiSignatureVerified permanece null porque todavía no se dispone de una llave pública oficial del SII confiable para validar FRMA/IDK 100. Nunca se informa falsamente como aprobada.

Arquitectura asíncrona y multitenant

Una sola EC2 ejecuta la API Express y cinco procesos worker independientes bajo PM2. No se usa ALB, Docker, PostgreSQL ni Redis. MongoDB conserva estado e idempotencia; SQS sólo transporta identificadores y referencias, nunca XML, CAF, PFX ni contraseñas.

Cola Worker Responsabilidad
tita-dte-generate generate Reserva, construye, timbra, firma y valida el DTE; deja artefactos privados en S3.
tita-dte-send-sii send-sii Crea y firma EnvioDTE, registra el inicio del upload y conserva TrackID/fecha.
tita-dte-status status Consulta el SII con esperas de 30, 60, 120 y 300 segundos sin bloquear un proceso.
tita-dte-pdf pdf Genera PDF tributario/cedible para documentos emitidos y PDF para DTE recibidos.
tita-dte-email-inbound email-inbound Procesa SES→S3, valida adjuntos XML, guarda XML completo en Mongo/S3 y encola PDF.

Cada cola tiene su -dlq, cifrado y máximo de cinco recepciones. Todos los registros, consultas, CAF, folios, prefijos S3, API keys y URLs se acotan por tenantId. Una credencial de otro tenant obtiene 403 o 404, nunca el documento.

Compuerta SII: SII_UPLOAD_ENABLED=false impide tanto el envío como el seguimiento real. Sólo se cambia después de revisar este ambiente y contar con autorización explícita.

Flujo de una prueba de certificación

  1. Validar
    Zod normaliza RUT, fechas, números y reglas condicionales.
  2. Construir
    Se calculan neto, exento, IVA, descuentos, recargos y total.
  3. Firmar
    CAF firma el TED y el certificado firma DTE y sobre.
  4. Verificar
    Se verifican firmas y XSD antes de persistir artefactos en MongoDB.
  5. Revisar
    Se inspeccionan XML, PDF y manifiestos generados.
  6. Enviar
    El envío al SII es explícito; guarda Track ID y fecha del upload.

Inicio rápido

Para desarrollo local, cree su archivo privado una sola vez:

Copy-Item .env.example .env
npm ci
npm start

Invoke-WebRequest http://127.0.0.1:3000/docs
Invoke-RestMethod http://127.0.0.1:3000/health

Verificaciones seguras

npm run db:check
npm run sii:preflight
npm run sii:check-connectivity
npm run sii:full-test
npm run sii:preview-package
npm run sii:preview-simulation -- --after-package=./tmp/certification-preview-2026-08-26
npm run sii:prepare-samples -- --path=./tmp/certification-preview-2026-08-26 --simulation=./tmp/certification-simulation-preview-2026-08-26/SIM-20260826-TITA

db:check verifica MongoDB e índices. sii:preflight valida persistencia, configuración, PFX y CAF sin conectarse al SII. sii:check-connectivity solicita semilla/token, pero no envía DTE ni consume folios. Ningún comando realiza upload automáticamente.

En la EC2 se usa exclusivamente /opt/soytita-facturacion/.env con permiso 0600. El despliegue falla si ese archivo real no existe y nunca copia .env.example como configuración del servidor.

La documentación queda en GET /docs y los mismos catálogos, en formato JSON, están disponibles en GET /v1/meta.

Endpoints disponibles

Dominios: toda la API se consume exclusivamente desde https://api.soytita.cl. Los objetos privados no se exponen desde la API ni desde S3: después de comprobar tenant y propiedad, la API entrega enlaces temporales de https://documentos.soytita.cl firmados por CloudFront.

Autenticación: las rutas /v1/* requieren Authorization: Bearer <api-key> o X-API-Key. La clave se guarda sólo como hash SHA-256 en Secrets Manager y determina el tenant; no confíe en un X-Tenant-Id suministrado por el cliente.

Método Ruta Uso
GET /health Salud del proceso local.
POST /v1/sii/send/:id Encola un DTE listo; responde error mientras la compuerta de upload esté cerrada.
GET /v1/sii/envios/:trackId Devuelve TrackID, estado y fecha persistidos para el mismo tenant.
GET /v1/inbound, /v1/inbound/:id Lista DTE recibidos por correo sin exponer el XML dentro del JSON.
GET /v1/inbound/:id/xml, /v1/inbound/:id/pdf Entrega JSON con una Signed URL temporal de documentos.soytita.cl.
GET /docs Este documento HTML.
GET /v1/meta Endpoints, tipos DTE, mapeo, estado y errores en JSON.
GET /v1/meta/data-map, /v1/meta/errors, /v1/meta/sii-codes Mapas de datos, taxonomía de errores y códigos originales SII.
POST /v1/certification/generate-dte Genera DTE 33, 34, 52, 56 o 61.
POST /v1/certification/generate-dte33 Alias compatible para DTE 33.
POST /v1/certification/generate-set Encola el set básico o exento completo y responde 202.
GET /v1/certification/receivers Lista perfiles de receptores persistidos en MongoDB.
POST /v1/certification/receivers Valida con Zod y guarda o actualiza un receptor.
POST /v1/certification/generate-books Encola IECV de ventas 5037510 y compras 5037511.
POST /v1/certification/generate-simulation Encola un sobre representativo con 10–100 DTE sin referencias SET/CASO.
GET /v1/certification/jobs/:id Consulta estado y resultado del trabajo asíncrono.
GET /v1/certification/jobs/:id/artifacts Entrega Signed URLs de CloudFront para todos sus XML y PDF.
POST /v1/certification/auth Prueba semilla y token de certificación.
POST /v1/certification/send-dte/:id Envía explícitamente un DTE individual ya generado.
POST /v1/certification/send-set/:attentionNumber Envía al SII un set ya generado.
POST /v1/certification/send-book/:attentionNumber Envía el IECV 5037510 o 5037511 ya generado.
POST /v1/certification/send-simulation/:simulationId Envía explícitamente una simulación ya generada.
GET /v1/certification/envios/:trackId Consulta estado del upload.
GET /v1/certification/dte-status Consulta estado tributario individual.
GET /v1/certification/reconciliation Cuadra informados, aceptados, rechazados y reparos por TrackID.
POST /v1/dte/factura Encola la factura 33 y responde 202 Accepted.
POST /v1/dte/factura-exenta Genera factura exenta 34.
POST /v1/dte/guia-despacho Genera guía de despacho 52.
POST /v1/dte/nota-debito Genera nota de débito 56.
POST /v1/dte/nota-credito Genera nota de crédito 61.
GET /v1/dte, /:id, /:id/status, /:id/xml, /:id/pdf, /:id/cedible.pdf Lista, consulta estados y responde JSON con Signed URLs breves de documentos.soytita.cl para XML/PDF del mismo tenant; no redirige ni transmite el objeto desde la API.
POST /v1/caf Importa CAF XML.
GET /v1/caf, /v1/caf/folios Inventario y disponibilidad de folios.
POST /v1/intercambio/recepcion Recibe EnvioDTE y genera RespuestaDTE.
POST /v1/intercambio/acuse Genera aceptación, discrepancia o rechazo comercial.
POST /v1/intercambio/recibo-mercaderias Genera EnvioRecibos Ley 19.983.
GET /v1/intercambio/respuestas/:id/*.xml Descarga RespuestaDTE, resultado comercial o EnvioRecibos.

Evidencia del upload: sets, libros y simulaciones guardan numeroEnvio con el Track ID exacto del SII, fechaEnvio en dd-mm-aaaa usando la hora de Chile, la marca ISO uploadedAt y la respuesta XML original.

Contrato JSON para generar un DTE

Ejemplo para POST /v1/dte/factura. La ruta fija automáticamente tipoDte: 33. Todas las operaciones que generan, importan, envían o producen acuses requieren el encabezado Idempotency-Key.

Idempotency-Key: factura-cliente-20260826-0001
{
  "folio": 1,
  "invoice": {
    "fechaEmision": "2026-08-26",
    "formaPago": 2,
    "receptor": {
      "rut": "<RUT_REAL_CLIENTE>",
      "razonSocial": "<RAZON_SOCIAL_REAL>",
      "giro": "<GIRO_REAL>",
      "direccion": "<DIRECCION_REAL>",
      "comuna": "<COMUNA_REAL>",
      "ciudad": "<CIUDAD_REAL>"
    },
    "items": [
      {
        "nombre": "SERVICIO DE PRUEBA",
        "cantidad": 1,
        "precioUnitario": 10000,
        "exento": false
      }
    ],
    "descuentosRecargosGlobales": [],
    "referencias": []
  }
}

Campos adicionales para Guía de Despacho 52

"invoice": {
  "tipoDte": 52,
  "indicadorTraslado": 1,
  "tipoDespacho": 2,
  "origen": {
    "direccion": "13 NORTE 853 871, DEPTO. 803",
    "comuna": "VIÑA DEL MAR"
  },
  "items": [{
    "nombre": "EQUIPO", "cantidad": 1,
    "unidadMedida": "UN", "precioUnitario": 10000
  }],
  "transporte": {
    "patente": "ABCD12",
    "rutTransportista": "<RUT_VALIDO>",
    "chofer": { "rut": "<RUT_VALIDO>", "nombre": "NOMBRE COMPLETO" },
    "destino": { "direccion": "DESTINO REAL", "comuna": "COMUNA" },
    "fechaSalida": "2026-08-26",
    "horaSalida": "15:30:00",
    "fechaLlegada": "2026-08-26"
  }
}

Reglas que Zod aplica antes de generar

Contratos del set y libros

Generar set asignado

POST /v1/certification/generate-set
Idempotency-Key: set-basico-5037509-v1

{
  "setName": "setBasico",
  "issueDate": "2026-08-26",
  "receiver": { "...receptor real caso 5037509-1..." },
  "folios": {
    "5037509-1": 1, "5037509-2": 2,
    "5037509-3": 3, "5037509-4": 4,
    "5037509-5": 1, "5037509-6": 2,
    "5037509-7": 3, "5037509-8": 1
  },
  "caseOverrides": {
    "5037509-2": { "receptor": { "...cliente real distinto..." } },
    "5037509-3": { "receptor": { "...cliente real distinto..." } },
    "5037509-4": { "receptor": { "...cliente real distinto..." } }
  }
}

Los objetos abreviados con puntos deben reemplazarse por el contrato completo de receptor; no son JSON ejecutable. Los importes, ítems y referencias del set ya están normalizados desde los archivos asignados por el SII.

Generar libros IECV

POST /v1/certification/generate-books
Idempotency-Key: libros-202608-v1

{
  "salesSetAttentionNumber": 5037509,
  "purchaseIssueDate": "2026-08-26",
  "purchaseSupplier": {
    "rut": "<RUT_REAL_PROVEEDOR>",
    "razonSocial": "<RAZON_SOCIAL_REAL>"
  }
}

Generar simulación

POST /v1/certification/generate-simulation recibe un simulationId, una lista de tipos requeridos y entre 10 y 100 objetos con el mismo contrato de generación DTE. Zod exige folios únicos por tipo, presencia de todos los tipos requeridos y prohíbe referencias SET/CASO.

npm run sii:preview-simulation -- --date=2026-08-26 --id=SIM-20260826-TITA --after-package=./tmp/certification-preview-2026-08-26

El comando produce una plantilla técnica: antes del envío, confirme que clientes, conceptos y montos correspondan a operaciones representativas. El preview no reserva folios ni realiza upload.

Mapeo de datos: API → XML SII

El catálogo completo también es consultable en GET /v1/meta/data-map.

Campo API/configuración Tipo Destino XML Regla
folio entero positivo Encabezado/IdDoc/Folio Dentro del CAF del mismo tipo.
invoice.tipoDte 33 | 34 | 52 | 56 | 61 Encabezado/IdDoc/TipoDTE Automático en rutas tipadas.
invoice.fechaEmision fecha ISO Encabezado/IdDoc/FchEmis Fecha real YYYY-MM-DD.
invoice.formaPago 1 | 2 | 3 Encabezado/IdDoc/FmaPago Por defecto 2.
invoice.indicadorTraslado 1..9 Encabezado/IdDoc/IndTraslado Obligatorio sólo para Guía 52.
invoice.origen dirección/comuna/ciudad Emisor/DirOrigen|CmnaOrigen|CiudadOrigen Reemplaza el domicilio cuando el origen efectivo es otro.
invoice.transporte objeto de transporte Encabezado/Transporte Patente, transportista, chofer, destino, salida y llegada estimada.
company.rut RUT Encabezado/Emisor/RUTEmisor Debe coincidir con CAF y postulante.
company.razon_social texto 1..100 Encabezado/Emisor/RznSoc Dato de empresa configurado.
company.giro texto 1..80 Encabezado/Emisor/GiroEmis Giro registrado.
company.actividad_economica 5..6 dígitos Encabezado/Emisor/Acteco ACTECO vigente.
company.direccion/comuna/ciudad texto DirOrigen/CmnaOrigen/CiudadOrigen Domicilio del emisor.
invoice.receptor.rut RUT Encabezado/Receptor/RUTRecep Dígito verificador válido.
invoice.receptor.razonSocial texto 1..100 Receptor/RznSocRecep Obligatorio.
invoice.receptor.giro texto 1..40 Receptor/GiroRecep Obligatorio.
invoice.receptor.direccion/comuna/ciudad texto DirRecep/CmnaRecep/CiudadRecep Obligatorios.
invoice.items[].nombre texto 1..80 Detalle/NmbItem Exacto al set durante certificación.
invoice.items[].descripcion texto 0..1000 Detalle/DscItem Opcional.
cantidad + precioUnitario decimales QtyItem/PrcItem Requeridos si no hay montoItem.
invoice.items[].montoItem monto ≥ 0 Detalle/MontoItem Alternativa al cálculo cantidad × precio.
invoice.items[].exento boolean Detalle/IndExe Siempre true para DTE 34.
descuentoPct/descuentoMonto 0..100 / monto DescuentoPct/DescuentoMonto Son mutuamente excluyentes.
recargoPct/recargoMonto 0..100 / monto RecargoPct/RecargoMonto Son mutuamente excluyentes.
descuentosRecargosGlobales[] D|R y %|$ Documento/DscRcgGlobal Máximo 20.
invoice.referencias[] objeto Documento/Referencia Requerido para notas.
referencias[].tipoDocumento SET o código DTE Referencia/TpoDocRef SET se agrega al generar sets.
referencias[].folio/fecha texto / fecha FolioRef/FchRef Identifican el documento referido.
referencias[].codigoReferencia/razon 1..3 / texto CodRef/RazonRef Razón máximo 90 caracteres.
company.fecha_resolucion fecha ISO SetDTE/Caratula/FchResol Desde configuración local.
company.numero_resolucion entero ≥ 0 SetDTE/Caratula/NroResol Desde configuración local.
company.senderRut RUT SetDTE/Caratula/RutEnvia Firmante autorizado; por defecto emisor.

Set de certificación, libros e intercambio

Campo API Tipo Zod Destino/uso Regla principal
setName setBasico | setFacturaExenta Selecciona 5037509 o 5037512 Determina los ocho casos y tipos DTE esperados.
issueDate fecha real YYYY-MM-DD DTE/.../FchEmis y referencias Se aplica a todos los casos del set.
caseOverrides.<caso>.receptor objeto receptor DTE/.../Receptor Distinto por factura; las notas heredan el referenciado.
folios.<caso> entero positivo DTE/.../Folio Ocho claves exactas, CAF correcto y sin reutilización.
salesSetAttentionNumber 5037509 | 5037512 Fuente del libro VENTA Debe existir el set generado; se prioriza el básico.
purchaseIssueDate fecha real YYYY-MM-DD PeriodoTributario y Detalle/FchDoc El período IECV se deriva como YYYY-MM.
purchaseSupplier.rut RUT LibroCompraVenta/Detalle/RUTDoc Proveedor real de los casos de compra.
envelopeXml XML ≤ 10 MiB EnvioDTE entrante ISO-8859-1/UTF-8, sin DTD, con firma/XSD/RUT verificados.
decisions[].status ACCEPTED | ACCEPTED_WITH_DISCREPANCY | REJECTED ResultadoDTE/EstadoDTE Mapea a 0/1/2; discrepancia o rechazo exige glosa.
venue / signerRut texto / RUT Recibo/Recinto / RutFirma Acuse material Ley 19.983.
Idempotency-Key header 8..128 No se serializa Evita doble folio y doble upload; conflicto devuelve HTTP 409.

Códigos originales y estados normalizados del SII

La API conserva siempre originalStatus, glosa y XML exacto, y agrega un estado normalizado para automatización. El catálogo JSON está en GET /v1/meta/sii-codes.

Servicio Códigos SII Estado normalizado
Recepción upload 0 RECEIVED
Recepción upload 1, 2, 3, 5, 6, 7, 8, 9 Rechazo tipificado; conserva respuesta exacta
Consulta envío EPR ACCEPTED, ACCEPTED_WITH_OBJECTIONS o REJECTED según contadores
Consulta envío RSC, RFR, RCT REJECTED
Consulta envío SOK, CRT, FOK, PDR, PRD PROCESSING
Consulta DTE DOK ACCEPTED
Consulta DTE DNK, FAU, FNA, FAN, EMP Datos distintos, no recibido, no autorizado, anulado o empresa no autorizada
Consulta DTE TMD, TMC, MMD, MMC, AND, ANC Modificado o anulado por nota relacionada
Autenticación/consultas 001, 002, 003 AUTHENTICATION_ERROR/EXPIRED

Las respuestas SOAP/upload se guardan sin normalizar junto a SHA-256 e historial. Después de firmar un XML nunca se vuelve a formatear ni modificar.

Contrato y catálogo de errores

Toda ruta devuelve el mismo formato. details contiene los problemas de Zod y requestId permite ubicar el evento en los logs.

{
  "code": "VALIDATION_ERROR",
  "type": "REQUEST_VALIDATION",
  "message": "Los datos enviados no cumplen el contrato de la API",
  "retryable": false,
  "action": "Corrija los campos informados en details y vuelva a enviar la solicitud.",
  "details": [
    { "field": "invoice.receptor.rut", "rule": "custom", "message": "El RUT y su dígito verificador no son válidos" }
  ],
  "requestId": "1df08b85-39cc-45a5-9f91-d13939a64ed9"
}

Tipos de error

REQUEST_VALIDATION y CONFIGURATION se corrigen antes de ejecutar; BUSINESS_RULE, CERTIFICATION_RULE, CAF y CONFLICT protegen las reglas tributarias y la unicidad; DATABASE clasifica fallas de persistencia; CERTIFICATE, XML_VALIDATION y SIGNATURE impiden producir artefactos no verificables; SII_AUTHENTICATION, SII_COMMUNICATION y SII_REJECTION representan respuestas o incertidumbre externa. INTERNAL nunca expone detalles sensibles.

Código Tipo HTTP Reintentar Significado
VALIDATION_ERROR REQUEST_VALIDATION 422 No Campos o reglas Zod inválidos.
INVALID_JSON REQUEST_VALIDATION 400 No JSON mal formado.
PAYLOAD_TOO_LARGE REQUEST_VALIDATION 413 No Cuerpo superior al límite.
RATE_LIMIT_EXCEEDED RATE_LIMIT 429 Más de 30 solicitudes por minuto.
ROUTE_NOT_FOUND NOT_FOUND 404 No Ruta inexistente.
DTE_NOT_FOUND NOT_FOUND 404 No Artefacto DTE inexistente.
CERTIFICATION_JOB_NOT_FOUND NOT_FOUND 404 No Trabajo asíncrono de certificación inexistente o de otro tenant.
CERTIFICATION_SET_NOT_FOUND NOT_FOUND 404 No Set no generado.
CERTIFICATION_BOOK_NOT_FOUND NOT_FOUND 404 No IECV 5037510/5037511 no generado.
CERTIFICATION_SIMULATION_NOT_FOUND NOT_FOUND 404 No Simulación no generada.
EXCHANGE_RESPONSE_NOT_FOUND NOT_FOUND 404 No Recepción o RespuestaDTE inexistente.
EXCHANGE_RESULT_NOT_FOUND NOT_FOUND 404 No Resultado comercial inexistente.
GOODS_RECEIPT_NOT_FOUND NOT_FOUND 404 No Recibo de mercaderías inexistente.
TEST_FILES_NOT_CONFIGURED CONFIGURATION 503 No Falta empresa, CAF o PFX local.
CONFIG_FILE_INVALID CONFIGURATION 503 No JSON de empresa inválido.
DATABASE_NOT_CONFIGURED DATABASE 503 No Falta configurar la conexión MongoDB.
DATABASE_UNAVAILABLE DATABASE 503 MongoDB no respondió o rechazó la operación.
ASYNC_JOBS_NOT_CONFIGURED CONFIGURATION 503 No Falta configurar MongoDB, S3, CloudFront o alguna de las cinco colas SQS.
QUEUE_PUBLISH_FAILED INTERNAL 503 No fue posible publicar el trabajo; reintente con la misma Idempotency-Key.
TENANT_NOT_FOUND CONFIGURATION 404 No El tenant indicado en X-Tenant-Id no está configurado.
AUTHENTICATION_REQUIRED AUTHENTICATION 401 No Falta Authorization Bearer o X-API-Key.
AUTHENTICATION_INVALID AUTHENTICATION 403 No La API key no existe, está deshabilitada o no coincide.
TENANT_MISMATCH AUTHORIZATION 403 No La credencial pertenece a otro tenant.
WORKFLOW_CONFLICT CONFLICT 409 Otro worker ya cambió el estado; consulte el DTE antes de reintentar.
ARTIFACT_NOT_READY CONFLICT 409 El XML o PDF todavía está siendo procesado por un worker.
SII_UPLOAD_STATE_UNCERTAIN SII_COMMUNICATION 409 No El worker no reenvía automáticamente cuando un upload pudo alcanzar al SII.
SII_UPLOAD_DISABLED CONFIGURATION 409 No El upload permanece cerrado hasta validar el ambiente y autorizar el envío.
SII_STATUS_POLLING_EXHAUSTED SII_COMMUNICATION 504 No Se agotó el seguimiento automático; el TrackID debe revisarse manualmente.
INVALID_DTE BUSINESS_RULE 422 No Regla tributaria incumplida.
TED_ENCODING_INVALID BUSINESS_RULE 422 No El TED contiene caracteres que no se pueden representar en ISO-8859-1.
PDF417_LAYOUT_INVALID BUSINESS_RULE 422 No El timbre PDF417 queda fuera de las dimensiones físicas exigidas.
UNSUPPORTED_DTE_TYPE BUSINESS_RULE 422 No Tipo no implementado.
CERTIFICATION_RECEIVER_REQUIRED CERTIFICATION_RULE 422 No Falta cliente real para una factura del set.
CERTIFICATION_RECEIVER_DUPLICATE CERTIFICATION_RULE 422 No Dos facturas 33/34 usan el mismo RUT receptor.
CERTIFICATION_REFERENCE_RECEIVER_MISMATCH CERTIFICATION_RULE 422 No Una nota cambió el receptor del DTE referenciado.
FOLIO_OUTSIDE_CAF CAF 422 No Folio fuera del rango autorizado.
INVALID_CAF CAF 422 No CAF inválido o corrupto.
CAF_COMPANY_MISMATCH CAF 422 No CAF de otro emisor.
CAF_ALREADY_IMPORTED CONFLICT 409 No CAF duplicado.
CAF_RANGE_OVERLAP CAF 409 No Rango CAF superpuesto para el mismo emisor y tipo.
CAF_NOT_YET_VALID CAF 422 No La emisión es anterior a la autorización del CAF.
CAF_EXPIRED CAF 422 No El CAF está vencido para la fecha de emisión.
NO_FOLIOS_AVAILABLE CONFLICT 409 No CAF agotado.
TEST_FOLIO_ALREADY_USED CONFLICT 409 No Folio reservado localmente.
IDEMPOTENCY_CONFLICT CONFLICT 409 No Conflicto con solicitud previa.
IDEMPOTENCY_KEY_REQUIRED REQUEST_VALIDATION 400 No Falta una clave válida de 8–128 caracteres.
IDEMPOTENCY_IN_PROGRESS CONFLICT 409 Sí, después La misma operación aún está en curso.
IDEMPOTENCY_PREVIOUS_FAILURE CONFLICT 409 No Un upload previo con esa clave terminó con error retenido.
CERTIFICATE_EXPIRED CERTIFICATE 422 No Certificado fuera de vigencia.
CERTIFICATE_PASSWORD_ERROR CERTIFICATE 422 No PFX o contraseña inválidos.
CERTIFICATE_SIGNER_MISMATCH CERTIFICATE 422 No RutEnvia configurado no coincide con el titular del PFX.
XSD_VALIDATION_ERROR XML_VALIDATION 422 No XML no cumple esquema oficial.
SIGNATURE_VERIFICATION_ERROR SIGNATURE 500 No Firma recién generada no verificable.
SII_TIMEOUT SII_COMMUNICATION 504 Sí* Timeout; consultar estado antes de reenviar.
SII_AUTHENTICATION_ERROR SII_AUTHENTICATION 502 Fallo de semilla, token o autorización.
SII_TRANSPORT_ERROR SII_COMMUNICATION 502 Sí* Fallo de comunicación; comprobar estado.
SII_UPLOAD_REJECTED SII_REJECTION 502 Según código El SII rechazó explícitamente el sobre; conserva respuesta exacta.
INTERNAL_ERROR INTERNAL 500 No Error no previsto; revisar por requestId.

Etapas externas restantes

La implementación local está preparada, pero faltan cinco etapas que requieren envío o aprobación del SII. El registro final como emisor ocurre después de completarlas.

  1. Enviar y obtener aceptación sin rechazos ni reparos de los sets 5037509/5037512 y sus libros 5037510/5037511.
  2. Enviar y aprobar una simulación de 10 a 100 DTE representativos. Consulte cada TrackID hasta estado terminal y revise GET /v1/certification/reconciliation.
  3. Ejecutar y aprobar el intercambio con los XML asignados por el SII; antes se debe comprobar la recepción real de dte@soytita.cl en S3 y el canal de respuesta.
  4. Ejecute npm run sii:prepare-samples. El preparador incluye todos los PDF de 5037509/5037512, una muestra por tipo de simulación, cedibles 33/34, una página por PDF, máximo 500 KB y lotes locales de hasta 20; la carga al portal es manual.
  5. Complete los controles organizacionales y presente la declaración de cumplimiento. No declare mientras existan respaldos, responsables o aprobaciones pendientes.

En todos los envíos la igualdad esperada es INFORMADOS = ACEPTADOS + RECHAZADOS + REPAROS. Producción debe permanecer deshabilitada hasta que el SII registre formalmente el RUT como emisor electrónico.

El preview verificado contiene 29 muestras: 23 provenientes de los dos sets asignados y 6 seleccionadas de la simulación (tributarias 33/34/56/61 más cedibles 33/34). Mientras use la plantilla técnica queda marcado TECHNICAL_PREVIEW_NOT_FOR_UPLOAD.

Respaldo y restauración MongoDB

Detenga la API antes de respaldar. mongodump --archive --gzip se cifra directamente con AES-256-GCM y una clave derivada con scrypt. El manifiesto conserva hashes SHA-256 y conteos, sin URI ni credenciales.

# Cargar SII_BACKUP_PASSPHRASE sin escribirla en el historial
$secure = Read-Host 'Frase de respaldo' -AsSecureString
$env:SII_BACKUP_PASSPHRASE = [Net.NetworkCredential]::new('', $secure).Password

npm run db:backup -- --confirm-api-stopped
npm run db:backup:verify -- --backup=.\backups\<archivo>.archive.gz.enc
npm run db:backup:test-restore -- --backup=.\backups\<archivo>.archive.gz.enc

La verificación autentica el archivo antes de entregarlo a mongorestore y ejecuta un dryRun. La prueba real usa únicamente colecciones con prefijo aleatorio __sii_restore_test_*__, compara sus conteos y las elimina al finalizar. El procedimiento completo está en BACKUP_RUNBOOK.md.

El 26-08-2026 se aprobó una ejecución técnica real: ocho colecciones restauradas con conteos idénticos, dryRun correcto y cero colecciones temporales remanentes. Consulte BACKUP_VALIDATION_2026-08-26.md.

El respaldo local no completa por sí solo la declaración: respaldo y manifiesto deben copiarse fuera del host, la contraseña debe custodiarse por separado y el ejercicio de restauración debe quedar registrado.

Archivos y variables requeridos

Archivo real de la EC2

NODE_ENV=production
HOST=127.0.0.1
PORT=3200
SII_ENVIRONMENT=certification
SII_PRODUCTION_ENABLED=false
SII_UPLOAD_ENABLED=false
ASYNC_JOBS_ENABLED=true
API_AUTH_REQUIRED=true
API_KEY_SECRET_ARN=arn:aws:secretsmanager:...
PUBLIC_API_BASE_URL=https://api.soytita.cl
AWS_REGION=us-east-1
DTE_ARTIFACT_BUCKET=soytita-dte-artifacts-...
DTE_ARTIFACT_KMS_KEY_ARN=arn:aws:kms:...
TENANT_CERTIFICATE_SECRET_ARN=arn:aws:secretsmanager:...
TENANT_SIGNER_RUT=<RUT_FIRMANTE>
SQS_DTE_GENERATE_URL=https://sqs.../tita-dte-generate
SQS_DTE_SEND_SII_URL=https://sqs.../tita-dte-send-sii
SQS_DTE_STATUS_URL=https://sqs.../tita-dte-status
SQS_DTE_PDF_URL=https://sqs.../tita-dte-pdf
SQS_DTE_EMAIL_INBOUND_URL=https://sqs.../tita-dte-email-inbound
CLOUDFRONT_DOMAIN=documentos.soytita.cl
CLOUDFRONT_KEY_PAIR_ID=<PUBLIC_KEY_ID>
CLOUDFRONT_PRIVATE_KEY_SECRET_ARN=arn:aws:secretsmanager:...
MONGODB_URI=<URI_PRIVADA>
MONGODB_DATABASE=SOYTITA

Las variables SII_TEST_*_PATH pertenecen sólo a herramientas locales de certificación y carga inicial. En ejecución asíncrona, el PFX se obtiene desde Secrets Manager y los CAF desde el bucket S3 privado por referencia/versionId.

No subir secretos: CAF, PFX/P12, contraseña, tokens y datos privados deben permanecer fuera de Git. La API no acepta el PFX ni su contraseña en el cuerpo HTTP.

Operación AWS: la EC2 usa el rol runtime SOYTITA-Facturador-EC2 y asume SOYTITA-Infrastructure-Deployment sólo para cambios de infraestructura. No se guardan access keys estáticas en ~/.aws/credentials ni en el .env del servidor.

La API escucha sólo en 127.0.0.1 por defecto. No configure HOST=0.0.0.0 sin autenticación, HTTPS y controles de red.

Estado de datos para TITA

No se usa Docker, PostgreSQL, Redis ni SimpleAPI. MongoDB conserva perfiles, idempotencia, folios, manifiestos y respuestas SII. En la EC2, XML/PDF/CAF se guardan cifrados en S3 y el PFX/contraseña en Secrets Manager; las copias locales son sólo material de bootstrap y revisión, siempre fuera de Git.

Fuentes oficiales SII usadas

Las copias descargadas, sus hashes y la fecha de descarga están en docs/sii/manifest.json y docs/sii/FUENTES.md.