createDte()
Builds an immutable, validated electronic tax document with its totals already calculated. It is the first step of every DTE lifecycle.
Basic Usage#
import { createDte } from 'dte-sdk'
const dte = createDte({
type: 33,
folio: 1024,
issuedAt: '2026-10-28',
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.totals
// { net: 120000, exempt: 0, vatRate: 19, vat: 22800, total: 142800 }Type Signature#
function createDte(input: CreateDteInput): Dte
type DteType = 33 | 34 | 39 | 41 | 46 | 52 | 56 | 61
interface CreateDteInput {
type: DteType
folio: number
issuedAt?: string // 'YYYY-MM-DD', defaults to today in America/Santiago
issuer: {
rut: string
businessName: string
activity: string
acteco: number | number[]
address: string
commune: string
city?: string
}
receiver: {
rut: string
businessName: string
activity?: string
address?: string
commune?: string
city?: string
email?: string
}
items: LineItem[] // 1..60 lines
references?: Reference[] // required for 56 and 61
paymentMethod?: 'cash' | 'credit' | 'free'
dueDate?: string
}
interface LineItem {
name: string
description?: string
quantity: number
unitPrice: number
unit?: string
discountPercent?: number
exempt?: boolean
}
interface Reference {
type: DteType | 'SET'
folio: number | string
date: string
code?: 1 | 2 | 3 // 1 = voids document, 2 = fixes text, 3 = fixes amounts
reason?: string
}
// Dte = CreateDteInput with resolved defaults + `totals: Totals`, deeply readonlyParameters#
input.type(DteType) - The document type code. See Document types below.input.folio(number) - The document number, a positive integer from a CAF range you hold for this type.stampDte()checks it against the CAF.input.issuedAt(string, optional) - Issue date asYYYY-MM-DD. Defaults to today in theAmerica/Santiagotime zone, not the server's.input.issuer- Your company, as registered with the SII:rut- The issuer RUT, with or without dots.businessName- Legal name (razón social).activity- Business line (giro).acteco(number | number[]) - One or more economic activity codes.address,commune- Street address and commune of origin.cityis optional.
input.receiver- The customer.rutandbusinessNameare required;activity,address,commune,cityandemailare optional.input.items(LineItem[]) - Between 1 and 60 detail lines:name- What you sell.descriptionadds a longer text.quantity,unitPrice- Quantity and net unit price in CLP (gross on receipts, seecalculateTotals()).unit(optional) - Unit of measure, such as'UN'or'KG'.discountPercent(optional) - Line discount from 0 to 100.exempt(optional) -truewhen the line is not subject to IVA.
input.references(Reference[]) - Other documents this one refers to. Required for debit notes (56) and credit notes (61).type,folio,date- The referenced document. Use'SET'as the type to reference a certification test set.code-1voids the referenced document,2fixes text,3fixes amounts.reason- Free text explaining the reference.
input.paymentMethod(optional) -'cash','credit'or'free'(no charge).input.dueDate(optional) - Payment due date asYYYY-MM-DD.
Return Value#
Returns a Dte: your input with its defaults resolved (issuedAt is always set) plus a totals object, calculated with the same rules as calculateTotals().
The document is immutable. Its type is deeply readonly and the object is frozen, so every later step (stamping, signing) returns a new object instead of changing this one.
Errors#
createDte() throws a DteError when the input can't become a valid document:
| Code | When |
|---|---|
MISSING_FIELD | A required field is missing or empty, including items and, for types 56 and 61, references |
INVALID_RUT | The issuer or receiver RUT is malformed or its Modulo 11 check digit is wrong |
INVALID_AMOUNT | A quantity is not a positive number, a unit price is negative or not finite, or a discount is outside 0–100 |
Messages are generic on purpose: they never include RUTs or amounts. Branch on error.code, not on the message.
import { createDte, DteError } from 'dte-sdk'
try {
createDte(input)
} catch (error) {
if (error instanceof DteError && error.code === 'INVALID_RUT') {
// Ask the user to check the customer's RUT
} else {
throw error
}
}Examples#
Exempt Lines#
Mark a line with exempt: true and it goes to totals.exempt instead of the taxable net:
import { createDte } from 'dte-sdk'
// `issuer` and `receiver` as in Basic Usage
const dte = createDte({
type: 33,
folio: 1024,
issuer,
receiver,
items: [
{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 },
{ name: 'Curso de capacitación', quantity: 2, unitPrice: 45000, exempt: true },
],
})
dte.totals
// { net: 120000, exempt: 90000, vatRate: 19, vat: 22800, total: 232800 }Credit Note With a Reference#
Credit and debit notes must point at the document they modify:
import { createDte } from 'dte-sdk'
const creditNote = createDte({
type: 61,
folio: 501,
issuer,
receiver,
items: [{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }],
references: [
{ type: 33, folio: 1024, date: '2026-10-28', code: 1, reason: 'Anula factura' },
],
})Leave out references on a type 61 and createDte() throws MISSING_FIELD. See Issue a Credit Note for the full flow.
Credit Sale With a Due Date#
const dte = createDte({
type: 33,
folio: 1025,
issuer,
receiver,
items: [{ name: 'Licencia anual', quantity: 1, unitPrice: 120000 }],
paymentMethod: 'credit',
dueDate: '2026-11-27',
})Immutability#
dte.folio = 1026 // ✗ TypeScript error: 'folio' is a read-only property
// Build a new document instead
const next = createDte({ ...input, folio: 1026 })Document Types#
dte-sdk supports eight document types. DTE_TYPES maps each code to its official Spanish name:
| Code | Document |
|---|---|
33 | Electronic invoice |
34 | Exempt electronic invoice |
39 | Electronic receipt |
41 | Exempt electronic receipt |
46 | Electronic purchase invoice |
52 | Electronic dispatch guide |
56 | Electronic debit note |
61 | Electronic credit note |
import { DTE_TYPES } from 'dte-sdk'
DTE_TYPES[33] // 'Factura electrónica'
DTE_TYPES[61] // 'Nota de crédito electrónica'Related Functions#
calculateTotals()- The rules behinddte.totalsstampDte()- Next step: add the electronic stamptoXml()- Preview the document as XML