Skip to content

Examples

End-to-end flows you can copy and adapt. Each one goes from raw input to a document the SII has accepted, including storage, retries and error handling.

These examples use the planned 1.0 API. The published 0.0.2 is a placeholder, and details may change before 1.0.

Start with the invoice: the credit note reuses its modules and corrects the invoice it issues.

Three Rules Both Examples Follow#

Never Reuse a Folio#

Every document of a type gets its own folio from the CAF range. Allocate it in the same transaction that stores the document, so a validation error doesn't burn one:

TypeScript
const signed = await db.transaction(async (tx) => {
  const folio = await tx.folios.next(33)
  const signed = await buildInvoice({ folio, receiver, items })
  await tx.invoices.insert({ folio, xml: signed.xml, state: 'signed' })
  return signed
})

Store Before You Send#

The signed XML is the legal document. Persist it first, then send, then persist the track id:

TypeScript
const { trackId } = await sendToSii(signed, { certificate, ...SII })
await db.invoices.update(signed.folio, { trackId, state: 'sent' })

Branch on the Code#

Every failure is a DteError with a stable code. Messages are generic and never include RUTs or amounts, so don't parse them:

TypeScript
import { DteError } from 'dte-sdk'
 
if (error instanceof DteError && error.code === 'SII_UNAVAILABLE') {
  // keep the document as 'signed' and retry the upload later
}

Run both examples with SII_ENVIRONMENT=certification until the SII authorizes you for production. The code is the same in both environments.