EN 16931 e-Invoice Lint - DE/FR/IT/BE/PL

Lints invoice payloads and field mappings against EN 16931 and national CIUS rules (XRechnung, Factur-X, FatturaPA, Peppol BIS, KSeF): missing business terms, stale spec IDs, wrong mandate dates. Runs entirely in your browser — nothing is uploaded.

Same engine as the VS Code extension, byte for byte.

Get one email when this rule changes
We watch the regulation and vendor sources behind EN 16931 e-Invoice Lint every day. When a rule changes, you get a single email with what changed and the updated check. No newsletter.

Install free

Free for the file open in your editor - no key, no limit. The workspace sweep and the report ask for a key.

npmMCP server (npx)Docker Hub
npx @readystack/en16931-einvoice-lint <file>
npx @readystack/en16931-einvoice-lint --mcp
docker run --rm -v "$PWD:/w" getreadystack/en16931-einvoice-lint /w

Team? One key for every ReadyStack linter, 5 seats, $149 once

Get the complete version $29

This page is the working piece. The full pack has everything below.

Checks an invoice payload or field mapping against EN 16931 and the national CIUS of the country it detects — 29 rules, in your editor.

A German tax adviser's time fee is fixed by StBVV § 13 at EUR 30-70 per half hour (EUR 60-140 an hour); one review of one invoice mapping costs more than this licence.

Buy the full version — $29

· ReadyStack

Worked example

Real numbers from this tool, line by line.

The invoice your AI assistant wrote will be rejected. Here are the six lines.

line 1  error  EN 16931 is bound to UBL 2.1. UBL 2.0 is not supported.
line 2  error  BT-24 Specification identifier must begin 'urn:cen.eu:en16931:2017#'.
line 3  error  Dates are ISO 8601 YYYY-MM-DD. '01/09/2026' is ambiguous.
line 4  error  BT-3 must be a 3-digit UNCL1001 code, not a word: 380, 381, 384.
line 5  error  @unitCode must come from UN/ECE Recommendation 20: C62, H87, HUR.
line 6  error  UBL requires @currencyID on every amount element.
line 6  error  The decimal separator in XML is '.', never ','.

Six lines, seven findings. Real output. Here is the file that produced it — an invoice an assistant wrote when asked for "a Peppol BIS 3.0 invoice":

<cbc:UBLVersionID>2.0</cbc:UBLVersionID>
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
<cbc:IssueDate>01/09/2026</cbc:IssueDate>
<cbc:InvoiceTypeCode>INVOICE</cbc:InvoiceTypeCode>
<cbc:InvoicedQuantity unitCode="pcs">10</cbc:InvoicedQuantity>
<cbc:PayableAmount>1200,00</cbc:PayableAmount>

It looks perfect. In order:

  1. UBL 2.0. EN 16931 is bound to UBL 2.1 — the wrong standard.
  2. A truncated specification identifier. BT-24 must carry the full CIUS string — for Peppol

...#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0, for XRechnung one ending xrechnung_3.0. A model trained on BIS 2.0 gives you a cenbii.eu URN.

  1. 01/09/2026. 1 September or 9 January? EN 16931 does not guess: ISO 8601, 2026-09-01.
  2. INVOICE. BT-3 is a UNCL1001 code, not a word: 380 invoice, 381 credit note.
  3. unitCode="pcs". Unit codes come from UN/ECE Rec 20 — C62 a piece, HUR an hour.
  4. 1200,00 with no @currencyID. The separator is a point, and every amount needs its

currency attribute — one line, two rejections.

This matters now. France crossed its line on 1 September 2026: every business established there must be able to receive a structured e-invoice. Belgium went first on 1 January, Poland's KSeF in February and April.

Why assistants are reliably wrong here

Not a knock on the models; it is structural. E-invoicing identifiers are versioned strings that change by revision and by country, on political timetables. Spain is the cleanest example: Verifactu was documented as starting January 2026 until Royal Decree-Law 15/2025 pushed it to

  1. Any model trained before that decree tells you 2026, confidently, because it was true.

A date, a form number, a jurisdiction, a revision: the shape of question a model cannot reason its way to, and the answer that costs money when wrong. A rejected invoice is not a bug report, it is an unpaid one.

So we wrote it down as rules

E-Invoicing Lint is a VS Code extension with 37 of these encoded as line rules, plus 26 snippets that are correct when you insert them. Every finding carries its BT- or BR- reference.

It runs offline; nothing you open leaves your machine. It also reads the country off the document: FR raises the September 2026 note, DE the Leitweg-ID in BT-10, and a Polish KSeF file is named as such rather than checked against rules that do not fit it.

The honest limits

These are line-level rules: wrong values, wrong codes, wrong formats. They do no cross-field arithmetic and cannot see a missing mandatory block. Use this while you write, and a full Schematron validator before you go live. A free web version runs the same 37 rules in one page, with a broken invoice already loaded.

What is free, and what the licence buys

Checking the file you have open: all 37 rules, all 26 snippets, no key, no counter, no watermark, nothing held back. That is the whole job of validating the invoice you are writing.

The licence is a different job, not a bigger one: every XML fixture in a repository at once, JSON output so a CI build fails when one stops being valid, and an exportable report. $49 once. Validating a single invoice, you will never need it.

15 seconds — what it actually does

Questions people ask

What does EN 16931 e-Invoice Lint actually do?

It reads the invoice payload or field mapping open in your editor — JSON, YAML or XML — and applies 29 rules: the mandatory EN 16931 business terms, the national CIUS fields for the country it detects, and date rules that compare the file against the real mandate dates. Findings appear inline with the line that breaks and the change that fixes it.

Who is it for?

Developers and integration consultants who ship invoicing code for customers in Germany, France, Italy, Belgium, Poland or Spain. If you are the person who maps your billing model onto XRechnung, Factur-X, FatturaPA, Peppol BIS or KSeF, this is the check that runs before the access point sees the document.

Why is a free validator not enough?

Free validators such as the Peppol test tool or the KoSIT schematron take a finished UBL or CII document and tell you it is malformed. They never see the JSON mapping in your repository, where the mistake was actually made, and they have no opinion about dates: they cannot tell you that the French deadline in your config is eight months wrong.

What is free and what needs a licence?

Checking the file in front of you is free and complete. All 29 rules run, every finding is shown with its fix, there is no watermark, no counter and no trial. The licence covers a different job: sweeping every invoice mapping in the workspace in one pass and writing a dated report file you keep, commit and hand to an auditor.

What would this cost done by a person?

A German tax adviser's time fee is fixed by StBVV § 13 at EUR 30 to 70 per half hour, so EUR 60 to 140 an hour. Having one invoice mapping reviewed once costs more than the licence, and it tells you nothing about the mapping you change next week. The check runs again for free every time you save.

Ask about this tool

One question, answered by the person who built it. Your email only if you want the answer sent.

ENDEJAESPT

Find a tool