en16931

EN 16931 · XRechnung · Peppol BIS 3.0 · ZUGFeRD / Factur-X

The European e-invoice,
as Rust types.

Validate the invoice, not the document. Findings point at BT-151 on line 3 — never at an XPath — because the rules run against the semantic model instead of a serialised file. Two libraries and a single static binary.

cargo add en16931 or cargo install en16931-cli
334 rules registered
277 rules exercised by a failing fixture
1 025 CEN unit-test assertions run, none disagreeing
500 published documents read, written and crossed

What this is

EN 16931 is the European e-invoice: a semantic data model of business terms and groups, business rules on it, and two mandatory XML syntaxes, UBL 2.1 and UN/CEFACT CII. National usage specifications such as XRechnung and Peppol BIS Billing 3.0 restrict it further.

These crates make the model the primary artefact and run the rules against it, so a finding says BG-25[2]/BT-151 and an invoice can be validated while it is still being assembled, before any XML exists.

let report = en16931::validate(&invoice);

assert!(report.has("BR-16"));                       // no invoice line
assert_eq!(report.fatal().next().unwrap().path.to_string(), "BT-1");

Three crates

en16931the semantic model, the rules, the typed proof of validity. Two dependencies, no XML, no I/O, builds for wasm32.
en16931-formatsUBL 2.1 and UN/CEFACT CII in both directions, ZUGFeRD / Factur-X extraction and embedding. Re-implements none of the 334 rules.
en16931-clithe same as a command, with exit codes a CI job can branch on.

What makes it different

Types retire rules. InvoiceAmount holds exactly two decimals, so the 21 BR-DEC-* rules cannot fire; PaymentMeans is an enum, so the rules forbidding two payment groups at once have nothing left to check. Of the 334 rules registered, 53 are retired this way and 4 are undecidable at the semantic layer, with the remaining 277 exercised by their own failing fixtures.

Measured against the authorities. Code lists, element order, prohibitions and severities are generated from or checked against CEN’s, KoSIT’s and OpenPeppol’s artefacts at pinned releases. 1 025 CEN unit-test assertions run with no disagreement (11 divergences declared), 381 KoSIT mutations agree, and 59 published invoices validate. See conformance.

Severity from the authority. KoSIT re-levels nine CEN rules for XRechnung; BR-CL-23 is a warning there. A validator that reports it as fatal rejects invoices Germany accepts.

A proof you cannot forge. Validated<XRechnung> is a type. A serialiser that demands one cannot be handed an unchecked invoice, or one checked against a different profile.

Two documents compared as invoices. en16931 diff a.xml b.cii.xml reads both into the model, so a UBL invoice and its CII translation compare equal.

Documentation

Getting started

Install the en16931 crates or the CLI, build your first EN 16931 invoice, reconcile the totals and read the validation report.

The semantic model

EN 16931's business terms and groups as Rust types: fixed-point amounts, calendar dates, per-cent percentages, signed quantities, and eighteen generated code lists.

Validation

The 334 EN 16931 business rules as Rust: the nine VAT category families, four tolerance regimes, severity from the authority, and reports in JSON or SVRL.

Profiles

XRechnung 3.0, Peppol BIS Billing 3.0 and the XRechnung Extension as EN 16931 profiles — CIUS versus Extension, restrictions as data, and the typed Validated<P> proof.

Syntaxes: UBL and CII

Read, write and convert UBL 2.1 and UN/CEFACT CII D16B through the EN 16931 semantic model — one call per task, generated element order, 1 218 prohibitions, and nothing dropped silently.

ZUGFeRD and Factur-X

Extract the CII payload from a ZUGFeRD or Factur-X hybrid PDF, embed a validated invoice into a PDF/A-3 file, compare the PDF's XMP metadata against the payload, and know which profiles are not EN 16931 invoices at all.

The command line

en16931-cli: validate, receive, convert, extract, embed, inspect and explain European e-invoices from one static binary, with exit codes a CI job can branch on.

Bridging a billing engine

Turn a derived billing document and a header into an EN 16931 invoice in one call — every amount read from the accessor of its business term, nothing recomputed — and render a BT-20 Skonto that BR-DE-18 accepts.

Conformance and performance

What is measured rather than claimed: CEN's unit tests, KoSIT's mutation suite, 59 published invoices, 500 documents round-tripped and crossed, and the benchmarks.

Contributing

Set up the en16931 workspace: fetch the CEN, KoSIT and Peppol artefacts, run the full CI gate locally, and regenerate the tables derived from the standard.