XRechnung is not a file format. It is a rule set: the German CIUS of EN 16931, which takes the European core invoice and makes a handful of optional things mandatory. That has one consequence that surprises people building their first integration, and it shapes this page.
Because XRechnung constrains the data model rather than the file, it exists in two syntaxes. The same invoice can be expressed as OASIS UBL or as UN/CEFACT CII, both are equally valid XRechnung, both declare the same specification identifier, and German receiving portals accept either. So there is no ladder of profiles here the way there is in Factur-X. There is one profile in two shapes.
The two syntaxes
Both files below carry the identical invoice and declare the identical BT-24:
urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0
Note the shape of that string if you are migrating from XRechnung 2.x. Version 3.0 moved the registrar segment from xoev-de to xeinkauf.de and dropped the standard: segment that the 1.2 to 2.3 identifiers carried, so a substring match written against the old form will not recognise a 3.0 document. The customization identifier reference has the full history.
Diff them against each other and the mapping is a useful thing to have read once: cac:AccountingSupplierParty against ram:SellerTradeParty, cbc:CustomizationID against ram:GuidelineSpecifiedDocumentContextParameter/ram:ID, and the whole of UBL's flat cac:InvoiceLine against CII's nested ram:IncludedSupplyChainTradeLineItem. Same invoice, same business terms, entirely different element names.
The invoice itself is a three-line services invoice from a German seller to a French buyer, with a document-level discount, a freight charge, a line-level surcharge, an invoicing period, and payment by SEPA credit transfer.
What XRechnung makes mandatory
If you already produce valid EN 16931 invoices, the German rules are the gap you have to close. These are the ones the samples exercise:
| Rule | Requires | Business term |
|---|---|---|
| BR-DE-15 | A buyer reference, which is the Leitweg-ID in public-sector invoicing | BT-10 |
| BR-DE-2 | A seller contact group, with name, phone and email inside it | BG-6 |
| BR-DE-1 | Payment instructions | BG-16 |
| BR-DE-21 | The specification identifier to match the XRechnung one exactly | BT-24 |
Plain EN 16931 leaves every one of these optional, which is why a generic EN 16931 check is a poor predictor of German acceptance. It passes documents a German portal will reject, and testing against an EN 16931 sample tells you nothing about whether your XRechnung output gets through. Anything aimed at Germany has to run the KoSIT rule set on top of the European one, which is exactly what the XRechnung validator here does: schema first, then the EN 16931 rules, then XRechnung 3.0.2. The fixtures below fail on that third layer and nowhere else.
Files that are wrong on purpose
Each of these breaks exactly one German rule and nothing else, which is what makes them useful for pinning your error handling. We assert that when generating them: if removing the field knocked out a second BR-DE rule as a side effect, the file would not be published.
BR-DE-15 is published in both syntaxes deliberately. It is the most commonly hit XRechnung rejection, and an integration is only ever built against one syntax, so shipping the fixture in one form would leave half of you without a test file. Comparing the two is also the cheapest way to see that the German rules are defined on business terms rather than on elements: the same rule fires on both, and only the XPath in the error message differs.
All three remain schema-valid, so an XSD check passes them. Only the Schematron layer catches these, which is the point: if your validator returns green on them, it is not running the KoSIT rules and it will not predict what a German portal does with your invoices.
How these files were generated
Both versions come from the same invoice JSON through the same endpoint. Nothing about the invoice changes between them, only which binding you ask for, and UBL is what you get if you do not ask:
curl -X POST https://api.invoicexml.com/v1/create/xrechnung \
-H "Authorization: Bearer $INVOICEXML_API_KEY" \
-H "Content-Type: application/json" \
-d @invoice.json \
--output xrechnung-ubl.xml
For the CII binding, add one option to the request body:
{
"invoice": { "invoiceNumber": "DEMO-2026-0042", "...": "..." },
"options": { "syntax": "cii" }
}
Every file is then run through the validator against the KoSIT rules before publishing, which is how we know the valid ones are valid and each broken one breaks on exactly one rule. To check a file of your own, the XRechnung validator takes an upload directly and reports the rule identifiers, not just a pass or fail.
Why sample files go stale
These were generated on 6 August 2026, against KoSIT XRechnung 3.0.2 and the EN 16931 CII and UBL rules 1.3.16.
XRechnung is the fastest-moving rule set in this family. KoSIT ships twice a year, typically publishing in January and July and putting the release in force the following month, and each one can add rules, tighten existing ones, or mint a new specification identifier that your BT-24 string match has never seen. A file that a German portal accepted last spring can be rejected this autumn without anything in your code changing.
That cadence is the real cost of owning this in-house. The XML is the easy part. Tracking KoSIT twice a year, re-vendoring the Schematron, re-running your corpus and shipping a release before the in-force date, indefinitely, is the part nobody scopes for.
On the InvoiceXML API the current rule set is simply what runs: no SDK to upgrade, no redeploy when KoSIT publishes, no version matrix to reason about. If that trade appeals, start with the free trial, or read how the XRechnung API handles both syntaxes end to end.