Saltar al contenido
dte-sdk

API del portal (dte-sdk/portal)

El portal del SII autenticado con certificado: sesión, datos de la empresa, solicitudes de folios y CAF, el registro de compras y ventas, el respaldo MIPYME y la verificación de actividades; además de los sets de certificación y el runner de certificación. Corre solo en Node, porque fetch no puede presentar un certificado cliente.

TypeScript
import { createPortalClient, openPortalSession, queryFolioQuota } from 'dte-sdk/portal'

Lo que ya se probó contra el portal real: en producción, el 9 y el 10 de noviembre de 2026, el login con certificado y la sesión reutilizada entre lecturas, con una empresa no inscrita como emisor, y las lecturas del registro de compras y ventas (fetchRegisterSummary, listPeriodDocuments, fetchPurchaseDocument, listPurchaseTypes) con las filas de una factura recibida; en ejecuciones anteriores cuyo ambiente no quedó anotado, login, logout, datos del contribuyente y las páginas de rechazo, con una empresa no inscrita como emisor, y las solicitudes de solo lectura del registro con una empresa sin documentos. Las páginas de folios y CAF de una empresa inscrita aún no se han visto, porque necesitan una, y tampoco las escrituras del registro ni las descargas del respaldo MIPYME. La verificación de actividades se leyó para una verificación pendiente y, el 9 de noviembre, para una condicionada, pendiente de acreditación; una aprobada aún no se ha visto, así que su lectura sigue inestable. La certificación (sets, runner, intercambio, subida de las muestras) y la certificación de boletas aún no se han ejecutado. Todo está probado con respuestas sintéticas. Ver Estado.

Los grupos siguientes siguen las guías: Portal, Registro, Sets de pruebas, Runner, Intercambio y muestras y Boletas. Las funciones del portal reciben un PortalClient primero y un CallOverrides al final; los pasos de la certificación reciben un CertificationDependencies y un CertificationState.

Catálogos y rechazos#

El portal informa un rechazo como un DteError con código SII_PORTAL_REJECTED y details.rejection, uno de los valores de PortalRejection. PORTAL_REJECTIONS y portalRejectionMessage dan el texto en español para el operador. Los flujos compuestos devuelven los rechazos como datos en vez de lanzar. Guía: Portal.

TypeScript
// Qué significa cada rechazo y qué hacer, en español, para el operador.
const PORTAL_REJECTIONS: Readonly<Record<PortalRejection, string>>
 
// El mensaje en español de un rechazo.
function portalRejectionMessage(rejection: PortalRejection): string
TipoDescripción
AccountingStatusEstado contable de un documento en el registro. Definido como 'registered' | 'pending' | 'notIncluded' | 'claimed'. Cuáles puede tener cada lado está en REGISTER_ACCOUNTING_STATUSES.
DocumentDirectionEn qué lado de un documento está el contribuyente. Definido como 'issued' | 'received'.
PortalRejectionPor qué el SII rechazó una solicitud del portal.
RegisterOperationQué libro del registro. Definido como 'purchase' | 'sale'.

Cliente, candado y sesión#

createPortalClient devuelve un cliente congelado; las operaciones del portal son funciones libres que lo reciben primero y aceptan un CallOverrides final (signal, timeoutMs, retry). El portal corre solo en Node, porque fetch no puede presentar un certificado cliente: el transporte por defecto es node:https con el certificado y la verificación TLS activada. El certificado debe estar habilitado como método de ingreso en sii.cl, o el login lanza SII_PORTAL_CERT_NOT_ENABLED. Las sesiones se abren a pedido; openPortalSession y closePortalSession lo hacen de forma explícita. sessionCache y lock son puertos para despliegues con varias réplicas. Guía: Portal.

Cliente#

TypeScript
// Valida y completa las opciones en un `PortalClient` congelado.
function createPortalClient(options: PortalClientOptions): PortalClient
 
// Política de reintentos del portal: 4 intentos a los 2, 4 y 8 s, sin jitter, repitiendo lo que
// acepta `isRetryablePortalError`.
const DEFAULT_PORTAL_RETRY_POLICY: RetryPolicy
 
// True para lo que conviene repetir en el portal: fallas de transporte, timeouts, HTTP
// 502/503/504, y las fallas TLS que el SII produce de forma intermitente con certificado cliente
// (`EPROTO … rsa_pss`), que no indican un certificado malo.
function isRetryablePortalError(error: unknown): boolean
TipoDescripción
PortalClientEl cliente del portal: datos planos congelados, con todos los campos resueltos. Se pasa a las funciones del portal.
PortalClientOptionsOpciones de createPortalClient.

Campos de PortalClientOptions

CampoTipoDescripción
environmentEnvironmentAmbiente: elige maullin o palena para las páginas CGI.
certificateCertificateCertificado que se presenta al iniciar sesión; su titular es el usuario del portal.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa, salvo que la llamada indique otro.
transport?HttpTransportTransporte HTTP; por defecto https de Node con el certificado cliente y tope TLS 1.2.
sessionCache?TokenCacheDónde vive la sesión; en memoria por defecto. createDirectoryTokenCache({ dir }) de dte-sdk/node la guarda en disco, un archivo por certificado que solo puede leer su dueño.
sessionTtlMs?numberVigencia de la sesión en la caché; 90 min por defecto, renovada en cada uso.
lock?PortalLockQuién puede usar la sesión ahora; por defecto una exclusión mutua en el proceso, que solo vale dentro de un proceso: los procesos que comparten una sesión en disco necesitan un candado compartido.
retry?Partial<RetryPolicy> | falseAjustes de la política de reintentos, o false para desactivarlos.
timeoutMs?numberTimeout por petición, en ms; 20 000 por defecto.
closePreviousSessions?booleanCerrar sesiones anteriores cuando el SII informa el límite y lo ofrece; true por defecto.
logger?LoggerLogger; silencioso por defecto.
capture?HttpCapturePuerto de captura HTTP; apagado por defecto.
now?() => DateReloj inyectable.
sleep?SleepFnEspera entre reintentos y entre pasos.
randomId?() => stringtransactionId — Fuente de los identificadores de transacción del RCV; por defecto crypto.randomUUID.

Candado#

TypeScript
// Exclusión mutua por clave dentro de un proceso.
function createMemoryPortalLock(): PortalLock
TipoDescripción
PortalLockQuién puede usar ahora una sesión del portal: run parte solo con el candado tomado y este se libera al terminar, aunque falle. Definido como <T>(key: string, run: () => Promise<T>) => Promise<T>.

Sesión#

TypeScript
// Abre una sesión de forma explícita, reutilizando una en caché que siga viva, según lo dice la
// página de empresa del ambiente del cliente (`ad_empresa1`). Las demás operaciones no lo
// necesitan: inician sesión a pedido.
function openPortalSession(
  portal: PortalClient,
  overrides?: CallOverrides,
): Promise<PortalSessionInfo>
 
// Cierra la sesión para devolver su cupo y siempre borra la sesión en caché. Un cierre fallido
// solo se registra: de todos modos el SII vence la sesión por su cuenta.
function closePortalSession(portal: PortalClient, overrides?: CallOverrides): Promise<void>
TipoDescripción
PortalSessionInfoLo que supo openPortalSession.

Datos de la empresa#

La resolución de la empresa (por ambiente), sus datos de contribuyente y el perfil del emisor que combina ambos. Guía: Portal.

TypeScript
// Lee la resolución de una empresa. Es por ambiente: certificación y producción responden fechas y
// números distintos para un mismo RUT, y el par equivocado hace que se rechace un envío con "Error
// en Carátula".
function fetchCompanyResolution(
  portal: PortalClient,
  input?: { readonly companyRut?: string; readonly environment?: Environment; },
  overrides?: CallOverrides,
): Promise<CompanyResolution>
 
// Lee los datos del contribuyente: nombre, domicilio separado en sus partes, actividades y
// sucursales.
function fetchTaxpayerData(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<TaxpayerData>
 
// Lee la resolución y los datos del contribuyente en secuencia y los combina. En paralelo, una
// respuesta pisa la cookie del balanceador que la otra necesita y `ad_empresa2` responde vacío.
function fetchIssuerProfile(
  portal: PortalClient,
  input?: { readonly companyRut?: string; readonly environment?: Environment; },
  overrides?: CallOverrides,
): Promise<IssuerProfile>
TipoDescripción
IssuerProfileLo que una empresa necesita para llenar un Issuer y una carátula.
CompanyResolutionLo que ad_empresa2 dice de una empresa en un ambiente.
TaxpayerDataLo que ce_consulta_muestra_e dice de un contribuyente. Solo responde en el host de certificación.
TaxpayerActivityUna actividad económica.
TaxpayerBranchUna sucursal inscrita.

Campos de IssuerProfile

CampoTipoDescripción
rutSiiRutRUTEmisor — RUT de la empresa.
businessNamestringRznSoc — Razón social.
businessActivitystringGiroEmis — Giro: la primera actividad, si no la glosa.
activityCodenumber | nullActeco — Código de la primera actividad, o null.
addressstringDirOrigen — Dirección.
communestringCmnaOrigen — Comuna.
citystringCiudadOrigen — Ciudad; la comuna si falta.
resolutionDatestringFchResol — Fecha de resolución del ambiente pedido.
resolutionNumbernumberNroResol — Número de resolución del ambiente pedido.

Campos de CompanyResolution

CampoTipoDescripción
rutstring | nullRut — RUT de la empresa tal como aparece.
businessNamestring | nullRazón Social — Razón social.
resolutionDatestring | nullFecha Resolución — Fecha de resolución, AAAA-MM-DD.
resolutionNumbernumber | nullResolución — Número de resolución.
authorizationDatestring | nullFecha Autorización — Fecha de autorización, tal como viene.

Campos de TaxpayerData

CampoTipoDescripción
rutstring | nullDATOS DEL CONTRIBUYENTE RUT — RUT.
businessNamestring | nullNOMBRE O RAZÓN SOCIAL — Razón social.
businessActivitystring | nullGiroEmis — Descripción de la primera actividad.
activityCodenumber | nullActeco — Código de la primera actividad.
addressstring | nullDirOrigen — Parte de calle y número del domicilio.
neighborhoodstring | nullVilla/Pob. — Villa o población.
citystring | nullCiudad — Ciudad.
communestring | nullComuna — Comuna.
portalAddressstring | nullDIRECCIÓN DE LA EMPRESA — Celda del domicilio, sin cambios.
regionalOfficestring | nullDIRECCIÓN REGIONAL DEL CONTRIBUYENTE — Dirección regional del SII.
activitiesreadonly TaxpayerActivity[]ACTIVIDADES ECONÓMICAS — Actividades económicas.
branchesreadonly TaxpayerBranch[]DIRECCIÓN SUCURSALES — Sucursales inscritas.
descriptionstring | nullGLOSA DESCRIPTIVA — Glosa descriptiva.

Consulta de sets de certificación#

Lee el estado de cada set de pruebas y libro en el host de certificación. Solo lee; declarar el avance es declareProgress. Guía: Sets de pruebas.

TypeScript
// Lee el estado de cada set de pruebas y libro, en el host de certificación. Solo lee: declarar
// avance es `declareProgress`.
function queryCertificationSets(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<CertificationSets>
TipoDescripción
CertificationSetsEl estado de certificación de una empresa.
CertificationSetUn set de pruebas o libro de la certificación, y su estado.

Timbraje: cupo y solicitudes de CAF#

Lista los tipos de documento que la empresa puede timbrar, lee el cupo de folios (esto no timbra nada) y solicita un CAF. El SII puede otorgar menos de lo que pides: lee granted. El XML del CAF contiene una llave privada: trátalo como un secreto. Guía: Portal.

TypeScript
// Lista los tipos de documento que el portal ofrece para timbraje con esta empresa. Una página de
// error no es "sin tipos": una página sin selector y sin rechazo declarado lanza.
function listStampableTypes(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<readonly StampableType[]>
 
// Lee cuántos folios autoriza el SII para un tipo, deteniéndose en el formulario que lo muestra:
// no se timbra nada y el cupo no se mueve. `MAX_AUTOR` y `FOLIOS_DISP` aparecen solo mientras el
// SII raciona el tipo. El formulario es el que tiene el tipo elegido en su selector: la página de la
// empresa, sin tipo elegido, se recarga con él, y una última página que no es ese formulario lanza
// `SII_PORTAL_SESSION_EXPIRED` o `SII_PORTAL_UNEXPECTED_PAGE` en vez de leerse como un tipo sin racionar.
function queryFolioQuota(
  portal: PortalClient,
  input: { readonly type: DocumentType; readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<FolioQuota>
 
// Solicita un rango de folios y descarga su CAF por los cinco pasos del portal. Un rechazo puede
// llegar en cualquier paso. Si se excede el máximo efectivo y no hay `minQuantity`, pide una vez
// más por un folio. Si el SII responde la solicitud con el formulario de solicitud otra vez, no se
// envía nada de nuevo: lanza `SII_PORTAL_REJECTED` con `stampingUncertain`, porque los folios pudieron
// otorgarse, y `listReobtainableRanges` dice si se otorgaron.
function requestCaf(
  portal: PortalClient,
  input: CafRequestInput,
  overrides?: CallOverrides,
): Promise<ObtainedCaf>
TipoDescripción
CafRequestInputEntrada de requestCaf.
FolioQuotaEl cupo de timbraje de un tipo de documento.
ObtainedCafUn CAF obtenido del portal. xml contiene la llave privada del CAF: guárdalo como un secreto.
QuotaFieldsEl cupo de un formulario: ambos null si el SII no está racionando este tipo, porque solo entonces los publica.
StampableTypeUn tipo de documento que el portal ofrece para timbraje.

Campos de CafRequestInput

CampoTipoDescripción
typeDocumentTypeCOD_DOCTO — Tipo de documento.
quantitynumberCANTIDAD — Folios pedidos.
minQuantity?numberMínimo aceptable: bajo él no se timbra, porque un rango corto queda sin usar y baja el próximo máximo.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Campos de FolioQuota

CampoTipoDescripción
maxAuthorizednumber | nullMAX_AUTOR — Máximo de folios que el SII autoriza ahora.
availableFoliosnumber | nullFOLIOS_DISP — Folios timbrados sin utilizar.
unrestrictedbooleanEl SII no está racionando este tipo.
blockedbooleanEl SII no autoriza nada: "NO SE AUTORIZA TIMBRAJE".

Campos de ObtainedCaf

CampoTipoDescripción
xmlstringAUTORIZACION — El archivo tal como lo entregó el SII.
cafCafEl archivo parseado.
grantednumberFolios que cubre.
maxAuthorizednumber | nullMAX_AUTOR — Máximo que autorizó el SII, o null si no estaba racionando.
availableFoliosnumber | nullFOLIOS_DISP — Folios timbrados sin usar, o null si no estaba racionando.
recoveredbooleanVolvió por "ya fue autorizado" o por la reobtención.

Anulación de folios#

Anular folios sin usar es irreversible y exige un alcance explícito. Lista antes los rangos sin usar. Guía: Portal.

TypeScript
// Lista los rangos sin usar de un tipo de documento, siguiendo las páginas del listado. No cambia
// nada.
function listFolioRanges(
  portal: PortalClient,
  input: { readonly type: DocumentType; readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<FolioRanges>
 
// Anula folios sin usar: hasta cuatro pasadas por el listado, por rango y folio por folio cuando
// parte del rango ya se anuló o se recibió, deteniendo una pasada tras dos negativas reales
// seguidas. Un folio solo conserva la respuesta del SII. Cuando el SII ya respondió por algunos
// folios, un `DteError` que termina el recorrido (una sesión vencida, un bloqueo, la cancelación de
// quien llama, un listado posterior rechazado o ilegible) vuelve en `failure`, con lo hecho hasta
// entonces; un rango que nunca llegó (`transport`) no es respuesta, y antes de cualquier respuesta
// el error se lanza. Un rango respondido folio por folio vuelve en tan pocas piezas como lo
// permitan sus respuestas, y un recorrido cortado en un folio conserva los folios respondidos antes.
function annulFolios(
  portal: PortalClient,
  input: AnnulFoliosInput,
  overrides?: CallOverrides,
): Promise<AnnulmentResult>
TipoDescripción
AnnulFoliosInputEntrada de annulFolios. Se exige range, withinDays o all: la anulación no se puede deshacer y los folios anulados pesan contra el cupo de timbraje durante seis meses.
AnnulmentResultLo que hizo una anulación, aunque un paso posterior la haya cortado.
FolioRangesLos rangos sin usar de un tipo de documento.
FolioSpanAlgunos folios y cuántos son.
AnnulmentRejectionReasonPor qué no se anularon unos folios. alreadyAnnulled y received son lo que el SII dijo de ellos y son definitivos; siiError, transport y unknown (una respuesta sin palabras conocidas) no lo son, porque el SII pudo haberlos anulado igual. Definido como 'alreadyAnnulled' | 'received' | 'siiError' | 'transport' | 'unknown'.
UnusedFolioRangeUn rango timbrado con folios sin usar, tal como lo lista la página de anulación. Los rangos anulados siguen en esta lista para siempre.

Campos de AnnulFoliosInput

CampoTipoDescripción
typeDocumentTypeCOD_DOCTO — Tipo de documento.
range?{ readonly from: number; readonly to: number }FOLIO_INI_A, FOLIO_FIN_A — Solo estos folios.
withinDays?numberSolo rangos timbrados en estos días; un rango sin fecha legible se omite.
all?booleanTodos los rangos sin usar, hasta maxRanges.
reason?stringMOTIVO — Motivo; "Folios no utilizados" por defecto.
maxRanges?numberMáximo de rangos que se intentan en CADA pasada, tomados del final del listado; 50 por defecto.
exclude?readonly { readonly from: number; readonly to: number }[]Folios que no se tocan, como un CAF todavía en uso.
knownAnnulled?readonly string[]knownAnnulled de la corrida anterior: un rango listado cuyos folios cubren estas claves, en una o en varias, no se vuelve a intentar.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Campos de AnnulmentResult

CampoTipoDescripción
annulledreadonly FolioSpan[]Folios anulados. Los folios contiguos con la misma respuesta son un solo tramo.
rejectedreadonly (FolioSpan & { readonly reason: AnnulmentRejectionReason })[]Folios no anulados y por qué, los folios contiguos con la misma respuesta en un solo tramo. alreadyAnnulled y received son resultados esperados, no negativas; unknown es una respuesta del SII sin palabras conocidas, así que esos folios pueden estar anulados o no.
totalAnnullednumberSuma de annulled.
totalRejectednumberSuma de rejected.
knownAnnulledreadonly string[]Claves desde-hasta definitivas (anuladas, alreadyAnnulled o received): guárdalas y devuélvelas, porque el portal las sigue listando para siempre. Un rango respondido folio por folio queda en tan pocas claves como lo permitan sus respuestas, una por cada tramo de folios con la misma respuesta, así que lee las claves como tramos de folios, no como los rangos del listado. Nada que el SII haya respondido con palabras desconocidas va aquí.
failureFolioFlowFailure | nullLo que detuvo el recorrido cuando el SII ya había respondido por algunos folios, o null: un DteError de un listado posterior (listFolioRanges) o de un rango posterior (annulFolios), un rechazo incluido. Anular no se puede deshacer, así que vuelve lo hecho hasta entonces: guarda knownAnnulled venga o no failure. Null en un recorrido que termina.

Recuperación de CAF#

Vuelve a descargar el CAF de un rango que el SII ya autorizó. No gasta cupo. Guía: Portal.

TypeScript
// Lista los rangos autorizados que el SII deja volver a descargar. Los rangos anulados aparecen
// sin marcar, así que saber cuáles lo son cuesta una petición por rango. Al trámite se entra como a
// los demás, con login a pedido y la pantalla de representación. Solo un listado da una lista, vacía
// si no tiene rangos: una página que declara un rechazo lanza `SII_PORTAL_REJECTED`, una de ingreso
// `SII_PORTAL_SESSION_EXPIRED` y cualquier otra `SII_PORTAL_UNEXPECTED_PAGE`.
function listReobtainableRanges(
  portal: PortalClient,
  input: { readonly type: DocumentType; readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<readonly ReobtainableRange[]>
 
// Descarga el CAF de un rango ya autorizado. No gasta cupo. Primero se entra al trámite, como entra
// `listReobtainableRanges`, con login a pedido, así que una sesión en caché que venció después del
// listado inicia sesión de nuevo en vez de enviar el rango con ella. Una página que declara un
// rechazo en la entrada lanza `SII_PORTAL_REJECTED` y cualquier otra que no es el trámite
// `SII_PORTAL_UNEXPECTED_PAGE`, antes de enviar nada; una página de ingreso en cualquier paso lanza
// `SII_PORTAL_SESSION_EXPIRED`, nunca el rechazo de un paso.
function reobtainCaf(
  portal: PortalClient,
  input: { readonly type: DocumentType; readonly range: ReobtainableRange; },
  overrides?: CallOverrides,
): Promise<ObtainedCaf>
TipoDescripción
ReobtainableRangeUn rango autorizado que el SII deja volver a descargar. La lista también trae rangos ya emitidos, que el SII no marca de ninguna forma: reutilizar uno hace que cada documento se rechace con DTE-3-101.

Entrar al trámite le suma a reobtainCaf un GET, de rf_reobtencion1_folios, respecto de antes de la 0.7.0. Quien tomaba reobtainDownloadMissing o reobtainCafMissing por una sesión vencida ahora recibe SII_PORTAL_SESSION_EXPIRED.

Flujos#

Flujos compuestos construidos sobre las operaciones anteriores. Devuelven los rechazos como datos y, cuando ya tienen algo que quien llama no puede perder (CAF, o folios que el SII anuló), también cualquier otro DteError, en failure. El error original va antes al logger del cliente, como la advertencia sii portal flow stopped, keeping what it holds, con los detalles del error, flow, code y stoppedAt, y cada detalle de texto tachado. La advertencia deja fuera lo que dijo una página (portalMessage, body) y la url de donde vino, que pueden nombrar a la empresa y su RUT; los errores lanzados los conservan. Guía: Portal.

TypeScript
// Solicita un CAF que cubra toda la cantidad; bajo ella no se timbra nada. Con `allowAnnul`, una
// vez que el SII respondió la anulación, un `DteError` que la corta, o uno de la solicitud que se
// repite después, termina el flujo con `rejection: null`, el cupo de la primera solicitud, la falla
// en `failure` y lo anulado en `knownAnnulled`; tras una anulación cortada no se vuelve a pedir.
// Antes de la primera respuesta de la anulación, lanza.
function requestCafExact(
  portal: PortalClient,
  input: RequestCafExactInput,
  overrides?: CallOverrides,
): Promise<RequestCafExactResult>
 
// Cubre una cantidad con varios CAF, para cuando `FOLIOS_DISP` es 0 y `MAX_AUTOR` es chico: el SII
// raciona por historial, no hay nada que anular ni reobtener, y esperar no lo mueve. Un rechazo
// vuelve con su propio tipo y `portalMessage`, en el primer viaje o en uno posterior; después de una
// entrega, solo un folio por sobre el máximo (`quotaExceeded`) se lee como `quotaCapReached`. Con un
// CAF ya en la mano, un viaje posterior que falla con un `DteError`
// que no es un rechazo (una falla de transporte, un tiempo agotado, una sesión vencida, un bloqueo,
// `CAF_INVALID`, la cancelación de quien llama) termina el flujo con los CAF obtenidos, el último
// cupo visto y la falla en `failure`; sin un CAF en la mano, lanza. `quantity` debe ser un entero
// de al menos 1, o lanza `INVALID_OPTION` antes de que salga nada.
function requestCafInBatches(
  portal: PortalClient,
  input: RequestCafInBatchesInput,
  overrides?: CallOverrides,
): Promise<FolioFlowResult>
 
// Cubre una cantidad con rangos autorizados sin gastar cupo, partiendo por el folio más antiguo.
// Es lo que levanta un bloqueo de timbraje, porque el SII pide emitir folios. El listado inicia
// sesión a pedido, y cualquier fallo al listar (un rechazo, una sesión vencida, una página que no es
// el listado) se lee como sin rangos, con el fallo en `reason`: no lanza. Una descarga rechazada se
// registra y se sigue. Con un CAF ya en la mano, una descarga que falla con cualquier otro
// `DteError` (una falla de transporte, un tiempo agotado, una sesión vencida, un bloqueo, la
// cancelación de quien llama) termina el recorrido con los CAF descargados, el mensaje de la falla
// en `reason` y la falla en `failure`; sin un CAF en la mano, lanza. Una página de ingreso en
// respuesta al rango o al archivo es una sesión vencida, no una descarga rechazada.
function reobtainFolios(
  portal: PortalClient,
  input: ReobtainFoliosInput,
  overrides?: CallOverrides,
): Promise<ReobtainResult>
TipoDescripción
FolioFlowFailureEl DteError que detuvo un flujo de folios que ya tenía algo que quien llama no puede perder: CAF, o folios que el SII anuló. Solo se guarda su código, con el tipo de un rechazo, porque sus otros detalles pueden traer lo que dijo una página; el logger recibe el resto, nunca lo que dijo una página ni su dirección.
FolioFlowResultEl resultado de un flujo compuesto. Los rechazos vuelven como datos, porque el flujo puede tener ya CAF en la mano: esos deben llegar a quien llama, y un CAF no puede viajar en los detalles de un error, que se registran. Por lo mismo, con un CAF ya en la mano, o folios ya anulados, cualquier otro DteError también vuelve como dato, en failure.
ReobtainFoliosInputEntrada de reobtainFolios.
ReobtainResultLo que obtuvo reobtainFolios. Lo descargado vuelve aunque no alcance o falle una descarga posterior, así quien llama pide solo la diferencia.
RequestCafExactInputEntrada de requestCafExact.
RequestCafExactResultEl resultado de requestCafExact, más la memoria de rangos anulados. Su failure se llena cuando el SII ya respondió su anulación y falla un paso posterior, y knownAnnulled guarda entonces lo anulado.
RequestCafInBatchesInputEntrada de requestCafInBatches.

Campos de FolioFlowFailure

CampoTipoDescripción
codeDteErrorCodeEl código del error.
operation'queryFolioQuota' | 'requestCaf' | 'reobtainCaf' | 'listFolioRanges' | 'annulFolios'El paso que falló. Leer el cupo o listar rangos no cambia nada; una solicitud pudo otorgarse igual, y listReobtainableRanges dice si se otorgó; una anulación pudo pasar, y la siguiente lo sabe por el SII como "ya anulado".
rejection?PortalRejectionEl tipo de rechazo cuando code es SII_PORTAL_REJECTED, como un listado que el SII rechaza después de una anulación; ausente si no.

Campos de FolioFlowResult

CampoTipoDescripción
completebooleanSe cubrió la cantidad pedida.
cafsreadonly ObtainedCaf[]Todos los CAF obtenidos, aunque no alcancen.
grantednumberFolios cubiertos.
maxAuthorizednumber | nullMAX_AUTOR — Último máximo visto, o null.
availableFoliosnumber | nullFOLIOS_DISP — Último valor visto, o null.
rejectionPortalRejection | nullPor qué no alcanzó, o null.
portalMessagestring | nullLo que dijo el portal, con sus secretos tachados, o null.
failureFolioFlowFailure | nullLo que detuvo el flujo mientras tenía algo que quien llama no puede perder, o null; rejection es entonces null. requestCafInBatches lo llena con CAF en la mano, cuando no fue un rechazo; requestCafExact una vez que el SII respondió su anulación, con lo que cortó la anulación o la solicitud que sigue, y knownAnnulled guarda lo anulado.

Campos de ReobtainFoliosInput

CampoTipoDescripción
typeDocumentTypeCOD_DOCTO — Tipo de documento.
quantitynumberFolios por cubrir.
isIssued?(range: { readonly from: number; readonly to: number }) => boolean | Promise<boolean>El registro de quien llama de los rangos ya enviados al SII, que el portal no marca.
isFolioFree?(folio: number) => boolean | Promise<boolean>Confirma un folio en el SII, normalmente con folioReceived.
maxChecksPerRange?numberMáximo de consultas por rango; 30 por defecto.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Campos de ReobtainResult

CampoTipoDescripción
completebooleanSe cubrió la cantidad.
cafsreadonly ObtainedCaf[]Los CAF descargados.
rangesreadonly { readonly from: number; readonly to: number; readonly freeFolios: readonly number[] }[]Cada rango usado y sus folios libres.
expiredreadonly { readonly from: number; readonly to: number; readonly authorizationDate: string | null }[]Rangos cuyo CAF ya venció: no cuentan y conviene anularlos.
availablenumberFolios libres cubiertos.
reasonstring | nullPor qué no alcanzó, en palabras, o null; si el listado o una descarga falló, el mensaje de ese fallo.
failureFolioFlowFailure | nullLo que detuvo las descargas con CAF en la mano cuando no fue un rechazo, o null; operation es entonces reobtainCaf.

Campos de RequestCafExactInput

CampoTipoDescripción
typeDocumentTypeCOD_DOCTO — Tipo de documento.
quantitynumberFolios necesarios en un CAF.
allowAnnul?booleanAnular folios sin usar para levantar el límite y pedir una vez más. Apagado por defecto: no se puede deshacer y pesa contra el cupo seis meses.
exclude?readonly { readonly from: number; readonly to: number }[]Folios que la anulación no toca, como un CAF todavía en uso.
knownAnnulled?readonly string[]knownAnnulled de la corrida anterior: un rango listado cuyos folios cubren estas claves, en una o en varias, no se vuelve a intentar.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Campos de RequestCafInBatchesInput

CampoTipoDescripción
typeDocumentTypeCOD_DOCTO — Tipo de documento.
quantitynumberFolios por cubrir en total: un entero de al menos 1.
maxBatches?numberMáximo de viajes al portal; 4 por defecto.
initialQuota?FolioQuotaUn cupo ya leído, para omitir la primera lectura.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Registro de compras y ventas (RCV)#

El registro corre sobre la sesión del portal. Las lecturas entregan campos tipados (null cuando faltan) y una copia raw de la fila. Las escrituras (changePurchaseType, moveVatToCommonUse, moveVatToRecoverable) cambian el registro real en un cliente de producción. Lo que el registro hace con cada código de documento son datos del paquete: revisa Códigos de documento y estados del registro. Guía: Registro.

TypeScript
// Cambia el tipo de compra de un documento. En producción esto cambia el registro real.
function changePurchaseType(
  portal: PortalClient,
  input: ChangePurchaseTypeInput,
  overrides?: CallOverrides,
): Promise<void>
 
// Una compra tal como la tiene el registro, incluido su tipo de compra vigente.
function fetchPurchaseDocument(
  portal: PortalClient,
  key: PurchaseDocumentKey,
  overrides?: CallOverrides,
): Promise<PurchaseDocument | null>
 
// Los totales oficiales de un período por tipo de documento y estado contable, incluido lo que el
// SII agrega, como las boletas. No se miran los códigos de respuesta, así que un mes que el SII se
// niega a mostrar se lee como uno vacío.
function fetchRegisterSummary(
  portal: PortalClient,
  input: RegisterSummaryInput,
  overrides?: CallOverrides,
): Promise<RegisterSummary>
 
// Todos los documentos de un período, sin XML: el resumen por tipo y luego una llamada de detalle
// por fila, al mismo tiempo. Este no es el registro oficial. No se miran los códigos de respuesta,
// así que un mes que el SII se niega a mostrar se lee como uno vacío.
function listPeriodDocuments(
  portal: PortalClient,
  input: ListPeriodDocumentsInput,
  overrides?: CallOverrides,
): Promise<PeriodDocuments>
 
// Los tipos de compra que el SII permite darle a un documento.
function listPurchaseTypes(
  portal: PortalClient,
  overrides?: CallOverrides,
): Promise<readonly PurchaseType[]>
 
// Mueve el IVA de un documento de recuperable a uso común. En producción esto cambia el registro
// real.
function moveVatToCommonUse(
  portal: PortalClient,
  input: MoveVatInput,
  overrides?: CallOverrides,
): Promise<void>
 
// Mueve el IVA de un documento de uso común de vuelta a recuperable: lo inverso de
// `moveVatToCommonUse`, con las mismas reglas. Al devolver todo, `commonUseVat` queda en 0 y
// `recoverableVat` lleva el total.
function moveVatToRecoverable(
  portal: PortalClient,
  input: MoveVatInput,
  overrides?: CallOverrides,
): Promise<void>
TipoDescripción
ChangePurchaseTypeInputLo que necesita changePurchaseType.
ListPeriodDocumentsInputLo que necesita listPeriodDocuments.
MoveVatInputLo que necesitan las funciones que mueven IVA: el monto final de cada casilla tras el cambio, no una diferencia. Un monto ausente va vacío.
PurchaseDocumentKeyQué compra del registro.
RegisterSummaryInputLo que necesita fetchRegisterSummary.
PeriodDocumentUn documento de un período: sin hora ni XML. Los nombres de campo no están medidos, como en PeriodSummaryRow.
PeriodDocumentsLos documentos de un período.
PeriodSummaryRowUna fila del resumen de un período, por tipo de documento y sección.
PurchaseDocumentUna compra tal como la tiene el registro. Los nombres de campo no están medidos, como en PeriodSummaryRow.
PurchaseTypeUn tipo de compra que el SII permite darle a un documento. Medido.
RcvObjectUn objeto de una respuesta del RCV, tal como lo envió el SII. Definido como Readonly<Record<string, unknown>>.
RegisterHeaderLa cabecera del registro oficial. Los nombres de campo no están medidos, como en PeriodSummaryRow. proportionalityFactor es un número de 0 a 1, que también se lee de un texto con espacios y coma decimal (" 1,0000"); un valor fuera de ese rango es null y queda en raw.
RegisterSummaryEl registro oficial de un período.
RegisterSummaryRowUna fila del registro oficial. Los nombres de campo no están medidos, como en PeriodSummaryRow.

Campos de ChangePurchaseTypeInput

CampoTipoDescripción
typenumbertipoDocumento — Tipo de documento.
folionumbernumeroDocumento — Folio.
periodstringperiodoTributario — Período tributario, AAAA-MM.
counterpartyRutstringrutContraparte + dvContraparte — RUT del emisor.
companyRut?stringrut + dv — Empresa, si no es la del cliente.
purchaseTypestringtipoCompra — Un id de listPurchaseTypes.

Campos de ListPeriodDocumentsInput

CampoTipoDescripción
periodstringperiodo — Período, AAAA-MM.
direction?DocumentDirectionoperacion — Documentos emitidos o recibidos; por defecto emitidos.
companyRut?stringrutContribuyente + dvContribuyente — Empresa, si no es la del cliente.

Campos de MoveVatInput

CampoTipoDescripción
typenumbertipoDocumento — Tipo de documento.
folionumbernumeroDocumento — Folio.
periodstringperiodoTributario — Período tributario, AAAA-MM.
counterpartyRutstringrutContraparte + dvContraparte — RUT del emisor.
companyRut?stringrut + dv — Empresa, si no es la del cliente.
commonUseVat?numberivaComun — IVA de uso común final.
recoverableVat?numberivaRec — IVA recuperable final.

Campos de RegisterSummaryInput

CampoTipoDescripción
periodstringptributario — Período, AAAA-MM.
operationRegisterOperationoperacion — Compras o ventas.
accountingStatus?AccountingStatusestadoContab — Estado contable; por defecto registrado.
companyRut?stringrutEmisor + dvEmisor — Empresa, si no es la del cliente.

Códigos de documento y estados del registro#

Lo que el registro hace con cada código de documento, y qué estados contables puede tener cada lado. Son datos del paquete, agregados en la 0.2.0: nada de esto llama al SII. Úsalos al leer los totales de fetchRegisterSummary: qué códigos restan, cuáles nunca llegan al registro, cuáles lista el registro documento por documento y en cuáles el comprador retiene el IVA. Guía: Registro.

TypeScript
import { REGISTER_ACCOUNTING_STATUSES, REGISTER_DOCUMENT_CODES, registerDocumentCode } from 'dte-sdk/portal'
 
registerDocumentCode(61)?.sign // -1: una nota de crédito resta de los totales
registerDocumentCode(52)?.inRegister // false: las guías de despacho nunca llegan al registro
registerDocumentCode(71) // undefined: no es uno de los 49 códigos
REGISTER_DOCUMENT_CODES.length // 49
REGISTER_ACCOUNTING_STATUSES.sale // ['registered']
TypeScript
// Los 49 códigos de documento del registro de compras y ventas, ordenados por código.
const REGISTER_DOCUMENT_CODES: readonly RegisterDocumentCode[]
 
// Lo que el registro hace con un código de documento, o `undefined` si el código no es uno de los 49.
function registerDocumentCode(code: number): RegisterDocumentCode | undefined
 
// Los estados contables que puede tener cada lado del registro: los cuatro en compras, solo
// `registered` en ventas, porque ninguna fuente del SII describe otros estados de una venta.
const REGISTER_ACCOUNTING_STATUSES: Readonly<Record<RegisterOperation, readonly AccountingStatus[]>>
TipoDescripción
RegisterDocumentCodeUn código de documento del registro, con lo que el registro hace con él.

Campos de RegisterDocumentCode

CampoTipoDescripción
codenumberTpoDoc — Código de documento del SII, el número del tipo de documento tributario.
namestringNombre oficial del documento, como lo escriben las tablas de códigos del SII.
operationsreadonly RegisterOperation[]Lados del registro donde aparece el código, compras antes que ventas; vacío si el código no está en el registro.
electronicbooleanSe emite como DTE, en el formato XML del SII. Los códigos 47 y 48 no son DTE.
inRegisterbooleanFalso cuando el código nunca llega al registro: las guías de despacho 50 y 52. Inferido.
sign1 | -1-1 cuando el código resta de los totales del registro (notas de crédito y disminuciones), 1 si suma. Inferido del F29. Los montos de los códigos 40, 43 y 103 pueden venir negativos y traen su propio signo.
perDocumentbooleanColumna "solo en resumen" — Falso cuando el registro muestra solo una línea de resumen mensual del código, sin detalle por documento.
buyerWithholdsVatbooleanEl comprador retiene el IVA (cambio de sujeto). Las notas de débito y crédito de una factura de compra pueden llevar la retención por documento y no por código, así que este indicador no las cubre.

Los códigos, según lo que el catálogo dice de ellos

GrupoCódigos
Compras y ventas29, 30, 32, 33, 34, 40, 43, 45, 46, 55, 56, 60, 61, 108, 901, 904
Solo ventas35, 38, 39, 41, 47, 48, 101, 102, 103, 104, 105, 106, 109, 110, 111, 112, 500, 501, 902, 903, 905, 906, 907, 919, 920, 922, 924
Solo compras909, 910, 911, 914
Fuera del registro (inRegister: false)50, 52
Restan de los totales (sign: -1)60, 61, 106, 112, 501, 922
Solo línea de resumen (perDocument: false)35, 38, 39, 41, 47, 48, 105, 500, 501, 906, 919, 920, 922, 924
El comprador retiene el IVA (buyerWithholdsVat: true)29, 45, 46
DTE (electronic: true)33, 34, 39, 41, 43, 46, 52, 56, 61, 110, 111, 112

El catálogo sigue las fuentes públicas del SII: el formato "Información Electrónica de Compras y Ventas" v3.0 (las tablas de códigos de cada lado y su columna "solo en resumen"), los formatos de carga del registro para compras, ventas y resumen de ventas, sus preguntas frecuentes, la Resolución Exenta SII N° 12 de 2011 (el comprador de una factura de inicio retiene todo el IVA) y las instrucciones del F29 (las notas de crédito restan). Lo que el SII no dice, el catálogo lo infiere, y su JSDoc lo indica: las guías de despacho 50 y 52 no figuran en ninguna tabla de códigos del registro, por eso quedan fuera de él; el signo de cada código es el del F29 y no uno que el registro declare; el código 906 es solo resumen; y los códigos 500 y 501 vienen del formato antiguo de libros. Todavía no se ha contrastado con un registro real con documentos.

Los cuatro estados contables: registered (REGISTRO) es un documento en el registro; pending (PENDIENTE), una compra a la que aún le falta el acuse de recibo del comprador; claimed (RECLAMADO), una compra reclamada dentro de 8 días, que no puede cambiar de estado; notIncluded (NO_INCLUIR), una compra que el contribuyente decidió dejar fuera.

Respaldo MIPYME#

Descarga el XML de los documentos emitidos o recibidos de un rango de fechas desde el respaldo MIPYME. Guía: Registro.

TypeScript
// Descarga desde el respaldo MIPYME el XML de los documentos emitidos o recibidos de un rango de
// fechas, partiendo el rango hasta que cada tramo quepa en los 20 documentos por descarga que
// permite el SII.
function downloadMipymeBackup(
  portal: PortalClient,
  input: MipymeBackupInput,
  overrides?: CallOverrides,
): Promise<MipymeBackup>
TipoDescripción
MipymeBackupLo que descargó un respaldo.
MipymeBackupChunkUn tramo de un respaldo.
MipymeBackupInputLo que necesita downloadMipymeBackup.
MipymeDownloadedChunkUn tramo descargado, tal como lo recibe onChunk.

Campos de MipymeBackupInput

CampoTipoDescripción
fromstringFEC_DESDE — Primer día, AAAA-MM-DD.
tostringFEC_HASTA — Último día, AAAA-MM-DD.
direction?DocumentDirectionORIGEN — Documentos emitidos o recibidos; por defecto emitidos.
type?numberTPO_DOC — Solo este tipo de documento; por defecto todos.
attempts?numberIntentos por listado y por descarga; por defecto 3.
onChunk?(chunk: MipymeDownloadedChunk) => Promise<void> | voidRecibe cada tramo a medida que llega, para que un histórico largo no quede en memoria: entonces el resultado no trae xml.
companyRut?stringRUT_EMP + DV_EMP — Empresa, si no es la del cliente.

Verificación de actividades#

Para emitir documentos electrónicos con IVA, el SII pide algo más que ser contribuyente de IVA: la empresa necesita una verificación positiva de sus actividades en terreno, o una en proceso (los requisitos del SII). Sin ella, una solicitud de CAF para un tipo que la necesita se rechaza con activityVerificationPending. unstable_fetchActivityVerification lee esa verificación desde la "Consulta estado de verificación y acreditación" del SII, y listAccreditationDocuments, desde la misma app, el catálogo de los documentos que acreditan una actividad. Ambas corren en la misma sesión que el resto del portal y llegaron en la 0.3.0. Ambas leen producción sea cual sea el ambiente del cliente, porque la app existe solo ahí. Guía: Portal.

unstable_ significa que su forma puede cambiar en cualquier versión, incluso un patch. unstable_fetchActivityVerification se ha leído contra el SII real el 8 de noviembre de 2026, para una empresa con la verificación pendiente, y el 9 de noviembre, para una verificación condicionada, pendiente de acreditación. Aún no se conocen los códigos del SII para una verificación aprobada, así que nada en el resultado dice por sí solo si la empresa puede emitir documentos con IVA. Cuando se lea una aprobada, la función pasa a llamarse fetchActivityVerification. Hasta entonces, fija la versión y lee el changelog antes de cada actualización, también de los patch. listAccreditationDocuments no está marcada como inestable.

TypeScript
import { listAccreditationDocuments, unstable_fetchActivityVerification } from 'dte-sdk/portal'
 
const { requests, messages } = await unstable_fetchActivityVerification(portal)
requests.length // 0 si la empresa nunca pidió la verificación
requests[0]?.status // 'PAC', descrito como 'PENDIENTE DE ACREDITACIÓN'
requests[0]?.preliminaryResult // 'CONDICIONADA'
requests[0]?.finalResult // null mientras no lo hay
requests[0]?.requestedOn // 'AAAA-MM-DD'
messages.filter((message) => message.blocking) // los mensajes en que se detiene la página del propio SII
 
const documents = await listAccreditationDocuments(portal)
documents[0] // { category: 'general', code: 1, description: '…' }
TypeScript
// Inestable: su forma puede cambiar en cualquier versión, incluso un patch. La verificación de
// actividades de la empresa, la "Consulta estado de verificación y acreditación" del SII. Envía el
// RUT de la empresa, no el de la sesión, y una solicitud de otro RUT lanza en vez de pasar como de
// la empresa. Lee producción sea cual sea el ambiente del cliente. Los funcionarios, los
// comentarios y el domicilio nunca salen.
function unstable_fetchActivityVerification(
  portal: PortalClient,
  input?: ActivityVerificationInput,
  overrides?: CallOverrides,
): Promise<ActivityVerification>
 
// Los tipos de documento que el SII acepta para acreditar una actividad, en el orden del SII: una
// lista general y una específica, cuyos códigos se repiten. Lee producción sea cual sea el ambiente
// del cliente.
function listAccreditationDocuments(
  portal: PortalClient,
  overrides?: CallOverrides,
): Promise<readonly AccreditationDocument[]>
TipoDescripción
ActivityVerificationInputLo que necesita unstable_fetchActivityVerification.
ActivityVerificationLa verificación de actividades de una empresa. Los funcionarios, los comentarios, el domicilio y lo interno del trámite quedan fuera a propósito, y no hay raw. Inestable.
ActivityVerificationRequestUna solicitud de verificación de las actividades de la empresa. Inestable.
ActivityVerificationMessageUn mensaje que el SII agrega a la verificación.
AccreditationDocumentUn tipo de documento que el SII acepta para acreditar una actividad. El código se repite entre categorías: la clave es el par.
AccreditationDocumentCategoryA qué lista pertenece un documento que acredita una actividad: GRAL general, ESPEC específico. Definido como 'general' | 'specific'.

Campos de ActivityVerificationInput

CampoTipoDescripción
companyRut?stringcontribuyenteBO.rut + contribuyenteBO.dv — Empresa, si no es la del cliente.

Campos de ActivityVerification

CampoTipoDescripción
requestsreadonly ActivityVerificationRequest[]converiBO — Las solicitudes; vacía si la empresa nunca pidió la verificación.
messagesreadonly ActivityVerificationMessage[]arrMensajeBO — Los mensajes del SII.

Campos de ActivityVerificationRequest

CampoTipoDescripción
numbernumber | nullverNumVerificacion — Número de la verificación.
kindstring | nulltipo — Tipo de verificación, como VIA.
reasonstring | nullmotivo — Motivo, como lo escribe el SII.
preliminaryResultstring | nullresultadoVia — Resultado preliminar, como CONDICIONADA.
finalResultstring | nullresultadoFinal — Resultado final; null mientras no lo hay.
statusstring | nullverEstadoVerificacion — Código del estado, como PAC.
statusDescriptionstring | nulldescEstadoVerificacion — Qué significa el estado, como PENDIENTE DE ACREDITACIÓN.
requestedOnstring | nullfechaSolicitud — Fecha de la solicitud, AAAA-MM-DD.
accreditationDeadlinestring | nullfechaLimiteAcreditacion — Último día para acreditar la actividad, AAAA-MM-DD; null si no hay.
procedureStatusstring | nulldescEstadoTramite — Estado del trámite de acreditación, como lo escribe el SII.
hasCertificatebooleanidCertificado — True cuando el SII emitió el certificado de la verificación.

Campos de ActivityVerificationMessage

CampoTipoDescripción
textstringmensaje — El mensaje.
blockingbooleanpuedeContinuar en false — True cuando la página del propio SII se detiene en él.

Campos de AccreditationDocument

CampoTipoDescripción
categoryAccreditationDocumentCategory | nulldocaCategoria — La categoría; null si dte-sdk no la conoce.
codenumber | nulldocaCodigo — Código dentro de la categoría.
descriptionstring | nulldocaDescripcion — Nombre del documento.

Lo que lanzan:

  • Un código de error del SII en la respuesta lanza SII_PORTAL_REJECTED con rejection: 'activityVerificationRefused', y las palabras del SII en details.portalMessage cuando dijo algo.
  • Una solicitud cuyo RUT no es el de la empresa lanza SII_PORTAL_UNEXPECTED_PAGE con step: 'otherTaxpayer', y no se devuelve nada de ella. La página del propio SII muestra la verificación de quien inició sesión; esta función envía el RUT de la empresa, y el SII respondió a una sesión del representante legal de la empresa.
  • Una respuesta sin la verificación o sin el catálogo lanza SII_PORTAL_UNEXPECTED_PAGE. Sin empresa en la llamada ni en el cliente, unstable_fetchActivityVerification lanza MISSING_FIELD, y con una inválida, INVALID_RUT. Los códigos de sesión y de transporte son los del resto del portal.

Como las lecturas del registro, cada llamada a la app del SII es una sola petición salvo que actives retry, mientras el ingreso y la visita a la app mantienen sus reintentos. Una lectura que encuentra una sesión vencida o una página ilegible parte de nuevo una vez con una sesión nueva.

Registro de folios#

Control local de folios: cuáles se reservaron, se enviaron y se anularon. createFolioRegistry trabaja sobre un almacén que tú entregas; createMemoryFolioRegistry lo guarda en memoria y createDirectoryFolioRegistry (de dte-sdk/node) lo guarda en un archivo JSON. Guía: Portal.

TypeScript
// Primeros 12 caracteres hexadecimales del SHA-256 de un archivo CAF, para distinguir dos archivos
// de un mismo rango.
function cafFingerprint(xml: string): string
 
// Un registro sobre un almacén. Las llamadas corren una tras otra dentro de este proceso, cada una
// leyendo el libro de nuevo; varios procesos necesitan un almacén o un registro propio que se haga
// cargo.
function createFolioRegistry(store: FolioLedgerStore, now?: () => Date): FolioRegistry
 
// Un registro que vive en memoria: para tests y corridas cortas.
function createMemoryFolioRegistry(now?: () => Date): FolioRegistry
TipoDescripción
FolioLedgerStoreDónde se guarda un libro.
FolioRegistryControl local de folios: cuáles se reservaron, enviaron y anularon. Un servicio con su propia base implementa estas funciones con sus propias transacciones; el resto arma una con createFolioRegistry.
FolioEntryUna entrada del libro.
FolioLedgerTodo el registro como un solo valor apto para JSON.
FolioScopeLos folios de un CAF para una empresa en un ambiente.
FolioSentRecordLo que se registra cuando un folio va al SII.
FolioStatsTotales de una empresa y tipo de documento.
ReserveOptionsCómo se elige un folio.

Campos de FolioLedgerStore

CampoTipoDescripción
load() => Promise<FolioLedger | null>El libro guardado, o null.
save(ledger: FolioLedger) => Promise<void>Reemplaza el libro guardado.

Campos de FolioRegistry

CampoTipoDescripción
reserve(scope: FolioScope, options?: ReserveOptions) => Promise<number>Reserva el siguiente folio libre: después del último reservado, o desde el menor reservado y no enviado; nunca uno usado o anulado.
markSent( scope: FolioScope, folio: number, sent?: { readonly trackId?: string; readonly sentAt?: string; readonly extra?: Readonly<Record<string, unknown>> }, ) => Promise<void>Registra un folio como enviado.
markAnnulled(scope: FolioScope, folios: readonly number[]) => Promise<void>Registra folios como anulados en el SII.
release(scope: FolioScope, folios: readonly number[]) => Promise<void>Devuelve folios.
remaining(scope: FolioScope) => Promise<number>Folios del rango aún sin usar.
stats(query: { readonly companyRut: string readonly type: number readonly environment?: Environment }) => Promise<FolioStats>Totales de una empresa y tipo.

Campos de FolioStats

CampoTipoDescripción
totalEntriesnumberCAF registrados.
totalUsednumberFolios usados.
totalSentnumberFolios enviados.
rangesreadonly { readonly from: number; readonly to: number; readonly environment: Environment; readonly cafFingerprint: string | null; readonly used: number; readonly sent: number; readonly remaining: number }[]Uno por entrada del registro, es decir por archivo CAF: su rango, el environment de su alcance y la cafFingerprint del archivo que cuenta (null si su alcance no la tiene), y sus folios usados, enviados y aún sin usar. Dos archivos de un mismo rango, o un rango en ambos ambientes, son dos entradas, que se distinguen por estos dos campos. Un FolioRegistry propio devuelve ambos en cada rango.

Campos de ReserveOptions

CampoTipoDescripción
lowestFree?booleanEntrega el menor folio del rango que no está usado ni anulado, estén donde estén los usados: un folio devuelto, o que quedó libre bajo un folio marcado como enviado, vuelve a salir.

Certificación: la mitad determinista#

Todo lo que no necesita el portal: leer el texto del set de pruebas del SII, planificar lo que emite cada set, asignar folios, emitir los documentos y armar los libros. Nada de esto envía; lo hace el runner. Guía: Sets de pruebas.

Catálogos#

TypeScript
// Tipos de set que puede traer el texto del set de pruebas del SII, por su nombre en inglés.
const TEST_SET_KINDS: {
  readonly basic: "basic"
  readonly exempt: "exempt"
  readonly guide: "guide"
  readonly purchase: "purchase"
  readonly export: "export"
  readonly settlement: "settlement"
  readonly salesBook: "salesBook"
  readonly purchaseBook: "purchaseBook"
  readonly exemptPurchaseBook: "exemptPurchaseBook"
  readonly guideBook: "guideBook"
  readonly other: "other"
}
 
// Nombres de los sets y libros tal como los lista el portal de certificación (`pe_avance2`).
const TEST_SET_PORTAL_NAMES: Readonly<Partial<Record<TestSetKind, string>>>
 
// `TpoDocRef` — El tipo de documento de referencia que lleva cada documento del set en su primera
// referencia: `SET`.
const TEST_SET_REFERENCE_TYPE = 'SET'
 
// La contraparte de cada línea de los libros de compras de certificación: el RUT del propio SII y
// un nombre de relleno. El SII lo acepta, existe como contribuyente y no es dato personal de
// nadie.
const CERTIFICATION_COUNTERPARTY: { readonly rut: "60803000-K"; readonly name: "Razon Social" }
TipoDescripción
TestSetKindUnión de los tipos de set.

Texto del set#

TypeScript
// Parsea el texto del set de pruebas del SII: sets, sus casos con ítems y referencias, los
// documentos de proveedor de los sets de libro de compras y el factor de proporcionalidad.
function parseTestSetText(text: string): readonly TestSet[]
TipoDescripción
TestSetUn set del texto del set de pruebas.
TestCaseUn caso de un set: un documento a emitir.
TestCaseItemUna fila de ítem de un caso.
TestBookDocumentUn documento de proveedor de un set de libro de compras.

Plan#

TypeScript
// Los casos que emite cada set, con los folios que necesita cada tipo de documento, a partir de
// los sets parseados. Por cada tipo gana el último set del texto.
function planCertificationSets(sets: readonly TestSet[]): CertificationPlan
TipoDescripción
CertificationPlanLo que la certificación emite, por tipo de set; un tipo que el texto no trae está ausente. Los libros de ventas y de guías no tienen plan: salen de los sets básico y de guías emitidos.
BasicSetPlanEl set básico: facturas 33, notas de crédito 61, notas de débito 56.
ExemptSetPlanEl set exento: facturas 34, notas de crédito 61, notas de débito 56; toda línea exenta.
GuideSetPlanEl set de guías: una 52 por caso.
PurchaseSetPlanEl set de factura de compra: una 46, a lo más una 61 y una 56.
PurchaseBookPlanUn set de libro de compras: los documentos de proveedor y el factor de proporcionalidad (0,6 si el set no lo trae).
PlannedInvoiceUn caso de factura (33, 34 o 46).
PlannedNoteUn caso de nota de crédito o débito.
PlannedGuideUn caso de guía de despacho.
PlannedItemUn ítem de un caso, listo para ser una línea de documento.
SetFoliosFolios que necesita cada tipo de documento. Definido como Readonly<Record<number, number>>.

Asignador de folios#

TypeScript
// Una fuente de folios sobre uno o varios CAF: un contador por CAF, gana el primer CAF del tipo
// con folio libre, un folio nunca se entrega dos veces, y el CAF devuelto es el que contiene el
// folio en su rango, así timbra con su propia llave.
function createFolioAllocator(cafs: readonly Caf[], options?: FolioAllocatorOptions): FolioSource
TipoDescripción
FolioSourceDe dónde sale el siguiente folio de un tipo, con el CAF que lo timbra. El asignador en memoria de abajo es una implementación; el runner puede implementarlo con el registro de folios.
FolioAllocatorOptionsOpciones de createFolioAllocator.

Campos de FolioAllocatorOptions

CampoTipoDescripción
usedFolios?readonly { readonly type: number; readonly folio: number }[]Folios ya usados; el asignador parte después del mayor usado de cada CAF.

Emisión de los sets#

TypeScript
// Emite cada documento del plan de un set y firma su sobre.
function issueTestSet(plan: IssuableSetPlan, options: IssueSetOptions): Promise<IssuedSet>
 
// `SetDTE/@ID` de cada sobre de certificación.
const TEST_SET_ENVELOPE_ID = 'DTE_SetDoc'
TipoDescripción
IssueSetOptionsLo que necesita emitir un set.
IssuableSetPlanLos planes que acepta issueTestSet. Definido como BasicSetPlan | ExemptSetPlan | GuideSetPlan | PurchaseSetPlan.
IssuedCaseUn documento emitido de un set.
IssuedSetUn set emitido: sus documentos en orden de emisión y el sobre firmado que los lleva.

Campos de IssueSetOptions

CampoTipoDescripción
issuerIssuerInputEl emisor, como en un documento.
receiverReceiverInputEl cliente que nombra cada documento; las facturas de compra y los traslados internos nombran al emisor.
certificateCertificateEl certificado de firma.
foliosFolioSourceDe dónde salen los folios y sus CAF.
resolution{ readonly number: number; readonly date: string }La resolución del ambiente de certificación: número 0 y su fecha.
now?() => DateReloj, leído una vez por documento y una vez para el sobre.

Campos de IssuedCase

CampoTipoDescripción
caseIdstringId del caso, por ejemplo 4256-1.
typeDocumentTypeTipoDTE — Tipo de documento.
folionumberFolio — Folio tomado para el documento.
documentSignedDocumentEl documento emitido y firmado.

Campos de IssuedSet

CampoTipoDescripción
kind'basic' | 'exempt' | 'guide' | 'purchase'Tipo de set.
attentionNumberstringNUMERO DE ATENCION del set.
casesreadonly IssuedCase[]Los documentos emitidos, en orden de emisión.
envelopeSignedEnvelopeEnvioDTE — El sobre firmado que lleva los documentos.

Simulación#

TypeScript
// Reemite cada caso de los cuatro planes con folios nuevos, en el orden básico, exento, guías y
// compra, y firma un solo sobre con todos.
function issueSimulation(
  plan: CertificationPlan,
  options: IssueSetOptions,
): Promise<IssuedSimulation>
TipoDescripción
IssuedSimulationLa simulación: cada caso de los cuatro sets reemitido, en un sobre.

Libros de los sets#

TypeScript
// El libro de ventas de la certificación: solo las facturas y notas del set básico, con fecha 15
// del período, el cliente como contraparte, todo monto presente (0 si falta) y la tasa de IVA en
// cada línea.
function createCertificationSalesBook(
  set: IssuedSet | SalesBookSource,
  input: CertificationSalesBookInput,
): SignedPurchaseSalesBook
 
// Un libro de compras de la certificación desde un set de libro de compras: una línea por
// documento de proveedor con la contraparte de relleno del SII, el IVA al 19 % del afecto, IVA de
// uso común, IVA no recuperable en entregas gratuitas, la retención de una factura de compra, el
// folio referido de una nota tomado de su observación y, en el libro para exentos, IVA no
// recuperable en toda línea afecta, la factura exenta en papel como tipo 32 y notas que heredan
// los montos del documento que refieren.
function createCertificationPurchaseBook(
  plan: PurchaseBookPlan,
  input: CertificationBookInput,
): SignedPurchaseSalesBook
 
// El libro de guías de la certificación: solo las guías del set de guías, con su tipo de traslado
// y fecha de emisión; por posición la segunda lleva `Operacion` 1 y la tercera va anulada
// (`Anulado` 2, total 0 y nada más), salvo que `caseFlags` diga otra cosa; una venta lleva el
// cliente, el neto, la tasa y el IVA; toda guía su total.
function createCertificationGuideBook(
  set: IssuedSet | GuideBookSource,
  input: CertificationGuideBookInput,
): SignedGuideBook
TipoDescripción
CertificationBookInputLo que necesita cada libro de certificación.
CertificationSalesBookInputOpciones de createCertificationSalesBook.
CertificationGuideBookInputOpciones de createCertificationGuideBook.
BookReceiverEl cliente escrito en los libros de ventas y de guías.
GuideBookCaseFlagCómo entra una guía al libro de guías. Definido como 'normal' | 'modified' | 'voided'.
BookCaseTotalsLos totales de un documento emitido, como los leen los libros.
SalesBookCaseUn documento del libro de ventas: el caso del set emitido, o lo que una corrida guardó de él.
GuideBookCaseUna guía del libro de guías: el caso del set emitido, o lo que una corrida guardó de él.
SalesBookSourceUna fuente de libro de ventas que no es el set emitido: su tipo y sus casos, como los tiene una corrida retomada.
GuideBookSourceUna fuente de libro de guías que no es el set emitido.

Campos de CertificationBookInput

CampoTipoDescripción
periodstringPeriodoTributario — Período AAAA-MM; el runner lo elige contra el historial del portal.
issuerRutstringRutEmisorLibro — RUT del contribuyente dueño del libro.
senderRutstringRutEnvia — RUT de quien envía, normalmente el titular del certificado.
resolution{ readonly number: number; readonly date: string }NroResol y FchResol — Número (0 en certificación) y fecha de la resolución.
certificateCertificateEl certificado de firma.
now?() => DateReloj para el id del libro y la marca de la firma.
submission?'total' | 'adjustment'TipoEnvio — total (por defecto) o adjustment, para un período que el SII ya tiene; cualquiera de los tres libros puede ajustar.
previousTotals?readonly BookTotals[]Totales del período de los envíos anteriores, arrastrados en un ajuste del libro de ventas o de compras; el libro de guías los ignora.

Campos de CertificationSalesBookInput

CampoTipoDescripción
periodstringPeriodoTributario — Período AAAA-MM; el runner lo elige contra el historial del portal.
issuerRutstringRutEmisorLibro — RUT del contribuyente dueño del libro.
senderRutstringRutEnvia — RUT de quien envía, normalmente el titular del certificado.
resolution{ readonly number: number; readonly date: string }NroResol y FchResol — Número (0 en certificación) y fecha de la resolución.
certificateCertificateEl certificado de firma.
now?() => DateReloj para el id del libro y la marca de la firma.
submission?'total' | 'adjustment'TipoEnvio — total (por defecto) o adjustment, para un período que el SII ya tiene; cualquiera de los tres libros puede ajustar.
previousTotals?readonly BookTotals[]Totales del período de los envíos anteriores, arrastrados en un ajuste del libro de ventas o de compras; el libro de guías los ignora.
receiverBookReceiverEl cliente que se escribe en cada línea (RUTDoc, RznSoc).
creditNoteSign?'positive' | 'negative'Notas de crédito con montos positivos (por defecto) o negativos.

Campos de CertificationGuideBookInput

CampoTipoDescripción
periodstringPeriodoTributario — Período AAAA-MM; el runner lo elige contra el historial del portal.
issuerRutstringRutEmisorLibro — RUT del contribuyente dueño del libro.
senderRutstringRutEnvia — RUT de quien envía, normalmente el titular del certificado.
resolution{ readonly number: number; readonly date: string }NroResol y FchResol — Número (0 en certificación) y fecha de la resolución.
certificateCertificateEl certificado de firma.
now?() => DateReloj para el id del libro y la marca de la firma.
submission?'total' | 'adjustment'TipoEnvio — total (por defecto) o adjustment, para un período que el SII ya tiene; cualquiera de los tres libros puede ajustar.
previousTotals?readonly BookTotals[]Totales del período de los envíos anteriores, arrastrados en un ajuste del libro de ventas o de compras; el libro de guías los ignora.
receiverBookReceiverEl cliente que se escribe en cada línea de guía (RUTDoc, RznSoc).
notificationFolio?numberFolioNotificacion; 3 por defecto.
caseFlags?readonly GuideBookCaseFlag[]Un indicador por guía, por posición; por defecto la segunda es modified y la tercera voided.

Certificación: la mitad del portal#

Las operaciones del portal de la certificación (descargar el set, declarar el avance, leer el avance, avanzar la etapa, historial de libros, declaración de cumplimiento), el almacén que guarda el estado de una corrida, el entorno que comparten todos los pasos y una función por paso. El runner las encadena. Guía: Runner.

Catálogos#

TypeScript
// Los sets en el orden en que se envían.
const SET_KEYS: readonly SetKey[] = ['basic', 'guide', 'exempt', 'purchase']
 
// Los libros en el orden en que se envían.
const BOOK_KEYS: readonly BookKey[] = ['purchaseBook', 'salesBook', 'guideBook', 'exemptPurchaseBook']
 
// Los libros que toda certificación debe tener aprobados.
const MANDATORY_BOOK_KEYS: readonly BookKey[] = ['purchaseBook', 'salesBook', 'guideBook']
 
// `FILE` — El nombre de archivo con que viaja cada libro en el envío, como lo espera el SII.
const BOOK_FILE_NAMES: Readonly<Record<BookKey, string>> = {
  salesBook: 'LibroCV.xml',
  purchaseBook: 'LibroCV.xml',
  exemptPurchaseBook: 'LibroCVExentos.xml',
  guideBook: 'LibroGuia.xml',
}
 
// El nombre de artefacto de cada libro.
const BOOK_ARTEFACT_NAMES: Readonly<Record<BookKey, string>> = {
  salesBook: 'libro-ventas.xml',
  purchaseBook: 'libro-compras.xml',
  exemptPurchaseBook: 'libro-compras-exentos.xml',
  guideBook: 'libro-guias.xml',
}
 
// El nombre de artefacto del sobre de cada set.
const SET_ARTEFACT_NAMES: Readonly<Record<SetKey, string>>
 
// `SETnn` — Los sets opcionales marcados al descargar el set de pruebas: guías (03), facturas
// exentas (06), los libros de ventas (07), compras (08) y guías (09), el libro de compras para
// exentos (15) y el set de factura de compra (72).
const DEFAULT_OPTIONAL_SETS: readonly string[] = ['SET03', 'SET06', 'SET07', 'SET08', 'SET09', 'SET15', 'SET72']
 
// Las etapas de una certificación, en orden, como las lleva el ejecutor.
const CERTIFICATION_STAGES: readonly [
  "testSets", "books", "simulation", "exchange", "printedSamples", "compliance", "done"
]
 
// Las palabras con que el portal nombra una etapa (`pe_avance6`, "paso <b>…</b>"), de la última
// hacia atrás. Cualquier texto posterior al intercambio cae en `printedSamples`: la declaración de
// cumplimiento dice si las muestras ya están aprobadas.
const PORTAL_STAGE_WORDS: readonly { readonly stage: CertificationStage; readonly words: readonly string[] }[]
 
// Los nombres de los eventos de progreso que emiten los pasos.
const CERTIFICATION_STEPS: readonly [
  "SETS_DOWNLOADING", "SETS_LOADED", "SETS_REGENERATED", "CAF_REQUESTING", "CAF_OK", "SET_START",
  "SET_OK", "SET_ERROR", "SETS_DECLARING", "SETS_DECLARED", "POLLING", "SETS_APPROVED",
  "SETS_REJECTED", "BOOKS_START", "BOOK_SKIPPED", "BOOK_SENDING", "BOOK_OK", "BOOK_ERROR",
  "BOOK_PERIOD_RETRY", "BOOKS_DECLARING", "BOOKS_DONE", "ADVANCE_WAITING", "ADVANCE_DONE",
  "SIM_START", "SIM_SENDING", "SIM_OK", "SIM_DECLARING", "SIM_DONE", "INTERCAMBIO_START",
  "INTERCAMBIO_DESCARGADO", "INTERCAMBIO_DONE", "MUESTRAS_UPLOADING", "MUESTRAS_DONE", "CERT_DONE",
  "CERT_ERROR"
]
TipoDescripción
SetKeyLos cuatro sets que emite la certificación. Definido como 'basic' | 'exempt' | 'guide' | 'purchase'.
BookKeyLos libros de la certificación. Definido como 'salesBook' | 'purchaseBook' | 'exemptPurchaseBook' | 'guideBook'.
DeclarationKeyCada fila que puede traer el formulario de declaración de avance (pe_avance2), por clave. Definido como SetKey | BookKey | 'simulation' | 'export1' | 'export2' | 'settlement'.
CertificationStageUnión de las etapas. Definido como (typeof CERTIFICATION_STAGES)[number].
CertificationStepUnión de los nombres de evento de progreso. Definido como (typeof CERTIFICATION_STEPS)[number].

Declaraciones y avance#

TypeScript
// Descarga el set de pruebas desde `pe_generar`. Sin sesión en la caché se lee primero la página
// de avance, lo que inicia sesión y deja que el SII refresque la postulación; responda lo que
// responda esa lectura, la descarga sigue.
function downloadTestSet(
  portal: PortalClient,
  input?: DownloadTestSetInput,
  overrides?: CallOverrides,
): Promise<DownloadedTestSet>
 
// Declara el track id y la fecha de envíos en `pe_avance2`, enviado a `pe_avance3`. Del formulario
// se leen los campos ocultos y el índice del campo de cada fila, buscada por su etiqueta (los
// índices se mueven al aprobarse sets).
function declareProgress(
  portal: PortalClient,
  input: DeclareProgressInput,
  overrides?: CallOverrides,
): Promise<DeclarationResult>
 
// Lee la página de avance: la secuencia de entrada, `pe_avance5` y luego `pe_avance6` con la
// empresa. En ninguna página del camino se busca un rechazo, y una página que no nombra etapa ni
// estado sigue siendo una respuesta.
function readProgress(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<ProgressReport>
 
// Pide al portal pasar la postulación a su siguiente etapa: `pe_avance4` con `TOTREG` y `PASO` tal
// como los trae `pe_avance2` (`PASO` cambia con la etapa; un valor fijo hace que el SII responda
// "ya se encuentra en el paso"), con `pe_avance2` de referer.
function advanceStage(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<AdvanceResult>
 
// Lista los libros que el SII tiene para un año (`QEstLibro`, después de que `DTEauth?7` liga la
// sesión a ese CGI). Todo período listado está ocupado para un nuevo envío total.
function listBookHistory(
  portal: PortalClient,
  input: { readonly year: number; readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<BookHistory>
 
// La declaración de cumplimiento: `pe_avance7`, `pe_avance8` con la empresa, una vez más con todos
// los inputs de la página cuando el portal pide continuar (`OK_MSG`), y luego el formulario de
// `pe_avance9` con todos los inputs de la página, salvo `Salir`, cada `OPCn` en `S` y `CONFIRMAR`,
// ambos envíos con `pe_avance8` de referer.
function declareCompliance(
  portal: PortalClient,
  input?: { readonly companyRut?: string; },
  overrides?: CallOverrides,
): Promise<ComplianceResult>
TipoDescripción
DownloadTestSetInputEntrada de downloadTestSet.
DownloadedTestSetLo que leyó downloadTestSet. Descargar genera el set: el SII asigna los casos de nuevo, así que lo enviado para un set anterior queda sin efecto.
DeclarationEntryUn envío por declarar: su track id y la fecha en que se envió, AAAA-MM-DD de Chile.
DeclarationEntriesLas entradas de una declaración, por clave de fila. Definido como Readonly<Partial<Record<DeclarationKey, DeclarationEntry>>>.
DeclareProgressInputEntrada de declareProgress.
DeclarationOutcomeCómo terminó una declaración, en una palabra. Definido como | 'accepted' | 'inReview' | 'contentErrors' | 'allRejected' | 'notSaved' | 'inconsistent' | 'declined' | 'failed'.
DeclarationResultLo que hizo declareProgress y lo que respondió el portal, con los hechos sobre los que decide el ciclo de declaración.
ProgressReportEl avance de la postulación como lo muestra pe_avance6.
AdvanceResultLo que obtuvo advanceStage. Definido como AdvanceAnswer.
BookHistoryLo que leyó listBookHistory para un año.
ComplianceResultLo que hizo declareCompliance.
SetGenerationStateUna fila de la tabla de sets de pe_generar1: un set y si la empresa lo obtuvo.
OptionalSetOptionUn set opcional que la página ofrece como casilla.
SetGenerationPageLo que muestra pe_generar1 antes de generar un set.
DeclarationFormEl formulario de pe_avance2 tal como lo lee la declaración: solo lo que entrega un atributo entre comillas.
DeclarationAnswerLo que dice una respuesta de pe_avance3, leída sobre la página tal como llegó.
DeclarationVerificationLo que dice el formulario releído de las filas recién declaradas.
AdvanceAnswerLo que respondió pe_avance4.
ItemStateEl estado de un set o libro en la página de avance. Definido como | 'approved' | 'inReview' | 'rejected' | 'objections' | 'pending' | 'annulled' | 'inconsistent' | 'unknown'.
ProgressPageLa página de avance (pe_avance6) leída.
BookHistoryEntryUn libro que el SII tiene, tal como lo lista QEstLibro.
ComplianceFormEl formulario de pe_avance9, listo para enviar: su acción y sus campos.

Campos de DownloadTestSetInput

CampoTipoDescripción
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.
optionalSets?readonly string[]SETnn — Sets opcionales a marcar; por defecto DEFAULT_OPTIONAL_SETS. Solo se envían los que la página ofrece.
download?booleanFalse para leer solo la tabla de estados, sin generar un set.
previousAttentionNumber?stringEl número de atención del set en mano, para reconocer un set regenerado.

Campos de DeclareProgressInput

CampoTipoDescripción
entriesDeclarationEntriesLos envíos por declarar.
companyRut?stringRUT_EMP + DV_EMP — RUT de la empresa; por defecto el del cliente.

Almacén#

TypeScript
// Un estado nuevo para una empresa.
function createCertificationState(companyRut: string, now?: Date): CertificationState
 
// Un almacén en memoria: para tests y corridas cortas.
function createMemoryCertificationStore(): CertificationStore
 
// Lanza salvo que el nombre sea una ruta relativa de segmentos seguros: sin segmento vacío, sin
// `.`, sin `..`, sin ruta absoluta, nada fuera de `[A-Za-z0-9._-]`.
function assertArtefactName(name: string): void
 
// Un almacén en un directorio: `state.json` escrito de forma atómica (archivo temporal y
// renombre), los artefactos como archivos, una `/` en un nombre como subdirectorio.
function createDirectoryCertificationStore(
  options: DirectoryCertificationStoreOptions,
): CertificationStore
TipoDescripción
CertificationStateTodo el estado de una corrida de certificación: lo descargado, obtenido, enviado, declarado y aprobado. Un valor JSON simple que el almacén guarda entre corridas; el ejecutor retoma desde él.
CertificationStoreDónde viven el estado y los artefactos de una corrida. Los nombres son rutas relativas con / de separador; un servicio puede respaldarlo con su propio almacenamiento.
SentEnvelopeUn envío hecho al SII: su track id, la fecha de Chile en que se envió (lo que toma la declaración), el instante.
SentCaseUn caso de un set enviado.
SentSetUn set enviado, con sus casos.
SentBookUn libro enviado: su período, su tipo de envío, y si el portal lo aprobó.
BooksStateLo que guarda la fase de libros.
AccumulatedTotalsLos totales de período acumulados por período y operación, para los envíos de ajuste. Definido como Readonly< Record<string, { readonly purchase?: readonly BookTotals[]; readonly sale?: readonly BookTotals[] }> >.
EnvelopeDiagnosisLo que dijo el estado SOAP de un envío, guardado para diagnóstico.
DirectoryCertificationStoreOptionsOpciones de createDirectoryCertificationStore.

Campos de CertificationStore

CampoTipoDescripción
load() => Promise<CertificationState | null>El estado guardado, o null.
save(state: CertificationState) => Promise<void>Reemplaza el estado guardado.
writeArtefact(name: string, content: string) => Promise<void>Escribe un artefacto, reemplazándolo.
readArtefact(name: string) => Promise<string | null>Lee un artefacto, o null.
listArtefacts() => Promise<readonly string[]>Todos los nombres de artefacto, ordenados.

Campos de DirectoryCertificationStoreOptions

CampoTipoDescripción
dirstringEl directorio de state.json y los artefactos; se crea en el primer uso. Contiene llaves privadas de CAF: fuera del control de versiones.

Entorno de ejecución#

TypeScript
// Lo que la corrida completa en un emisor que lo omite: el giro, el código de actividad, la comuna
// y la ciudad. El RUT, la razón social y la dirección no tienen valor por defecto.
const DEFAULT_CERTIFICATION_ISSUER: Readonly<{ businessActivity: "ACTIVIDADES DE PROGRAMACION INFORMATICA"; activityCode: 620200...
 
// El receptor de prueba que usa la corrida cuando no se le da uno.
const DEFAULT_CERTIFICATION_RECEIVER: ReceiverInput
TipoDescripción
CertificationDependenciesLo que necesita cada paso: los clientes, el almacén, el registro, la empresa y el reloj.
CertificationIssuerInputEl emisor tal como lo recibe la corrida: el giro y la comuna se pueden omitir.
CertificationProgressEventLos eventos de progreso que emiten los pasos, con los nombres de sus pasos.
PollingLabelLo que espera un evento POLLING. Definido como 'sets' | 'declaration' | 'books' | 'simulation'.
StepResult<Outcome extends string>Lo que devuelve un paso: el estado que guardó, cómo terminó, y una palabra o frase sobre el porqué.

Campos de CertificationDependencies

CampoTipoDescripción
portalPortalClientEl cliente del portal en el ambiente de certificación.
siiSiiClientEl cliente del SII en el ambiente de certificación.
storeCertificationStoreDónde viven el estado y los artefactos.
registryFolioRegistryEl registro de folios.
issuerCertificationIssuerInputEmisor — La empresa que se certifica; lo que omita toma los valores de DEFAULT_CERTIFICATION_ISSUER.
receiver?Partial<ReceiverInput>Receptor — El receptor de los documentos de la corrida; por defecto el receptor de prueba de DEFAULT_CERTIFICATION_RECEIVER, campo por campo.
certificateCertificate
resolution?{ readonly number?: number; readonly date?: string }NroResol, FchResol — La resolución del ambiente de certificación; por defecto número 0 y la fecha UTC de hoy.
now?() => DateReloj; las fechas son fechas de Chile de él.
sleep?(ms: number) => Promise<void>Función de espera; por defecto un temporizador real.
onProgress?(event: CertificationProgressEvent) => voidEventos de progreso.
contact?ExchangeContactNmbContacto, MailContacto, FonoContacto — El contacto que nombran las respuestas del intercambio, si hay.

Campos de CertificationIssuerInput

CampoTipoDescripción
rutstring
businessNamestringRznSoc (RznSocEmisor en boletas) — Razón social, máximo 100 caracteres.
activityCode?numberActeco — Código de actividad económica del SII.
phone?stringTelefono — Teléfono.
email?stringCorreoEmisor — Correo electrónico del emisor.
branch?stringSucursal — Nombre de la sucursal, máximo 20.
siiBranchCode?numberCdgSIISucur — Código de sucursal inscrito en el SII, entero de 1 a 999999999.
addressstringDirOrigen — Dirección de origen, máximo 70.
city?stringCiudadOrigen — Ciudad de origen, máximo 20; por defecto la comuna.
salespersonCode?stringCdgVendedor — Código del vendedor.
businessActivity?stringGiroEmis — Giro; por defecto ACTIVIDADES DE PROGRAMACION INFORMATICA.
commune?stringCmnaOrigen — Comuna; por defecto Santiago.

Campos de StepResult

CampoTipoDescripción
stateCertificationState
outcomeOutcome
detail?string

Pasos#

TypeScript
// Descarga el set de pruebas, lo parsea, planifica los sets y guarda el texto y el plan como
// artefactos. Descargar genera el set de nuevo en el SII, así que una corrida que ya tenía plan
// parte de cero: todo lo enviado queda sin efecto.
function obtainTestSet(
  deps: CertificationDependencies,
  state: CertificationState,
  options?: { readonly optionalSets?: readonly string[]; },
): Promise<StepResult<"loaded" | "regenerated">>
 
// Envía un set de pruebas: lo emite con los folios de los CAF del estado a través del registro,
// guarda el sobre y cada documento como artefactos, lo sube, marca los folios enviados pase lo que
// pase, y registra el track id y la fecha de Chile del envío.
function sendTestSet(
  deps: CertificationDependencies,
  state: CertificationState,
  options: { readonly kind: SetKey; },
): Promise<StepResult<"sent">>
 
// Declara los sets enviados hasta ahora con la fecha de hoy, con el ciclo de declaración; el
// resultado y cualquier diagnóstico van al estado.
function declareTestSets(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<DeclarationStepResult>
 
// Espera la aprobación de los sets enviados: 5 intentos cada 10 s, durmiendo primero, leyendo la
// página de avance. Una lectura que falla solo gasta su intento.
function waitForTestSetsApproval(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<"approved" | "rejected" | "timedOut">>
 
// Pide al portal la etapa siguiente después de los libros: se lee la página de avance, hasta 30
// veces cada 10 s mientras no se pueda leer; con la primera página que se lee se pide el avance de
// inmediato, diga lo que diga la página de los libros (decide el portal); luego se lee de nuevo la
// página para saber la etapa, y la etapa del estado pasa a la del portal cuando esa es posterior.
function advanceToNextStage(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<"advanced" | "unchanged" | "failed" | "timedOut">>
 
// Envía la simulación: CAF nuevos para un folio por caso (nunca los CAF de los sets), cada caso de
// los cuatro sets reemitido en un sobre, el sobre y los documentos guardados como artefactos, el
// envío, los folios marcados enviados pase lo que pase, y el track id con la fecha de Chile del
// envío.
function sendSimulation(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<"sent">>
 
// Declara la simulación, salvo que la página de avance nombre el intercambio como el paso en que
// está la postulación: un paso posterior se declara como cualquier otro, y también una página que
// no se puede leer.
function declareSimulation(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<DeclarationStepResult<DeclarationOutcome | "skipped">>
 
// Espera la simulación: 30 consultas cada 10 s a la página de avance, consultando primero. Una
// lectura que falla solo gasta su intento.
function waitForSimulationApproval(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<"done" | "confirmed" | "rejected" | "timedOut">>
 
// El cierre de la certificación: una petición más para avanzar la etapa, luego la declaración de
// cumplimiento.
function declareComplianceFinal(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<"declared" | "blocked">>

Paso de folios#

TypeScript
// Asegura que la corrida tenga los folios que necesita cada tipo. Primero los CAF en mano: uno
// vencido se omite, los folios de esta corrida que el SII nunca recibió se devuelven, y los que el
// SII ya recibió se marcan como usados para saltarlos. Cada CAF obtenido se guarda en el estado de
// inmediato. Si aún falta, lanza `FOLIO_OUT_OF_RANGE` o, cuando las tandas se detuvieron por una
// falla y no por la respuesta del SII, el código de esa falla. Una reobtención o una anulación
// cortadas por una falla terminan el paso también con el código de esa falla, una vez que lo que
// trajo y se conservó, o lo que anuló, está en el estado. Solo un rechazo de racionamiento lleva a
// anular: una tanda posterior rechazada por la empresa, la opción o la persona conserva su tipo, y
// un bloqueo de la persona se levanta primero reobteniendo.
function prepareFolios(
  deps: CertificationDependencies,
  state: CertificationState,
  options?: PrepareFoliosOptions,
): Promise<PrepareFoliosResult>
 
// Los folios que necesita cada tipo para los sets aún no enviados: la suma de los `folios` de cada
// plan de set, nunca más, porque folios autorizados sin usar hacen que el SII racione la próxima
// solicitud.
function setFolioNeeds(
  plan: CertificationPlan,
  sent: readonly string[],
): Readonly<Record<number, number>>
 
// Los folios que necesita la simulación: uno por caso, por tipo.
function simulationFolioNeeds(plan: CertificationPlan): Readonly<Record<number, number>>
TipoDescripción
PrepareFoliosOptionsOpciones de prepareFolios.
PrepareFoliosResultLo que devuelve prepareFolios: el estado, y los CAF que cubren las necesidades.

Campos de PrepareFoliosOptions

CampoTipoDescripción
needs?Readonly<Record<number, number>>Folios necesarios por tipo; por defecto los sets aún no enviados.
fresh?booleanIgnorar los CAF en mano y pedir nuevos (la simulación nunca reutiliza los CAF de los sets).

Campos de PrepareFoliosResult

CampoTipoDescripción
stateCertificationState
outcomeOutcome
detail?string
cafsreadonly string[]Los CAF con que emitir: los en mano más los nuevos, o solo los nuevos con fresh; los rangos reobtenidos que se conservan ocupan el lugar de los en mano de su tipo.

Paso de libros#

TypeScript
// La fase de libros.
function runBooks(
  deps: CertificationDependencies,
  state: CertificationState,
): Promise<StepResult<BooksOutcome>>
 
// El mes anterior a un período `AAAA-MM`.
function previousPeriod(period: string): string
 
// El primer período en o bajo `period` que el SII no tiene, bajando mes a mes, a lo más 400 veces.
function nextFreePeriod(period: string, occupied: ReadonlySet<string>): string
TipoDescripción
BooksOutcomeCómo terminó la fase de libros: todos los libros pedidos aprobados; un libro obligatorio nunca enviado; una declaración que el portal no tomó o libros que el SII rechazó; la espera de aprobación agotada. Definido como 'approved' | 'incomplete' | 'rejected' | 'timedOut'.

Intercambio y muestras impresas#

El intercambio y las muestras impresas se responden en dos portales que hablan GWT-RPC. Este grupo reúne las utilidades GWT, las operaciones de cada portal, las respuestas del intercambio y los dos pasos que usa el runner. Guía: Intercambio y muestras.

Catálogos#

TypeScript
// El portal de intercambio (`pfeInternet`): ahí se descarga el set de intercambio de la
// certificación y se suben sus respuestas.
const EXCHANGE_PORTAL: GwtPortal
 
// El portal de muestras impresas (`pdfdteInternet`), el validador automático del SII de los
// documentos impresos.
const SAMPLES_PORTAL: GwtPortal
 
// Los nombres de archivo de las respuestas del intercambio, como los nombran las subidas del
// portal: la respuesta de recepción, los recibos y la aprobación comercial.
const EXCHANGE_ANSWER_FILES: Readonly<Record<ExchangeAnswerKey, string>> = {
  reception: 'respuesta-recepcion-envio.xml',
  receipts: 'envio-recibos.xml',
  approval: 'respuesta-aprobacion-comercial.xml',
}
 
// Las respuestas del intercambio en orden de subida.
const EXCHANGE_ANSWER_KEYS: readonly ExchangeAnswerKey[] = ['reception', 'receipts', 'approval']
TipoDescripción
GwtPortalUn portal GWT del SII: la base de su módulo, la ruta e interfaz de su servicio RPC, el nombre de su módulo y el par de hashes que se sabe que funciona (capturado en junio de 2026; el SII cambia ambos al redesplegar el portal).
ExchangeAnswerKeyLas claves de las tres respuestas del intercambio. Definido como 'reception' | 'receipts' | 'approval'.

GWT#

TypeScript
// El cuerpo de petición de una llamada: `7|0|N|` + la tabla de strings + el cuerpo, cada ítem
// seguido de `|`.
function gwtBody(call: GwtCall): string
 
// Lee una respuesta: `//OK`, la tabla de strings, el mensaje, los tokens Long.
function gwtAnswer(body: string): GwtAnswer
 
// Un número en el alfabeto base 64 de GWT, el dígito más significativo primero (`264872` es
// `BAqo`).
function encodeGwtLong(value: number): string
 
// El número que contiene un token base 64 de GWT, o null si un carácter no está en el alfabeto.
function decodeGwtLong(token: string): number | null
 
// Los hashes de un portal GWT: el par del llamador si lo da; si no, se lee el `nocache.js` del
// módulo (los strings de 32 hexadecimales entre `=`, `'` o `,`): el par conocido vale si su
// permutación está listada, si no, la primera listada es la permutación y su `cache.html` da la
// política, el primer string de 32 hexadecimales entre comillas que no sea ella; cualquier falla,
// página vacía o candidato ausente deja el par conocido.
function discoverGwtHashes(context: PortalContext, input: GwtDiscoveryInput): Promise<GwtHashes>
TipoDescripción
GwtCallUna llamada GWT-RPC: adónde va y qué lleva.
GwtParameterUn parámetro de una llamada GWT-RPC, como lo serializan los portales del SII: un string (en la tabla, 0 si es null, o en un lugar propio si es distinct), un java.lang.Integer encajonado, un java.lang.Long encajonado (un número, o un token ya en el alfabeto base 64 de GWT), un booleano primitivo (Z), null (un String salvo que nombre su tipo declarado), o un objeto con sus campos en orden de serialización.
GwtAnswerUna respuesta GWT-RPC, leída.
GwtHashesLos dos hashes que un portal GWT exige en cada llamada.
GwtDiscoveryInputLo que necesita discoverGwtHashes: el módulo, el par que se sabe que funciona, y un par del llamador que gana.
GwtStageUna etapa de trabajo en un portal GWT: una entrada autenticada, un calentamiento y un par de hashes que comparten todas las llamadas de la etapa. Sus cookies viven solo lo que dura la etapa.

Campos de GwtDiscoveryInput

CampoTipoDescripción
moduleBasestringLa URL base del módulo, con su barra final.
moduleNamestringEl nombre del módulo (<name>.nocache.js).
knownGwtHashesEl par que se sabe que funciona.
override?GwtHashesUn par que el llamador conoce mejor; entonces no se consulta nada.

Portal de intercambio#

TypeScript
// Descarga el set de intercambio del portal de intercambio: el calentamiento y luego
// `downloadFile` con la empresa en la query y un cuerpo multipart vacío. La descarga no cambia la
// postulación.
function downloadExchangeSet(
  portal: PortalClient,
  input?: ExchangeCompanyInput,
  overrides?: CallOverrides,
): Promise<ExchangeSetDownload>
 
// Valida al usuario en el portal de intercambio: el calentamiento y luego `validarUsuario` con la
// empresa y el titular del certificado, sobre los hashes conocidos. La respuesta dice si la
// empresa está en la etapa de intercambio; no se exige `//OK`.
function validateExchangeUser(
  portal: PortalClient,
  input?: ExchangeGwtInput,
  overrides?: CallOverrides,
): Promise<ExchangeUserValidation>
 
// Sube las tres respuestas del intercambio, en el orden del portal: la respuesta de recepción a
// `uploadFile1`, los recibos a `uploadFile2`, la aprobación comercial a `uploadFile3`, cada una
// como una sola parte `uploadFormElement`.
function uploadExchangeAnswers(
  portal: PortalClient,
  input: UploadExchangeAnswersInput,
  overrides?: CallOverrides,
): Promise<ExchangeUploadResult>
 
// Confirma el intercambio en el portal: `validarSetContriPostSeguimiento` con la empresa (su
// respuesta se guarda, no se juzga) y luego `updatePostulacionSeguimiento` para los ids de
// seguimiento 40, 41 y 43, uno por respuesta subida, cada uno de los cuales debe responder `//OK`.
function confirmExchange(
  portal: PortalClient,
  input?: ExchangeGwtInput,
  overrides?: CallOverrides,
): Promise<ExchangeConfirmation>
 
// Ejecuta `run` en una etapa del portal de intercambio: la sesión asegurada, un calentamiento, y
// cada llamada que recibe la etapa enviada una vez sobre ella. La subida, la validación del
// usuario y la confirmación comparten una etapa.
function withExchangeStage<T>(
  portal: PortalClient,
  operation: string,
  overrides: CallOverrides | undefined,
  run: (stage: GwtStage) => Promise<T>,
  sessionChecked?: boolean,
): Promise<T>
TipoDescripción
ExchangeCompanyInputEntrada de las operaciones del intercambio que solo nombran a la empresa.
ExchangeGwtInputEntrada de las operaciones del intercambio que llaman al servicio del portal.
ExchangeSetDownloadLo que leyó downloadExchangeSet.
ExchangeUserValidationLo que leyó validateExchangeUser: el estado y la respuesta cruda, con los hashes usados, para las llamadas siguientes.
UploadExchangeAnswersInputEntrada de uploadExchangeAnswers: las tres respuestas en XML, firmadas.
ExchangeUploadAnswerLo que respondió una página de subida.
ExchangeUploadResultLo que hizo uploadExchangeAnswers.
ExchangeConfirmationAnswerLo que respondió una confirmación de seguimiento.
ExchangeConfirmationLo que hizo confirmExchange.
ExchangeUserStateLo que dijo el portal de intercambio al validar al usuario.

Campos de ExchangeCompanyInput

CampoTipoDescripción
companyRut?stringre + dve — RUT de la empresa; por defecto el del cliente.
stage?GwtStageLa etapa en que correr, de withExchangeStage; sin ella la llamada abre una etapa propia.

Campos de ExchangeGwtInput

CampoTipoDescripción
companyRut?stringre + dve — RUT de la empresa; por defecto el del cliente.
stage?GwtStageLa etapa en que correr, de withExchangeStage; sin ella la llamada abre una etapa propia.
gwt?GwtHashesLos hashes del portal, si el llamador conoce otros mejores que el par que se sabe que funciona, que es el de por defecto; nunca se buscan.

Campos de UploadExchangeAnswersInput

CampoTipoDescripción
companyRut?stringre + dve — RUT de la empresa; por defecto el del cliente.
stage?GwtStageLa etapa en que correr, de withExchangeStage; sin ella la llamada abre una etapa propia.
receptionstringRespuestaDTE/Resultado/RecepcionEnvio — La respuesta de recepción.
receiptsstringEnvioRecibos — Los recibos.
approvalstringRespuestaDTE/Resultado/ResultadoDTE — La aprobación comercial.

Portal de muestras#

TypeScript
// Lee la revisión de muestras impresas de la empresa: `leeImpreso` con el RUT de la empresa. El
// portal responde HTTP 200 con un estado, o con una frase cuando la postulación no está en la
// etapa de muestras impresas (antes de ella, y también después).
function readSamplesReview(
  portal: PortalClient,
  input?: ReadSamplesReviewInput,
  overrides?: CallOverrides,
): Promise<SamplesReview>
 
// Crea una revisión de muestras impresas: `creaLista` con la empresa como remitente y proveedor.
// El portal solo crea una cuando la revisión actual está `RECHAZADO` o `APROBADO`, o no hay
// ninguna; una revisión en `INGRESO` se retoma.
function createSamplesReview(
  portal: PortalClient,
  input?: SamplesCompanyInput,
  overrides?: CallOverrides,
): Promise<SamplesReviewCreated>
 
// Sube un PDF a una revisión: `POST upload` con las partes `Filedata` (el archivo), `id` (el id de
// la revisión en decimal) y `ambiente` (`false`), el referer el `cache.html` de la permutación.
// HTTP 200 es éxito.
function uploadSample(
  portal: PortalClient,
  input: UploadSampleInput,
  overrides?: CallOverrides,
): Promise<SampleUploaded>
 
// Envía una revisión al SII: `solicitaRevisionSII` con el token de la revisión. La respuesta es
// `//OK[0,[],0,7]` tanto si el SII acepta como si rechaza las muestras: el estado se lee de nuevo
// después.
function submitSamplesReview(
  portal: PortalClient,
  input: SamplesReviewInput,
  overrides?: CallOverrides,
): Promise<{ readonly body: string; }>
 
// Lee cómo clasificó el SII cada PDF de una revisión rechazada: `muestraMail` con el token de la
// revisión. Una falla se registra y entrega un detalle vacío: el rechazo se mantiene sin él.
function readSamplesDetail(
  portal: PortalClient,
  input: SamplesReviewInput,
  overrides?: CallOverrides,
): Promise<SamplesDetail>
 
// Ejecuta `run` en una etapa del portal de muestras: la sesión asegurada, un calentamiento, los
// hashes buscados una vez, y cada llamada que recibe la etapa enviada una vez sobre ella.
function withSamplesStage<T>(
  portal: PortalClient,
  operation: string,
  overrides: CallOverrides | undefined,
  run: (stage: GwtStage) => Promise<T>,
): Promise<T>
TipoDescripción
SamplesCompanyInputEntrada de las operaciones de muestras que nombran a la empresa.
ReadSamplesReviewInputEntrada de readSamplesReview.
SamplesReviewInputEntrada de las operaciones de muestras que nombran una revisión por su token.
SamplesReviewLo que leyó readSamplesReview.
SamplesReviewCreatedLo que hizo createSamplesReview.
UploadSampleInputEntrada de uploadSample.
SampleUploadedLo que hizo uploadSample.
SamplesDetailLo que leyó readSamplesDetail.
ReviewStateLos estados en que puede estar una revisión de muestras, como los escribe el portal. Definido como 'APROBADO' | 'POR REVISAR' | 'EN REVISION' | 'RECHAZADO' | 'INGRESO' | 'ENVIADO AL SII'.
SampleDetailUna fila del detalle del rechazo: cómo clasificó el SII un PDF.

Campos de SamplesCompanyInput

CampoTipoDescripción
companyRut?stringRUT de la empresa; por defecto el del cliente.
gwt?GwtHashesLos hashes del portal, si el llamador los conoce; si no, se descubren.
stage?GwtStageLa etapa en que correr, de withSamplesStage; sin ella la llamada abre una etapa propia.

Campos de ReadSamplesReviewInput

CampoTipoDescripción
companyRut?stringRUT de la empresa; por defecto el del cliente.
gwt?GwtHashesLos hashes del portal, si el llamador los conoce; si no, se descubren.
stage?GwtStageLa etapa en que correr, de withSamplesStage; sin ella la llamada abre una etapa propia.
anyStatus?booleanTrue para leer la respuesta sea cual sea su estado HTTP; por defecto cualquier estado distinto de 200 es inesperado.

Campos de SamplesReviewInput

CampoTipoDescripción
revisionTokenstringEl token Long de la revisión, como lo escribió el portal.
gwt?GwtHashesLos hashes del portal, si el llamador los conoce.
stage?GwtStageLa etapa en que correr, de withSamplesStage.

Campos de UploadSampleInput

CampoTipoDescripción
revisionIdnumberEl id de la revisión, en decimal.
fileNamestringEl nombre de archivo del PDF, enviado tal cual.
bytesUint8ArrayLos bytes del PDF.
gwt?GwtHashesLos hashes del portal, si el llamador los conoce.
stage?GwtStageLa etapa en que correr, de withSamplesStage.

Respuestas del intercambio#

TypeScript
// Arma y firma las tres respuestas a un set de intercambio, como las espera la certificación: la
// respuesta de recepción (el sobre recibido, cada documento recibido cuando su receptor es la
// empresa, si no "error en RUT receptor"), los recibos de la Ley 19.983 (uno por documento,
// firmados por el titular del certificado) y la aprobación comercial (aceptado cuando el receptor
// es la empresa, si no rechazado con `CodRchDsc` -1).
function createExchangeAnswers(setXml: string, input: CreateExchangeAnswersInput): ExchangeAnswers
 
// Lee el set de intercambio como lo lee el lector de campo, con tolerancia: no se comprueba que el
// XML esté bien formado y sus etiquetas se leen por su nombre completo, así que un sobre con
// prefijo no es un sobre; la raíz es `EnvioDTE`, `EnvioDTEB`, `EnvioDTETraslado` o `EnvioBOLETA`;
// el id del set (el atributo `ID`, si no un hijo `ID`, si no `SetDTE`), los RUT de la carátula y,
// por documento, su tipo (`TipoDTE` o `TpoDoc`), folio, fecha de emisión, emisor y receptor (los
// de la carátula cuando el documento no los nombra) y total.
function parseExchangeSet(setXml: string): ExchangeSet
TipoDescripción
ExchangeDocumentUn documento del set de intercambio, como lo describen las respuestas.
ExchangeSetEl set de intercambio que envía el SII: su id, su carátula y sus documentos.
ExchangeContactEl contacto que nombran las respuestas, cada campo opcional.
CreateExchangeAnswersInputEntrada de createExchangeAnswers.
ExchangeAnswerUna respuesta, lista para subir.
ExchangeAnswersLas tres respuestas del intercambio y el set que responden.
ExchangeStateLa etapa de intercambio: el set respondido y hasta dónde llegaron las respuestas.
SamplesStateLa etapa de muestras impresas: la revisión y lo que se subió a ella.

Campos de CreateExchangeAnswersInput

CampoTipoDescripción
companyRutstringRutResponde — La empresa que responde: el receptor que el SII espera en cada documento.
certificatePick<Certificate, 'privateKeyPem' | 'publicKey' | 'certificateBase64' | 'rut'>RutFirma — El certificado firmante; su titular firma los recibos.
contact?ExchangeContactEl contacto, si hay.
now?DateEl reloj; por defecto ahora.

Pasos#

TypeScript
// La etapa de intercambio: el set (dado, guardado de una corrida anterior, o descargado), las tres
// respuestas generadas y guardadas como artefactos, el usuario validado en el portal, las
// respuestas subidas y el intercambio confirmado, que mueve la postulación a las muestras
// impresas.
function runExchange(
  deps: CertificationDependencies,
  state: CertificationState,
  input?: RunExchangeInput,
): Promise<StepResult<ExchangeOutcome>>
 
// El artefacto que guarda el set de intercambio; el llamador lo llena a mano cuando falla la
// descarga.
const EXCHANGE_SET_ARTEFACT: "intercambio/set-intercambio.xml"
 
// La etapa de muestras impresas: la revisión leída (un bloqueo o una revisión ya enviada terminan
// aquí), retomada cuando está en `INGRESO` con un id legible o creada si no, cada PDF subido en
// orden (cada nombre guardado sobre la marcha), la revisión enviada, y su estado leído de nuevo
// (una lectura fallida se advierte y deja el estado desconocido): `RECHAZADO` trae el detalle y su
// resumen.
function uploadPrintedSamples(
  deps: CertificationDependencies,
  state: CertificationState,
  input: UploadPrintedSamplesInput,
): Promise<StepResult<SamplesOutcome>>
TipoDescripción
RunExchangeInputEntrada de runExchange.
ExchangeOutcomeCómo terminó runExchange: done con las respuestas subidas y confirmadas; alreadyDone cuando el estado o el portal dicen que el intercambio ya se completó; setUnavailable cuando el set no se pudo descargar (el artefacto que nombra el detalle debe llenarse a mano); notInExchange cuando el portal dice que la empresa no está en la etapa. Definido como 'done' | 'alreadyDone' | 'setUnavailable' | 'notInExchange'.
UploadPrintedSamplesInputEntrada de uploadPrintedSamples.
SamplesOutcomeCómo terminó uploadPrintedSamples: submitted con la revisión enviada al SII; alreadySubmitted cuando ya se había enviado una revisión (su estado en el detalle); blocked cuando el portal dice que la postulación no está en la etapa; rejected cuando el SII rechazó la revisión de inmediato (el resumen en el detalle). Definido como 'submitted' | 'alreadySubmitted' | 'blocked' | 'rejected'.
PrintedSampleFileUn archivo de muestra como lo sube la certificación: su nombre base y sus bytes.

Campos de RunExchangeInput

CampoTipoDescripción
setXml?stringEl set de intercambio, cuando el llamador lo tiene (descargado a mano del portal).

Campos de UploadPrintedSamplesInput

CampoTipoDescripción
samplesreadonly PrintedSampleFile[]Los PDF a subir, en orden; readPrintedSamples los lee de un directorio.

Runner#

runCertification corre el lado HTML de la certificación en el orden de las etapas (sets de pruebas, libros, simulación, intercambio, muestras impresas, declaración de cumplimiento), retomando desde el estado guardado, y se detiene con un RunStop. La declaración de cumplimiento es irreversible y solo se hace con declareCompliance: true. Guía: Runner.

TypeScript
// El lado HTML de la certificación, en el orden de las etapas, retomado desde el estado guardado:
// el set de pruebas (descargado una vez), los folios, cada set aún no enviado, su declaración y
// aprobación; los libros; el avance; la simulación enviada, declarada y confirmada; el set de
// intercambio respondido, subido y confirmado; las muestras impresas subidas y enviadas cuando la
// opción `samples` las da (si no, se detiene ahí); y luego declara cumplimiento, solo con
// `declareCompliance: true`, porque esa declaración no se puede deshacer.
function runCertification(
  dependencies: CertificationDependencies,
  options?: RunCertificationOptions,
): Promise<RunCertificationResult>
TipoDescripción
RunCertificationOptionsOpciones de runCertification.
RunCertificationResultLo que devuelve runCertification.
RunStopPor qué se detuvo el ejecutor. Definido como | 'done' | 'exchange' | 'printedSamples' | 'compliance' | 'until' | 'blocked' | 'rejected' | 'timedOut' | 'incomplete'.

Campos de RunCertificationOptions

CampoTipoDescripción
until?CertificationStageDetenerse al completar esta etapa.
optionalSets?readonly string[]Los sets opcionales a marcar al descargar; por defecto DEFAULT_OPTIONAL_SETS.
declareCompliance?booleanHacer la declaración de cumplimiento, la declaración jurada del representante legal, que no se puede deshacer. Apagado por defecto: el ejecutor se detiene en compliance.
exchangeSetXml?stringEl set de intercambio, cuando se descargó a mano del portal.
samples?readonly PrintedSampleFile[] | (() => Promise<readonly PrintedSampleFile[]>)Las muestras impresas a subir, o una función que las lee (readPrintedSamples); sin ellas el ejecutor se detiene en printedSamples.

Campos de RunCertificationResult

CampoTipoDescripción
stateCertificationStateEl estado tal como quedó guardado.
stoppedRunStopPor qué se detuvo.
detail?stringUna palabra o frase sobre el porqué, cuando la hay.

Certificación de boletas#

La certificación de boletas es una aplicación aparte y no tiene runner: son piezas que tú encadenas. Una boleta (39, 41) lleva receiptReferences, nunca references. Guía: Boletas.

Set de pruebas#

TypeScript
// El portal de boletas (`certBolElectDteInternet`), donde corre la certificación de boletas
// electrónicas. Sus hashes no se descubren: `moduleName` es lo que sugiere su interfaz, no un dato
// registrado.
const RECEIPTS_PORTAL: GwtPortal
 
// Parsea el set de pruebas de boletas que entrega el portal de boletas, un texto plano.
function parseReceiptsTestSet(text: string): readonly ReceiptsTestCase[]
TipoDescripción
ReceiptsTestCaseUn caso del set de pruebas de boletas: una boleta por emitir.
ReceiptsTestItemUn ítem de un caso del set de pruebas de boletas.

Emisión#

TypeScript
// Emite el set de pruebas de boletas: una boleta tipo 39 por caso, en orden, cada una con el
// siguiente folio de la fuente, el consumidor final como receptor, los precios del set tomados con
// IVA incluido, la exención de un ítem exento, la unidad de medida que nombra una observación en
// su primer ítem, y una referencia con el código `SET` y la razón `CASO-<n>`; luego firma el
// `EnvioBOLETA` que las lleva, con el titular del certificado como enviador (el emisor cuando el
// certificado no nombra ninguno) y el SII como receptor.
function issueReceiptsSet(
  cases: readonly ReceiptsTestCase[],
  options: IssueReceiptsSetOptions,
): Promise<IssuedReceiptsSet>
TipoDescripción
IssueReceiptsSetOptionsLo que necesita emitir el set de boletas.
IssuedReceiptUna boleta emitida del set.
IssuedReceiptsSetEl set de boletas emitido: sus boletas en orden de caso y el sobre firmado que las lleva.

Campos de IssueReceiptsSetOptions

CampoTipoDescripción
issuerCertificationIssuerInputEmisor — El emisor, como en un documento; lo que omita toma los valores de DEFAULT_CERTIFICATION_ISSUER. El RUT, la razón social y la dirección no los tienen.
certificateCertificateRutEnvia — El certificado de firma; su titular es quien envía el sobre.
foliosFolioSourceDe dónde salen los folios del tipo 39 y sus CAF.
resolution?{ readonly number?: number; readonly date?: string }NroResol, FchResol — La resolución del ambiente de certificación; por defecto número 0 y la fecha UTC del instante, campo por campo.
now?() => DateFchEmis, TSTED, TmstFirma, TmstFirmaEnv — Reloj, leído una vez para la fecha de emisión (su fecha UTC), una vez por boleta para sus marcas (el instante UTC al segundo) y una vez para el sobre (la hora de Chile).

Envío#

TypeScript
// Envía el set de boletas: sube el sobre y lee la respuesta (`STATUS` 0 con track id es enviado;
// `STATUS` 7 con track id también se toma como enviado, y sin él es un duplicado que salta al
// reporte sin track id; `STATUS` 99 y cualquier otra respuesta es una falla y lanza), espera 20 s
// y lee una vez el estado de un sobre enviado (un rechazo termina aquí; una consulta que nunca
// llegó se registra, y una respuesta sin estado, o con uno desconocido, no bloquea nada), y luego
// envía el reporte de consumo de folios armado desde el sobre, con la secuencia `sequence` más el
// intento, hasta diez intentos: un `STATUS` 7 sin track id es un duplicado y tres seguidos
// significan que el reporte de hoy ya se aceptó; un `STATUS` 99 u otro rechazo lo termina como
// `consumptionFailed`; a un reporte subido se le dan 30 s y se lee su estado una vez: un éxito o
// un estado intermedio (también un código de error de la consulta o `0`) lo acepta, una consulta
// que nunca llegó lo acepta, y cualquier otra cosa (un rechazo, ningún estado, un estado
// desconocido) prueba la secuencia siguiente, salvo que su glosa hable de autorización o firma.
function sendReceiptsSet(
  sii: SiiClient,
  issued: { readonly envelope: SignedEnvelope; },
  options?: SendReceiptsSetOptions,
): Promise<ReceiptsSendResult>
 
// Arma de nuevo el reporte de consumo de folios desde un sobre de boletas ya enviado y lo sube una
// vez, con la secuencia dada.
function resendReceiptsConsumption(
  sii: SiiClient,
  input: ResendReceiptsConsumptionInput,
): Promise<{ readonly sequence: number; readonly xml: string; readonly trackId: string; readonly duplicate: boolean; }>
TipoDescripción
ReceiptsProgressEventLos eventos de progreso de sendReceiptsSet, con los nombres de sus pasos. Definido como { readonly step: 'BOLETA_SOAP_CHECK' } | { readonly step: 'BOLETA_RCOF' }.
SendReceiptsSetOptionsOpciones de sendReceiptsSet.
ReceiptsConsumptionAttemptUn reporte de consumo de folios intentado.
ReceiptsSendResultLo que hizo sendReceiptsSet.
ResendReceiptsConsumptionInputEntrada de resendReceiptsConsumption.

Campos de SendReceiptsSetOptions

CampoTipoDescripción
sequence?numberSecEnvio — La secuencia del primer reporte de consumo de folios; 100 por defecto (también si es 0), y cada intento suma uno.
sleep?(ms: number) => Promise<void>Función de espera; por defecto la del cliente.
onProgress?(event: ReceiptsProgressEvent) => voidEventos de progreso.

Campos de ReceiptsSendResult

CampoTipoDescripción
outcome'sent' | 'envelopeRejected' | 'consumptionFailed'Cómo terminó.
notAuthorizedbooleanLa glosa del SII o el error habla de autorización o firma: la empresa aún no puede firmar boletas.
envelopeTrackIdstring | nullTrackId — El track id del sobre, para declararlo en el portal de boletas; null cuando el SII ya tenía el sobre y no nombró ninguno.
envelopeDuplicatebooleanEl SII ya tenía el sobre.
consumptionTrackIdstring | nullEl track id del reporte aceptado, o null.
consumptionSequencenumber | nullSecEnvio del reporte aceptado, o null.
consumptionAlreadySentbooleanTres reportes seguidos fueron duplicados: ya se aceptó uno hoy.
consumptionsreadonly ReceiptsConsumptionAttempt[]Cada reporte intentado, en orden.
detail?stringLa glosa o el error que lo terminó, cuando no terminó en sent.

Campos de ResendReceiptsConsumptionInput

CampoTipoDescripción
envelopeXmlstringEnvioBOLETA — El sobre de boletas tal como se envió.
sequencenumberSecEnvio — La secuencia del reporte.

Portal#

TypeScript
// Descarga el set de pruebas de boletas.
function downloadReceiptsTestSet(
  portal: PortalClient,
  input?: DownloadReceiptsTestSetInput,
  overrides?: CallOverrides,
): Promise<ReceiptsTestSetDownload>
 
// Declara el track id del sobre de boletas, para que el SII valide el set (`ingresarTrackId`), tal
// como se da. Se envía una vez.
function declareReceiptsTrackId(
  portal: PortalClient,
  input: ReceiptsPortalInput & { readonly trackId: string; },
  overrides?: CallOverrides,
): Promise<{ readonly body: string; }>
 
// Lee el estado de la postulación de boletas: si la empresa está inscrita (tiene representantes
// vigentes), si el SII aprobó el set (`P90`, lista para declarar) y si la declaración ya se hizo
// (`P91`).
function readReceiptsStatus(
  portal: PortalClient,
  input?: ReceiptsPortalInput,
  overrides?: CallOverrides,
): Promise<ReceiptsStatus>
 
// Hace la declaración de cumplimiento de la postulación de boletas, que autoriza a la empresa a
// emitir boletas en producción (`autorizarEmpresaBolProd`). No se puede deshacer.
function declareReceiptsCompliance(
  portal: PortalClient,
  input: DeclareReceiptsComplianceInput,
  overrides?: CallOverrides,
): Promise<ReceiptsComplianceResult>
 
// Lee si la empresa puede emitir boletas. En producción, un GET de la página de entrada del
// timbraje y un POST de su formulario con la empresa, y el tipo 39 entre los valores de opción
// entre comillas de la respuesta (que debe tener un selector).
function verifyReceiptsAuthorization(
  input: VerifyReceiptsAuthorizationInput,
): Promise<ReceiptsAuthorization>
TipoDescripción
ReceiptsPortalInputLo que recibe cada operación del portal de boletas.
DownloadReceiptsTestSetInputEntrada de downloadReceiptsTestSet.
ReceiptsTestSetDownloadLo que leyó downloadReceiptsTestSet.
ReceiptsStatusEl estado de la postulación de boletas.
ReceiptsProviderEl proveedor de software que nombra la declaración.
DeclareReceiptsComplianceInputEntrada de declareReceiptsCompliance.
ReceiptsComplianceResultCómo terminó declareReceiptsCompliance.
VerifyReceiptsAuthorizationInputEntrada de verifyReceiptsAuthorization.
ReceiptsAuthorizationCheckUn lado de verifyReceiptsAuthorization. queryFailed significa que el portal no respondió la pregunta: nunca es "no autorizada".
ReceiptsAuthorizationLo que leyó verifyReceiptsAuthorization; un lado es null cuando no se entregó su cliente.
ReceiptsProgressLa fila de boletas de la página de avance.

Campos de ReceiptsPortalInput

CampoTipoDescripción
companyRut?stringRUT de la empresa; por defecto el del cliente.
gwt?GwtHashesLos hashes del portal, cuando el par que se sabe que funciona quedó obsoleto.
sessionChecked?booleanTrue cuando una operación anterior de la misma corrida ya comprobó la sesión guardada.

Campos de DownloadReceiptsTestSetInput

CampoTipoDescripción
companyRut?stringRUT de la empresa; por defecto el del cliente.
gwt?GwtHashesLos hashes del portal, cuando el par que se sabe que funciona quedó obsoleto.
sessionChecked?booleanTrue cuando una operación anterior de la misma corrida ya comprobó la sesión guardada.
providerMail?stringmailProvSw — El correo del proveedor de software que el portal pide con el set.

Campos de DeclareReceiptsComplianceInput

CampoTipoDescripción
companyRut?stringRUT de la empresa; por defecto el del cliente.
gwt?GwtHashesLos hashes del portal, cuando el par que se sabe que funciona quedó obsoleto.
sessionChecked?booleanTrue cuando una operación anterior de la misma corrida ya comprobó la sesión guardada.
providerReceiptsProviderEl proveedor de software; una empresa que es su propio proveedor se pasa a sí misma.
businessNamestringLa razón social de la empresa.
link?stringEl link de consulta; por defecto www.sii.cl.

Campos de VerifyReceiptsAuthorizationInput

CampoTipoDescripción
production?PortalClientUn cliente en producción, para leer el formulario de timbraje.
certification?PortalClientUn cliente en certificación, para leer la página de avance (pe_avance6).
companyRut?stringRUT de la empresa; por defecto el de cada cliente.
sessionChecked?booleanTrue cuando una operación anterior de la misma corrida ya comprobó las sesiones guardadas.