Eleven online validators, the same invoice, one day

In July 2026 the BDI observed that e-invoice validators disagree with each other. A great deal has been written about that; none of it was measured. This is the measurement: three files from the official KoSIT test suite, put through eleven freely accessible checking sites on one day.

Run · Reference rule set v2026-08-31

Measured and checked against the official KoSIT validator by Dmytro Yalanskyi, NormAPI.

Why this exists

Anyone who wants to know whether their invoice will go through uploads it to a free validator. If "valid" comes back, that settles it — so the assumption goes.

The assumption does not hold. On the day of the run, three of the eleven sites tested did not process an XRechnung in UBL at all — one of them fixed it the next day, which is why the table below shows two — and three more were working from a rule set predating 2 September 2026. In those cases "valid" does not mean the invoice is sound; it means this site found nothing.

"Companies are currently confronted with differing validation solutions and results, on both the outgoing and the incoming side […]. It is unclear whose validation result is the authoritative one." (our translation)
The sentence this responds to: BDI, "Probleme mit der E-Rechnung", 6 July 2026

Method

Every file comes from the official KoSIT test suite v2026-08-31 (Apache-2.0), published the same day as the rule set. No customer data, and every file can be reproduced.

Each change touches exactly one thing. Before the run, each was checked against the official KoSIT validator to confirm it triggers precisely the intended rule — two drafts failed that check because they were rejected by the XSD first, and were replaced.

Every entry below is an observation: what a tool reported about this file on this day, in the wording of its own report. Not an assessment of product quality.

The three files

A1
Unmodified conformance instance from the KoSIT test suite. Every validator should accept it.
B1
As A1, but the issue date carries a timezone offset: 2016-04-04+02:00. Valid per XSD, but since v2026-08-31 it triggers BR-TMP-6 (warning).
C1
As A1, but without BT-10 "Buyer reference" — the Leitweg-ID. Violates BR-DE-15.

What the tools reported

Rule set predating 2 September (3)

These read UBL, apply the German rules and catch the missing Leitweg-ID. But for B1 they report no warning, where v2026-08-31 reports BR-TMP-6. All three display findings below error level elsewhere, so the absence is a result rather than a question of presentation.

Serviceportal Baden-Württemberg

Version it states: 5.0.10
File C1
Fehler: 1, Warnungen: 0 — "Es wird empfohlen das Dokument zurückzuweisen."
Codes: none named
File B1
Fehler: –, Warnungen: – — "Es wird empfohlen das Dokument anzunehmen und weiter zu verarbeiten."
Codes: none named

Reads UBL correctly — it echoes the changed date back as 2016-04-04+02:00 — and catches the missing Leitweg-ID. For B1 it reports no warnings, where the KoSIT configuration v2026-08-31 reports BR-TMP-6 as a warning. That the same two fields read "1" and "0" for C1 shows the counters are populated when there is something to report.

invoice-portal.de

Version it states: XRechnung 3.0.2
File C1
XSD 0 · CEN-EN16931-UBL 0 · XRechnung 3.0.2: 2
Codes: BR-DE-15, BR-DE-TMP-32
File B1
XRechnung 3.0.2: 1
Codes: BR-DE-TMP-32

The report names every step with its artefact. C1 matches the official run code for code. On B1, BR-TMP-6 is absent while BR-DE-TMP-32 is still shown at information level.

portinvoice

Version it states: 2.26.0
File C1
XRechnung 3.0 STANDARD — 11 Regeln bestanden, 2 gescheitert
Codes: BR-DE-15, BR-DE-TMP-32
File B1
XRechnung 3.0 STANDARD — "Format-Validierung war erfolgreich", 1 gescheitert
Codes: BR-DE-TMP-32

Names the detected profile URN and the engine version. BR-DE-15 correctly disappears once the Leitweg-ID is restored. BR-TMP-6 is not reported for B1; BR-DE-TMP-32 is, at information level.

Does not process XRechnung in UBL (2)

XRechnung permits two syntaxes, UBL and CII. Which one is required is decided by the receiver, not the sender. These sites do not process the UBL variant — and do not always report that as what it is.

File A1
"weder Fehler noch Warnungen … konform"
Codes: none named
File B1
"1 Fehler / 0 Warnungen … nicht konform" — Schritt: CII-XSD
Codes: cvc-complex-type.2.4.b
File C1
"weder Fehler noch Warnungen … konform" — empfohlen anzunehmen
Codes: none named

Its own report names the detected document type as "EN16931 (CII)", though the file is UBL and declares the German CIUS in cbc:CustomizationID. It is checked against the CII schema accordingly; the single error on B1 concerns ram:IssueDateTime, a CII element that does not appear in the submitted file. For C1 no Schematron step appears and the word "XRechnung" is absent from the report — an invoice with no Leitweg-ID is recommended for acceptance.

File A1
"Kein E-Rechnungs-Profil erkannt · Weder ZUGFeRD/Factur-X noch XRechnung"
Codes: none named
File C1
"Kein E-Rechnungs-Profil erkannt · Weder ZUGFeRD/Factur-X noch XRechnung"
Codes: none named

This applies to A1 as well — the unmodified conformance instance from the official KoSIT test suite. Nothing about that file was altered.

Identical to the official run (3)

On everything tested, the same outcome as the official KoSIT run.

File C1
Ungültig — Profil: X-Rechnung 3.0
Codes: none named
File B1
Gültig — Profil: X-Rechnung 3.0
Codes: none named

Detects the XRechnung profile and reaches the same outcome as the official run on both files. Quota: ten checks per day.

File C1
Prüfung nicht bestanden — XRechnung 3.0
Codes: BR-DE-15
File B1
Prüfung bestanden — XRechnung 3.0
Codes: none named

Reads UBL, catches the missing Leitweg-ID and names the rule code. Nothing can be said about BR-TMP-6: the interface shows a pass/fail verdict rather than a list of findings, so silence is not evidence either way.

File C1
Nicht konform, 1 Fehler — "Käuferreferenz (Leitweg-ID, BT-10) ist erforderlich."
Codes: BR-DE-15
File B1
Mit Warnungen, keine Fehler — "[BR-TMP-6] Datumsangaben in UBL müssen im Format JJJJ-MM-TT (YYYY-MM-DD) übermittelt werden."
Codes: BR-TMP-6

Reads UBL, catches the missing Leitweg-ID and names BR-TMP-6 — a rule three other tools in this run do not report. One aside: in the extracted-fields summary the offset-bearing issue date shows as "Invalid Date", though it is validated correctly.

Corrected

On 15 September: On 15 September the site did not process an XRechnung in UBL and answered "Kein CrossIndustryInvoice-Element gefunden."

Re-tested: The operator wrote on 16 September that the pre-check had only recognised UBL by a root element without a namespace prefix, and that this was fixed. Re-tested with the same two files: it holds. The site now reads UBL and reports BR-DE-15 and BR-TMP-6.

Validates something else, deliberately (2)

Validates a different standard or catalogue. Silence on the German rules is correct here, not a defect.

File C1
SUCCESS — 0 Fehler
Codes: none named
File B1
SUCCESS — 0 Fehler
Codes: none named

Validates EN 16931, not the German CIUS. Not reporting BR-DE-15 is correct here, not a defect. The practical consequence: "it passed the EU validator" says nothing about a German B2G invoice.

Within what was tested, the profile catalogue contains no XRechnung and no EN 16931 profile; the public demo profiles are EDIFACT INVOIC, SAP XML ZORDERS05, UBL 2.0 Invoice and EDIFACT DESADV. Validating against "UBL 2.0 Invoice" would be a schema check and not an XRechnung result, so it was not run.

Not tested (1)

Could not be tested with this method. That is a limit of the method, not a statement about the tool.

Could not be tested: the form only processes uploads from a genuine user interaction. That is a limit of our method, not a statement about the tool.

The data

The full corpus — nine files, of which the three above went through all eleven sites — the official KoSIT run as the control, the European Commission ITB run, and every single observation as JSON. Plus the scripts that build the corpus and check that each file triggers precisely the intended rule. Results and scripts under CC BY 4.0; the corpus stays Apache-2.0.

Raw data on GitHub

How to cite this measurement

NormAPI (2026). Eleven online validators, the same invoice, one day. https://normapi.com/en/study/online-validators

A snapshot of one day. Tools change; a correction is recorded as one and never folded in silently. The reference is release v2026-08-31 — when a new one appears we repeat the run and carry the date here forward.

What this measurement does not show

The other half of the question: two validators, 29 documents, one rule set

Deutsche Fassung

NormAPI provides technical validation, not tax or legal advice.