The missing EN 16931 toolkit for JavaScript

Every serious EN 16931 implementation used to be Java or Python. einvoice brings parsing, validation and rendering of EU e-invoices to the npm ecosystem — zero dependencies, typed end to end, running in Node ≥ 18, browsers and edge runtimes.

Library

npm install einvoice
import { parseInvoice, validate, renderText } from "einvoice-kit";

// UBL XML, CII XML, or a Factur-X/ZUGFeRD PDF — auto-detected
const { invoice, format, profile } = await parseInvoice(bytes);

const result = validate(invoice);          // EN 16931 business rules
if (!result.ok) {
  for (const f of result.findings) {
    console.log(f.rule, f.where ?? "", f.hint ?? f.text);
  }
}

console.log(invoice.totals.payable?.raw);  // typed semantic model (BT-115)
console.log(renderText(invoice));          // human-readable summary

The parser is namespace-aware and immune to XXE by construction (no DOCTYPE, no entity expansion). All rule arithmetic uses exact BigInt decimals — no floating-point VAT surprises. Amounts keep their lexical form, so decimal-precision rules (BR-DEC) behave exactly like the official Schematron.

CLI

npx einvoice-kit validate invoice.xml      # exit 1 on violations — CI-friendly
npx einvoice-kit validate --json *.xml     # machine-readable findings
npx einvoice-kit show facture.pdf          # readable summary of a Factur-X PDF
npx einvoice-kit inspect invoice.xml       # full semantic model as JSON

MCP server (AI agents)

Give any MCP-capable agent the ability to read and validate e-invoices locally:

{
  "mcpServers": {
    "einvoice": { "command": "npx", "args": ["-y", "einvoice-kit-mcp"] }
  }
}

Tools: validate_invoice and read_invoice — both accept XML content or a file path, including Factur-X PDFs. Invoice data never leaves the machine.

What's implemented

AreaStatus
UBL 2.1 Invoice & CreditNote → semantic model✅ full BT/BG mapping
UN/CEFACT CII (D16B) → semantic model✅ full BT/BG mapping
Factur-X / ZUGFeRD PDF extraction✅ incl. PDF 2.0 / PDF-A/4, Flate streams
EN 16931 business rules (BR, BR-CO, BR-DEC, VAT groups, BR-CL)✅ ~165 rules, official ±1 tolerances
Rendering (text, standalone HTML)
XRechnung BR-DE / Peppol national rules🔜 roadmap
Invoice generation (model → XML)🔜 roadmap

Verification: the engine runs against 120 official test files from the EU and KoSIT corpora in CI — see the conformance report. Schema (XSD) validation is intentionally out of scope for v0.x; the semantic rules catch what matters for interoperability.

Why not wrap the official Schematron?

Running the official XSLT needs Java (or SaxonJS) and yields messages like "[BR-CO-15] failed". A native rule engine over one semantic model validates both syntaxes with the same code, runs in ~1 ms per invoice, fits in a browser tab, and can tell you "BT-112 is 336.90, expected 366.86 = 314.86 + 52.00". The official artefacts remain our reference: rule texts, code lists and tolerances are extracted from them mechanically, and the corpus keeps us honest.