Qué tenemos hoy
Node.js + TypeScript
Aplicación, scripts, pruebas y Vitest migrados; typecheck, build, 162 pruebas y servidor compilado validados.
DTE
Factura 33, factura exenta 34, guía de despacho 52, nota de débito 56 y nota de crédito 61.
Artefactos
XML, TED, firma electrónica, XSD, EnvioDTE, PDF417 en modo byte y PDF tributario/cedible.
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.
CAF
Importación, validación de emisor, inventario y reserva atómica de folios en MongoDB.
Set SII
Sets 5037509 y 5037512, receptores distintos, referencias SET/CASO y herencia de receptor en notas.
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.
Libros e intercambio
IECV ventas 5037510, compras 5037511, RespuestaDTE, resultado comercial y recibo Ley 19.983.
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.
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.
Antes del upload
Confirmar permisos del firmante, comprobar la casilla de intercambio y revisar los artefactos antes de enviarlos.
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 |
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
-
Validar
Zod normaliza RUT, fechas, números y reglas condicionales. -
Construir
Se calculan neto, exento, IVA, descuentos, recargos y total. -
Firmar
CAF firma el TED y el certificado firma DTE y sobre. -
Verificar
Se verifican firmas y XSD antes de persistir artefactos en MongoDB. -
Revisar
Se inspeccionan XML, PDF y manifiestos generados. -
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
- Objetos estrictos: los campos desconocidos se rechazan.
- RUT con dígito verificador válido y formato normalizado.
- Fechas reales en formato
YYYY-MM-DD. - Folios enteros positivos y tipos DTE limitados a
33|34|52|56|61. - La Guía 52 exige traslado, cantidad/unidad, vehículo, transportista, chofer, destino, salida y llegada estimada; el set asignado a TITA continúa usando 33/34/56/61.
- Ítems con
montoItemo concantidad + precioUnitario. - No permite informar simultáneamente descuento porcentual y descuento en monto; lo mismo para recargos.
- Todos los ítems de un DTE 34 deben tener
exento: true. - Las notas 56 y 61 deben incluir al menos una referencia.
- El set exige exactamente sus ocho folios; rechaza casos ajenos, faltantes y folios repetidos por tipo DTE.
- Cada factura 33/34 del set usa un receptor distinto; las notas deben conservar el RUT del documento referenciado.
- Decisiones comerciales y recibos rechazan identificadores DTE repetidos.
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 | Sí | 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 | Sí | 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 | Sí | 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 | Sí | Otro worker ya cambió el estado; consulte el DTE antes de reintentar. |
ARTIFACT_NOT_READY |
CONFLICT | 409 | Sí | 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 | Sí | 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.
- Enviar y obtener aceptación sin rechazos ni reparos de los sets 5037509/5037512 y sus libros 5037510/5037511.
-
Enviar y aprobar una simulación de 10 a 100 DTE representativos. Consulte cada TrackID
hasta estado terminal y revise
GET /v1/certification/reconciliation. -
Ejecutar y aprobar el intercambio con los XML asignados por el SII; antes se debe
comprobar la recepción real de
dte@soytita.clen S3 y el canal de respuesta. -
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. - 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
-
Migración TypeScript completa: 179 fuentes
.ts, cero fuentes.jsen aplicación, scripts y tests; compilación y ejecución dedist/server.jscomprobadas. - PFX y contraseña: configurados, llave coherente y vigencia comprobada.
- RutEnvia confirmado:
15.805.965-7. - CAF 33, 34, 56 y 61: configurados, emisor correcto y folios 1–50.
- CAF 52: no configurado; sólo se necesita si se decide probar Guía de Despacho.
- TED/CAF preservan ISO-8859-1 y el PDF417 usa compactación byte, nivel de corrección 5, proporción 3:1, zona muda mínima de 0,25 pulgadas y dimensiones físicas SII.
- Semilla/token del ambiente de certificación: comprobados correctamente.
-
Confirmados en el portal SII:
FchResol=2026-08-26,NroResol=0, UnidadVIÑA DEL MAR, actividad 620900, software SOYTITA y Mail Contacto Empresasdte@soytita.cl. - Datos de contraparte completos: cuatro receptores para 5037509; DATCAPITAL, RUTTY MUÑOZ y HAPPY ME reutilizados en 5037512; DATCAPITAL como proveedor para 5037511.
-
El MX de
soytita.clapunta a SES entrante enus-east-1; la entrega SES→S3→SQS usa la cola finaltita-dte-email-inbound; el worker está desplegado y el procesamiento XML→MongoDB/S3→PDF está cubierto por integración. Falta la última comprobación operativa con un nuevo correo XML recibido desde fuera de AWS. -
Validación EC2 del 26-08-2026: factura 33 DATCAPITAL, folio 2, terminó
READY_TO_SENDy PDFREADY. XML, PDF tributario y cedible respondieron 200 mediantedocumentos.soytita.cl; el acceso sin firma fue rechazado con 403. No se generó TrackID y la cola de envío SII quedó vacía.
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
- Proceso de certificación
- Formato DTE vigente, versión 2.5
- Resolución Exenta SII N° 154/2025 sobre traslado de bienes
- Instructivo técnico de emisión
- Instrucciones del set de pruebas
- Manual de muestras impresas
- Esquemas XML oficiales
Las copias descargadas, sus hashes y la fecha de descarga están en
docs/sii/manifest.json y docs/sii/FUENTES.md.