Validate an XRechnung invoice in Python
XRechnung 3.0.2 is required for invoices to German public buyers, and B2B is phasing in. Validate against the official rule set in a few lines of Python.
XRechnung is Germany’s national profile of the European e-invoice standard EN 16931, maintained by KoSIT. It has been mandatory for invoices to German public-sector buyers since 2020, and the B2B side is phasing in: every German company has had to accept e-invoices since January 2025, and issuing becomes mandatory in 2027 for companies above 800,000 euros in turnover, then for everyone in 2028.
If your system produces XRechnung files, the question is not whether they look like XML. It is whether they pass the official rule set your recipient’s system will run. That check is one HTTP call.
The call
# pip install requests
import requests
with open("invoice.xml", "rb") as f:
response = requests.post(
"https://api.einvoicekit.com/v1/validate",
headers={
"Authorization": "Bearer eik_live_...",
"Content-Type": "application/xml",
},
data=f.read(),
)
result = response.json()
print(result["valid"], result["errors"])
The file goes up as the raw request body, 5 MB maximum. The API key is free: GitHub sign-in, no card, 100 validations a month.
The response
{
"valid": false,
"syntax": "cii",
"errors": [
{
"rule": "BR-CO-15",
"message": "[BR-CO-15]-Invoice total amount with VAT (BT-112) = Invoice total amount without VAT (BT-109) + Invoice total VAT amount (BT-110).",
"path": "/Q{urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100}CrossIndustryInvoice[1]"
}
],
"warnings": []
}
The response also carries a profile field, naming the exact specification the file itself declared.
Every failed rule comes back with its official identifier, the official rule message (which names the business terms involved, the BT-x references used throughout EN 16931 and the XRechnung specification), and the exact path in your XML. An XRechnung file is checked against the full official rule set, currently XRechnung 3.0.2: both syntaxes (UBL and UN/CEFACT CII) are read.
The failures you will actually see
Three families come up constantly in XRechnung files:
- Missing buyer reference (BT-10). XRechnung requires it, plain EN 16931 does not. For public-sector invoices this is where the Leitweg-ID goes, and files migrated from a generic EN 16931 setup fail here first.
- Totals that do not add up. The
BR-CO-*calculation rules recompute sums, VAT breakdowns and rounding. A single line-extension amount off by a cent fails the whole invoice. - Code-list violations. Currencies, VAT category codes, unit codes: every coded field is checked against the official lists, and a homegrown
piecewhereH87belongs is a rejection.
Wire it into CI
The call is fast enough to run on every generated invoice, but even a nightly job over your day’s output catches a bad template before your customers’ systems do. Exit non-zero when valid is false and let your pipeline do the rest:
import sys
sys.exit(0 if result["valid"] else 1)
Where XRechnung fits
XRechnung is one of several formats built on the same European standard; ZUGFeRD and Factur-X embed the same kind of XML in a PDF. If you deal with more than one of them, here is how they all fit together.