Core Concepts
A short, practical primer on Chile's electronic invoicing system: the vocabulary you'll meet in SII documentation and in the dte-sdk API. You don't need to memorize it, but knowing what a CAF or a TED is makes every error code easier to read.
What is a DTE?#
A DTE (Documento Tributario Electrónico) is a tax document (an invoice, a receipt, a dispatch guide or a note) issued as a signed XML file and reported to Chile's tax authority, the SII (Servicio de Impuestos Internos). The XML is the legal document. A printed or PDF copy is only a representation of it, and carries a barcode so anyone can check it against the original.
A DTE is identified by three values: the issuer's RUT, the document type and the folio. The combination is unique: the SII won't accept two documents that share all three.
Document types#
The type is a numeric code. dte-sdk supports eight of them:
| Code | Document | Typical use | Totals in dte-sdk |
|---|---|---|---|
| 33 | Electronic invoice (Factura electrónica) | Taxable sales between businesses | Net prices + 19% IVA |
| 34 | Exempt electronic invoice (Factura no afecta o exenta electrónica) | Sales exempt from or not subject to IVA | Fully exempt |
| 39 | Electronic receipt (Boleta electrónica) | Sales to final consumers | Prices include IVA |
| 41 | Exempt electronic receipt (Boleta exenta electrónica) | Exempt sales to final consumers | Fully exempt |
| 46 | Electronic purchase invoice (Factura de compra electrónica) | Issued by the buyer when the seller can't invoice | Net prices + 19% IVA |
| 52 | Electronic dispatch guide (Guía de despacho electrónica) | Moving goods, with or without a sale | Net prices + 19% IVA |
| 56 | Electronic debit note (Nota de débito electrónica) | Increasing or correcting a previous document | Net prices + 19% IVA |
| 61 | Electronic credit note (Nota de crédito electrónica) | Voiding, reducing or correcting a previous document | Net prices + 19% IVA |
In any type, individual lines can be marked exempt: true to keep them out of the IVA base. The DTE_TYPES constant maps each code to its official Spanish name, which is the one to print on the document.
Folios and the CAF#
The folio is the document's number within its type. You don't pick folios freely: the SII authorizes them in ranges, per document type, through a CAF (Código de Autorización de Folios). A CAF is an XML file that contains:
- the issuer's RUT and the document type it covers,
- the authorized range, for example folios 1001 to 2000,
- the authorization date and the SII's own signature over all of the above,
- an RSA key pair. The private key is what you use to stamp each document.
A few rules follow from that:
- One folio, one document. Keep track of the folios you use, ideally in the same transaction that stores the document, so two processes can't stamp the same one.
- One CAF, one type and one issuer. Stamping a credit note with an invoice CAF fails with
CAF_MISMATCH. - CAFs expire. Folios left in an expired CAF can't be used;
stampDte()throwsCAF_EXPIRED. Request ranges that match your volume and ask for the next CAF before you run out.
import { readFile } from 'node:fs/promises'
import { parseCaf } from 'dte-sdk'
const caf = parseCaf(await readFile('./caf/33.xml', 'latin1'))
caf.type // 33
caf.issuerRut // '76.123.456-0'
caf.range // { from: 1001, to: 2000 }
caf.expiresAt // after this date, stampDte() throws CAF_EXPIREDA CAF contains a private key. Treat the file like a password: keep it out of your repository and off the client. See Security.
The TED and the PDF417 barcode#
The TED (Timbre Electrónico DTE, the electronic stamp) is a small signed block inside every DTE. It holds a summary of the key fields (issuer and receiver RUT, type, folio, date, total and the first line item) together with the CAF, and it's signed with the CAF's private key. Because the CAF carries the SII's signature, the TED proves the folio was authorized, and the summary ties that proof to this particular document.
The TED is also the part that gets printed. On the paper or PDF version it appears as a PDF417 barcode, so a receiver or an inspector can scan it and check the document without going online.
stampDte() produces both: ted (the XML block) and pdf417 (the payload to hand to a barcode renderer). dte-sdk doesn't render PDFs or barcodes itself.
The digital certificate#
The TED proves the folio; the XML signature proves who issued the document. Every DTE is signed with XMLDSig using a digital certificate: a .pfx or .p12 file plus its password, issued by an accredited provider to a natural person who is authorized before the SII to sign on the company's behalf.
The same certificate authenticates you against the SII's web services. To send documents or check their status, the client signs a one-time seed issued by the SII and exchanges it for a short-lived token. sendToSii() and getStatus() handle that handshake and cache the token per certificate.
Because the certificate belongs to a person, its owner's RUT is usually different from the company's. That's the senderRut you pass to sendToSii().
Certification and production#
The SII runs two separate environments:
- Certification is a test environment. Companies become electronic issuers by completing a certification process there, which includes issuing a test set (set de pruebas) of documents defined by the SII. Documents sent to certification have no tax effect.
- Production is the real thing. Every document accepted there is a legal tax document.
The two share nothing: a CAF requested in certification only works in certification, and track ids from one environment mean nothing in the other.
| Certification | Production | |
|---|---|---|
environment | 'certification' | 'production' |
| CAF | Requested in certification | Requested in production |
resolution.number | 0 | The number of your SII resolution |
| Tax effect | None | Legal document |
dte-sdk has no default environment: you pass it explicitly to sendToSii() and getStatus(), so a test can't reach production by accident.
SII acceptance states#
Sending isn't the same as being accepted. sendToSii() returns as soon as the SII has received the upload, with a track id. The SII then checks the schema, the signatures, the TED and its business rules asynchronously, and getStatus() reports where things stand:
state | Meaning | What to do |
|---|---|---|
received | Uploaded, still being processed | Ask again later |
accepted | Valid, no observations | Done: deliver the document to the receiver |
accepted_with_objections | Valid, with observations (reparos) | It's issued; read the reason and fix your data for next time |
rejected | Not valid | It has no tax effect; fix the cause and issue it again |
One upload can carry several documents, so the status also lists a result per document, with a reason whenever a document has objections or was rejected.
References: credit and debit notes#
Credit notes (61) and debit notes (56) don't stand alone: they modify a document that already exists, so they must reference it. createDte() requires at least one reference for these types and throws MISSING_FIELD without one.
A reference identifies the original document by type, folio and date, and its code says what the note does:
code | Meaning | Typical use |
|---|---|---|
1 | Voids the referenced document | Cancel an invoice in full |
2 | Corrects text | Fix the receiver's business name or address; no amounts change |
3 | Corrects amounts | A partial refund, a later discount, a price fix |
import { createDte } from 'dte-sdk'
// `invoice` is the type 33 document from the Quick Start.
const creditNote = createDte({
type: 61,
folio: 501,
issuer: invoice.issuer,
receiver: invoice.receiver,
items: [{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }],
references: [
{ type: 33, folio: 1024, date: '2026-10-28', code: 1, reason: 'Anula factura' },
],
})
creditNote.totals.total // 142800, the full amount of the voided invoiceThe note needs its own folio from a type 61 CAF. In certification, documents issued for the SII's test set also carry a reference of type 'SET' that identifies the test case.
Glossary#
| Term | Meaning |
|---|---|
| DTE | Documento Tributario Electrónico: a tax document issued as signed XML |
| SII | Servicio de Impuestos Internos: Chile's tax authority |
| RUT | Rol Único Tributario: the tax ID of a company or person, with a Modulo 11 check digit |
| Folio | The document's number within its type |
| CAF | Código de Autorización de Folios: the file that authorizes a folio range and holds the stamping key |
| TED | Timbre Electrónico DTE: the signed stamp inside each document |
| PDF417 | The barcode format used to print the TED |
| EnvioDTE | The signed envelope that carries one or more DTEs to the SII |
| Track id | The number the SII assigns to an upload, used to check its status |
| IVA | Impuesto al Valor Agregado: Chile's value-added tax, 19% |