eu-einvoice-canonical documentation
Contributing | Code of Conduct | Security | Changelog
One TypeScript model for every XML e-invoice you can receive from the 27 EU member states, plus the layer that gets you from a received file to “this is format X, version Y”: unwrapping (PDF/A-3, .p7m, ZIP, SBDH, SOAP, legacy encodings), detection, and parsing into canonical JSON.
Try it in the browser: alexcatdad.github.io/eu-einvoice-canonical. Drop an invoice and get the JSON. The page runs the same code as the library, entirely client-side; files are never uploaded.
Status:
- Every parser family is implemented: UBL (Peppol BIS 3 and self-billing, PINT, XRechnung, NLCIUS, CIUS-RO, CIUS-PT, HR-CIUS, OIOUBL, plain EN 16931), CII (Factur-X/ZUGFeRD 2 in every profile, XRechnung CII), Svefaktura 1.0, FatturaPA, KSeF FA(2)/FA(3)/FA_RR, Facturae, ISDOC, ebInterface, Finvoice, e-arve, eSLOG 2.0, ZUGFeRD 1.0, TEAPPSXML and myDATA.
- Also built: CAdES/XAdES signature verification, opt-in XSD and Schematron validation for UBL and CII, field-level provenance, the
einvoiceCLI, a coverage gate, and a per-format conformance checklist (the conformance page on the site). - How well each format is covered (fixtures, real samples, mapping source, validation) is in the generated conformance checklist, not in this README, so it cannot drift.
received file ──► unwrap() ──► XML payload(s) ──► detectXml() ──► parser family ──► CanonicalInvoice[] .xml .pdf .p7m PDF/A-3 attachment format id, version, ubl, cii, fatturapa, .zip .isdocx CMS/PKCS#7, base64, ZIP, profile, or "not an ksef, facturae, ... .xsig SBDH, SOAP, encoding invoice"Layout
Section titled “Layout”| File | What it is |
|---|---|
src/canonical.ts |
The canonical type. EN 16931 core + EU-wide additions + per-country extensions. |
src/codes.ts |
Code lists as open string unions (UNCL 1001/5305/4461/5189/7161, ISO 4217/3166, ICD/EAS). |
src/formats.ts |
Registry of 37 formats with detection rules, parser family, countries, status and build phase. |
src/probe.ts |
Streaming header read (root, namespaces, CustomizationID, guideline ID, KSeF form code…). |
src/envelope.ts |
Unwrapping: PDF attachments, CMS signed data, base64, ZIP, SBDH, SOAP, encoding. Rejects DOCTYPEs and enforces size/count limits. |
src/server.ts |
The reference HTTP server for openapi/openapi.yaml (Bun.serve, nothing else); src/problems.ts is the error catalogue. |
src/detect.ts |
detectXml(): invoice format, known non-invoice, or unknown. |
src/parsers/ |
ubl.ts, cii.ts, svefaktura.ts, the shared DOM reader (context.ts) and the family registry with stubs for the rest. |
src/writers/ |
ubl.ts and cii.ts: canonical invoice back to Peppol BIS 3 UBL 2.1 and EN 16931 CII D16B (toUbl, toCii); shared.ts is the XML builder, escaping and specification choice. |
src/values.ts |
toDecimal() / toIsoDate() constructors and exact BigInt arithmetic. No value passes through a JS number. |
src/checks.ts |
EN 16931 calculation rules BR-CO-10/13/14/15/16, run after every parse. Mismatches become warnings; values are never rewritten. |
src/index.ts |
inspect(bytes) (unwrap + detect) and convert(bytes) (unwrap + detect + parse). Both return everything that was skipped, with the reason. |
test/ |
Detection, parser, hostile-input and value tests (about 160), plus fixtures/expected.json for the known-answer sweep. |
scripts/sweep.ts |
Runs detection over a directory tree. Without --expect it counts formats; with --expect answers.json it checks each file against a known answer and exits 1 on a mismatch. |
schemas/ |
Generated JSON Schemas (draft 2020-12) for CanonicalInvoice and ConvertResult. bun run build:schemas regenerates them from src/canonical.ts; CI fails when they are stale. |
site/ |
The GitHub Pages site, an Astro project with its own package.json: Starlight docs generated from this README (site/docs.ts), the browser converter as a React island, and the conformance, real-world results and API reference pages. bun run build:site builds it into dist/. |
All documentation pages
Section titled “All documentation pages”- Getting started: Install and use eu-einvoice-canonical: convert(bytes) in TypeScript, opt-in field provenance, and how a parser reads the source XML.
- Site languages: The browser converter speaks English, German, French, Italian, Spanish, Dutch, Polish and Romanian. How the language is chosen and how to correct a translation.
Use it
Section titled “Use it”- Command line: The einvoice command line: detect, inspect, convert, export, render, write, match and find duplicates in e-invoices, with exit codes for scripts.
- MCP server for AI agents: Run einvoice mcp, a Model Context Protocol server that lets an AI agent detect, convert, validate and match e-invoices without network access.
- Conversion API (HTTP): The einvoice serve HTTP API (OpenAPI 3.1): convert, inspect, detect, list formats and fetch schemas, with RFC 9457 errors and a Docker image.
- EU trusted lists: Check e-invoice signers against the EU List of Trusted Lists with signed snapshots, from the library, the CLI and the browser.
- Matching invoices to purchase orders: Match e-invoice lines to purchase orders (two-way) and goods receipts (three-way), with tolerances and a match, within-tolerance or needs-review verdict.
- Bookkeeping export: Turn a received e-invoice into a balanced journal entry and export it as SIE 4, JSON or CSV with your own account mapping.
- Human-readable rendering: renderHtml and renderPdf turn a canonical e-invoice into a self-contained HTML page or an A4 PDF that a person can read, print or archive.
- Writing UBL and CII: Write a canonical invoice back to Peppol BIS 3 UBL 2.1 or EN 16931 CII D16B with toUbl and toCii: deterministic, escaped and round-trip tested.
Model and contracts
Section titled “Model and contracts”- The canonical model: The canonical invoice model: the EN 16931 core, EU-wide additions, clearance data, country extensions and where every value came from.
- Line roles and relations: How the converter tells items from headings and surcharge lines and links them with proven arithmetic, plus an optional in-browser language model for the rest.
- JSON Schema: The published JSON Schemas (draft 2020-12) for the canonical invoice, the convert result and the inspect result, and how they are versioned.
- Deliverables and versioning: What the project publishes (library, JSON Schemas, OpenAPI spec, CLI binaries, browser converter) and the compatibility promise between v1 and v2.
Formats
Section titled “Formats”- EU coverage: Which e-invoice formats you will receive from each of the 27 EU member states, with mandate dates and notes.
- Beyond the EU: Peppol PINT (Singapore, Australia, New Zealand, Japan, Malaysia, UAE) and Saudi ZATCA invoices, mapped on top of the UBL parser.
- Build order and mapping notes: The parser families in the order they were built, with the mapping notes for each national e-invoice format.
- Mexico: CFDI: How a Mexican CFDI 3.3 or 4.0 invoice maps to the canonical model: taxes, withholdings, payments, the SAT stamp, and what the model cannot say.
- Supported e-invoice formats: The 44 e-invoice formats eu-einvoice-canonical detects and converts: Peppol BIS 3, XRechnung, Factur-X, FatturaPA, KSeF, Facturae and more, by country.
Project
Section titled “Project”- What was tested: The test suite behind the converter: detection, parsers, hostile input, decimal values, the known-answer sweep and the real-sample runs.
- Security: How the converter treats inbound e-invoices as hostile: DOCTYPE rejection, size and nesting limits, bounded ZIP and PDF decompression.
- Design decisions: Why VAT stays EN-shaped, why kind is only the accounting direction, which fields are required and how extensions are typed.
- Known gaps: What the converter does not do yet: unverified detection rules, EN 16931-1:2026, signature trust, national validation, PINT and ZATCA rules.
- License: eu-einvoice-canonical is released under the 0BSD licence; third-party sample files keep their own licences.
- Supply chain: What protects releases and CI, how to verify a download, and the repository settings the owner should apply . Nothing is published to npm.
- Canonical line annotations: This example interprets invoice lines using a selected view of the library’s canonical JSON. Names, descriptions, notes, identifiers and financial context…