dte-sdk
A zero-dependency TypeScript SDK for Chilean electronic tax documents (DTE): build, stamp, sign and send invoices, receipts, dispatch guides and credit or debit notes to the SII, from one small typed API.
Pre-release. The published dte-sdk@0.0.2 is a placeholder that only
exports hello(). These pages document the planned 1.0 API: names and
signatures may still change before it ships. Follow progress on
GitHub.
Why dte-sdk#
Issuing a DTE means getting many small things exactly right: an XML schema, ISO-8859-1 encoding, IVA rounded to whole pesos, an electronic stamp signed with the CAF key, an XMLDSig signature made with your certificate, and an authentication handshake with the SII before you can upload anything. dte-sdk turns each of those into one focused function:
createDte() checks RUTs, amounts and required fields up front and
returns an immutable document. Mistakes fail in your code, not days
later at the SII.
Integer CLP, half-up rounding, 19% IVA, exempt lines and gross-price receipts, computed the same way every time.
TED generation with your CAF and XMLDSig signing over Web Crypto. The same code runs on Node, Deno, Bun and the browser.
Error messages never include RUTs, amounts, CAF keys or certificate passwords. Zero runtime dependencies, about 8.4 KB min+gzip.
The lifecycle at a glance#
Every document goes through the same five steps. Each function takes the result of the previous one, and the types keep you from skipping a step: you can't sign a document that hasn't been stamped, or send one that hasn't been signed.
| Step | Function | What happens |
|---|---|---|
| 1. Build | createDte() | Validates the input and computes the totals |
| 2. Stamp | stampDte() | Generates the TED (electronic stamp) with the CAF that covers the folio |
| 3. Sign | signDte() | Signs the document with your digital certificate (XMLDSig) |
| 4. Send | sendToSii() | Wraps it in an EnvioDTE, authenticates and uploads it; returns a track id |
| 5. Track | getStatus() | Asks the SII whether the document was accepted |
calculateTotals() and toXml() are helpers you can call at any step, while parseCaf() and loadCertificate() load the two credentials the pipeline needs. That's the whole surface: nine functions.
Quick example#
import { createDte, DTE_TYPES } from 'dte-sdk'
const invoice = createDte({
type: 33,
folio: 1024,
issuer: {
rut: '76.123.456-0',
businessName: 'Arrow Software SpA',
activity: 'Desarrollo de software',
acteco: 620200,
address: 'Av. Providencia 1234',
commune: 'Providencia',
},
receiver: {
rut: '77.654.321-7',
businessName: 'Comercial Los Andes Ltda.',
activity: 'Comercio al por menor',
address: 'Huérfanos 1055',
commune: 'Santiago',
},
items: [{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }],
})
DTE_TYPES[invoice.type] // 'Factura electrónica'
invoice.totals // { net: 120000, exempt: 0, vatRate: 19, vat: 22800, total: 142800 }From here, stampDte(), signDte() and sendToSii() take the document the rest of the way. The Quick Start walks through all five steps.
What you'll need#
The package handles the format, the cryptography and the transport. To issue documents the SII will accept, you also need three things only the SII and a certification provider can give you:
- A CAF for each document type you issue: the file that authorizes a range of folios.
- A digital certificate (
.pfxor.p12) belonging to a person authorized to sign for the company. - Authorization as an electronic issuer: the SII resolution number and date, or access to the certification environment while you test.
Core Concepts explains each one. The first two are secrets: read Security before you put them on a server.
Where to next#
Install with npm, pnpm, bun or yarn, and check your setup.
Quick StartIssue a type 33 invoice end to end, from build to acceptance.
Core ConceptsDTE types, folios and CAF, the TED, certificates and SII states.
FeaturesEach step of the lifecycle in depth.
ExamplesComplete invoice and credit note flows you can copy.
API ReferenceEvery signature, type, constant and error code.
License#
MIT © Arrow Software. Free for personal and commercial use, including closed-source and paid products, with no usage limit and no attribution required beyond keeping the license notice.