Warum XRechnung implementieren?
Ab 1. Januar 2027 müssen alle deutschen Unternehmen im B2B-Bereich E-Rechnungen versenden können. XRechnung ist der deutsche Standard nach EN 16931 — und das Pflichtformat für Rechnungen an öffentliche Auftraggeber. Wer Software für Rechnungsstellung entwickelt, kommt an XRechnung nicht vorbei.
Dieser Artikel zeigt Ihnen als Entwickler den direkten Weg: XML-Struktur verstehen, Pflichtfelder korrekt befüllen, gegen EN 16931 validieren und per API automatisieren.
1. XML-Struktur: UBL 2.1 vs. CII
XRechnung unterstützt zwei XML-Syntaxen. Beide sind gleichwertig gültig — die Wahl hängt von Ihrem Anwendungsfall ab.
UBL 2.1 (Universal Business Language)
UBL ist der international verbreitetere Standard. Die Rechnungsdaten liegen im Namespace urn:oasis:names:specification:ubl:schema:xsd:Invoice-2. Das Root-Element ist <Invoice>.
<?xml version="1.0" encoding="UTF-8"?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0</cbc:CustomizationID>
<cbc:ID>RE-2026-001</cbc:ID>
<cbc:IssueDate>2026-03-22</cbc:IssueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<cac:AccountingSupplierParty>
<!-- Rechnungssteller -->
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<!-- Rechnungsempfänger -->
</cac:AccountingCustomerParty>
<cac:LegalMonetaryTotal>
<!-- Summen -->
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<!-- Rechnungspositionen -->
</cac:InvoiceLine>
</Invoice>UN/CEFACT CII (Cross-Industry Invoice)
CII ist die UN-Syntax, die auch ZUGFeRD verwendet. Das Root-Element ist <CrossIndustryInvoice>. Die Daten sind hierarchisch in Trade-Blöcke gegliedert.
<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
<rsm:ExchangedDocumentContext>
<ram:GuidelineSpecifiedDocumentContextParameter>
<ram:ID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0</ram:ID>
</ram:GuidelineSpecifiedDocumentContextParameter>
</rsm:ExchangedDocumentContext>
<rsm:ExchangedDocument>
<ram:ID>RE-2026-001</ram:ID>
<ram:TypeCode>380</ram:TypeCode>
<ram:IssueDateTime>
<udt:DateTimeString format="102">20260322</udt:DateTimeString>
</ram:IssueDateTime>
</rsm:ExchangedDocument>
<rsm:SupplyChainTradeTransaction>
<!-- Handelspartner, Lieferung, Zahlung -->
</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>UBL oder CII?
UBL eignet sich, wenn Sie international agieren oder PEPPOL nutzen. CII ist die Wahl, wenn Sie auch ZUGFeRD unterstützen wollen — ZUGFeRD verwendet ausschließlich CII.
2. Pflichtfelder nach EN 16931
EN 16931 definiert über 160 semantische Elemente. Nicht alle sind Pflicht. Die folgende Tabelle zeigt die Mindestanforderungen für eine gültige XRechnung:
| BT-Nr. | Feld | Beschreibung | Beispielwert |
|---|---|---|---|
| BT-1 | Rechnungsnummer | Eindeutige Kennung der Rechnung | RE-2026-001 |
| BT-2 | Rechnungsdatum | Ausstellungsdatum | 2026-03-22 |
| BT-3 | Rechnungsart | UNTDID 1001 Code | 380 (Rechnung) |
| BT-5 | Währung | ISO 4217 Währungscode | EUR |
| BT-27 | Verkäufername | Name des Rechnungsstellers | Muster GmbH |
| BT-44 | Käufername | Name des Rechnungsempfängers | Kunde AG |
| BT-109 | Zahlbarer Betrag | Gesamtbetrag inkl. MwSt. | 1190.00 |
| BT-112 | Nettobetrag | Gesamtbetrag exkl. MwSt. | 1000.00 |
| BT-115 | Fälliger Betrag | Zu zahlender Betrag | 1190.00 |
Zusätzliche Pflichtfelder für XRechnung (BR-DE)
Die deutschen Geschäftsregeln (BR-DE) erweitern die EN 16931-Pflichtfelder:
- Leitweg-ID (BT-10): Pflicht bei B2G-Rechnungen. Format:
04011000-12345-67 - Bankverbindung (BG-17): IBAN des Verkäufers bei Überweisung
- E-Mail-Adresse (BT-43): Kontaktadresse des Verkäufers
- Zahlungsbedingungen (BT-20): Freitext für Zahlungskonditionen
3. XRechnung implementieren mit der E-Invoice API
Statt XML manuell zu bauen, können Sie die E-Invoice API nutzen. Sie senden Rechnungsdaten als JSON — die API erzeugt valides XRechnung-XML.
API starten (Docker)
docker run -p 8000:8000 ghcr.io/jenslaufer/e-invoice:latestXRechnung generieren (Python)
Dieses Beispiel erstellt eine vollständige XRechnung im UBL-Format:
import requests
invoice_data = {
"invoice_number": "RE-2026-001",
"issue_date": "2026-03-22",
"due_date": "2026-04-21",
"currency_code": "EUR",
"invoice_type_code": "380",
"buyer_reference": "04011000-12345-67", # Leitweg-ID
"seller": {
"name": "Muster GmbH",
"street": "Musterstraße 1",
"city": "Berlin",
"postal_code": "10115",
"country_code": "DE",
"tax_id": "DE123456789",
"contact": {
"email": "rechnung@muster.de"
},
"bank_account": {
"iban": "DE89370400440532013000"
}
},
"buyer": {
"name": "Bundesministerium für Beispiele",
"street": "Regierungsstraße 10",
"city": "Berlin",
"postal_code": "10117",
"country_code": "DE"
},
"lines": [
{
"description": "Softwareentwicklung",
"quantity": 10,
"unit_code": "HUR",
"unit_price": 100.00,
"tax_category": "S",
"tax_percent": 19.0
}
],
"payment_terms": "Zahlbar innerhalb von 30 Tagen"
}
# XRechnung als UBL generieren
response = requests.post(
"http://localhost:8000/api/v1/invoices/xml",
json=invoice_data,
params={"syntax": "ubl"}
)
if response.status_code == 200:
with open("rechnung.xml", "wb") as f:
f.write(response.content)
print("XRechnung erstellt: rechnung.xml")
else:
print(f"Fehler: {response.json()}")CII-Syntax verwenden
Für CII-Output ändern Sie nur den Parameter:
response = requests.post(
"http://localhost:8000/api/v1/invoices/xml",
json=invoice_data,
params={"syntax": "cii"}
)4. Validierung gegen EN 16931
Eine XRechnung muss fünf Validierungsschichten bestehen. Jede Schicht prüft unterschiedliche Aspekte:
| Schicht | Prüfung | Werkzeug |
|---|---|---|
| 1. Schema | XML-Struktur und Datentypen | XSD-Validierung |
| 2. EN 16931 | Europäische Geschäftsregeln (BR-*) | Schematron |
| 3. XRechnung CIUS | Deutsche Geschäftsregeln (BR-DE-*) | Schematron |
| 4. Berechnung | Summen, Steuern, Rundung | Arithmetische Prüfung |
| 5. Semantik | Codelisten, Referenzen, Konsistenz | Geschäftslogik |
Validierung per API
# XRechnung validieren
with open("rechnung.xml", "rb") as f:
xml_content = f.read()
response = requests.post(
"http://localhost:8000/api/v1/invoices/validate",
files={"file": ("rechnung.xml", xml_content, "application/xml")}
)
result = response.json()
print(f"Gültig: {result['valid']}")
if not result["valid"]:
for error in result["errors"]:
print(f" [{error['rule']}] {error['message']}")Eine typische Validierungsantwort bei Fehlern:
{
"valid": false,
"errors": [
{
"rule": "BR-DE-1",
"message": "Eine XRechnung muss eine Leitweg-ID enthalten (BT-10).",
"severity": "error",
"location": "/Invoice"
}
],
"warnings": []
}Validierung in die CI/CD-Pipeline integrieren
Validieren Sie generierte Rechnungen automatisch in Ihrer Pipeline:
# validate_invoices.py
import sys
import requests
import glob
api_url = "http://localhost:8000/api/v1/invoices/validate"
errors_found = False
for xml_file in glob.glob("output/*.xml"):
with open(xml_file, "rb") as f:
resp = requests.post(
api_url,
files={"file": (xml_file, f, "application/xml")}
)
result = resp.json()
if not result["valid"]:
errors_found = True
print(f"FEHLER in {xml_file}:")
for err in result["errors"]:
print(f" [{err['rule']}] {err['message']}")
else:
print(f"OK: {xml_file}")
sys.exit(1 if errors_found else 0)5. Häufige Fehler und wie Sie sie vermeiden
Diese Fehler treten bei der EN 16931 Implementierung am häufigsten auf:
Fehler 1: Falsche CustomizationID
Die CustomizationID muss exakt zur XRechnung-Version passen. Ein Tippfehler führt zur Ablehnung.
<!-- Falsch -->
<cbc:CustomizationID>urn:cen.eu:en16931:2017</cbc:CustomizationID>
<!-- Richtig (XRechnung 3.0) -->
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_3.0</cbc:CustomizationID>Fehler 2: Steuerberechnung mit Rundungsfehlern
EN 16931 verlangt kaufmännische Rundung auf 2 Dezimalstellen. Fließkomma-Arithmetik führt zu Abweichungen.
# Falsch: Fließkomma-Fehler
tax = 100.05 * 0.19 # 19.0095000000000027...
# Richtig: Decimal verwenden
from decimal import Decimal, ROUND_HALF_UP
tax = (Decimal("100.05") * Decimal("0.19")).quantize(
Decimal("0.01"), rounding=ROUND_HALF_UP
) # Decimal('19.01')Fehler 3: Fehlende Leitweg-ID bei B2G
Die Geschäftsregel BR-DE-1 verlangt eine Leitweg-ID (BT-10) für alle Rechnungen an öffentliche Auftraggeber. Ohne Leitweg-ID wird die Rechnung abgelehnt.
Fehler 4: Datumsformat in CII
CII verwendet ein anderes Datumsformat als UBL. Häufiger Fehler: ISO-8601 statt CCYYMMDD.
<!-- Falsch in CII -->
<udt:DateTimeString format="102">2026-03-22</udt:DateTimeString>
<!-- Richtig in CII -->
<udt:DateTimeString format="102">20260322</udt:DateTimeString>Fehler 5: Summen stimmen nicht überein
EN 16931 enthält arithmetische Regeln (BR-CO-*). Die Summen müssen exakt passen:
- BT-106 (Summe Nettobetrag Positionen) = Summe aller BT-131
- BT-109 (Rechnungsbetrag ohne MwSt.) = BT-106 + BT-108 (Zuschlag) − BT-107 (Abzug)
- BT-112 (Rechnungsbetrag mit MwSt.) = BT-109 + BT-110 (MwSt.-Betrag)
- BT-115 (Fälliger Betrag) = BT-112 − BT-113 (bereits gezahlt)
Fehler 6: Falsche Unit-Codes
Mengeneinheiten müssen UN/ECE Recommendation 20 entsprechen. Häufige Codes:
| Code | Bedeutung |
|---|---|
HUR | Stunde |
DAY | Tag |
C62 | Stück (Einheit) |
KGM | Kilogramm |
MTR | Meter |
LTR | Liter |
Tipp: Validieren Sie jede generierte Rechnung vor dem Versand. Die E-Invoice API prüft alle 5 Schichten in einem Aufruf — Schema, EN 16931, BR-DE, Berechnung und Semantik.
6. Komplettes Beispiel: XRechnung von A bis Z
Das folgende Beispiel zeigt den vollständigen Workflow — Rechnung erstellen, validieren und speichern:
import requests
from pathlib import Path
API_BASE = "http://localhost:8000/api/v1"
def create_xrechnung():
"""Erstellt eine XRechnung und validiert sie."""
invoice = {
"invoice_number": "RE-2026-042",
"issue_date": "2026-03-22",
"due_date": "2026-04-21",
"currency_code": "EUR",
"invoice_type_code": "380",
"buyer_reference": "04011000-12345-67",
"seller": {
"name": "DevCorp GmbH",
"street": "Entwicklerweg 42",
"city": "München",
"postal_code": "80331",
"country_code": "DE",
"tax_id": "DE987654321",
"contact": {"email": "billing@devcorp.de"},
"bank_account": {"iban": "DE89370400440532013000"}
},
"buyer": {
"name": "Stadt München",
"street": "Marienplatz 8",
"city": "München",
"postal_code": "80331",
"country_code": "DE"
},
"lines": [
{
"description": "API-Entwicklung",
"quantity": 80,
"unit_code": "HUR",
"unit_price": 120.00,
"tax_category": "S",
"tax_percent": 19.0
},
{
"description": "Code Review",
"quantity": 20,
"unit_code": "HUR",
"unit_price": 95.00,
"tax_category": "S",
"tax_percent": 19.0
}
],
"payment_terms": "Zahlbar innerhalb von 30 Tagen netto"
}
# 1. XML generieren
resp = requests.post(
f"{API_BASE}/invoices/xml",
json=invoice,
params={"syntax": "ubl"}
)
resp.raise_for_status()
xml_bytes = resp.content
# 2. Validieren
val = requests.post(
f"{API_BASE}/invoices/validate",
files={"file": ("invoice.xml", xml_bytes, "application/xml")}
)
result = val.json()
if not result["valid"]:
for err in result["errors"]:
print(f"Fehler: [{err['rule']}] {err['message']}")
return False
# 3. Speichern
output = Path("output/RE-2026-042.xml")
output.parent.mkdir(exist_ok=True)
output.write_bytes(xml_bytes)
print(f"Valide XRechnung gespeichert: {output}")
return True
if __name__ == "__main__":
create_xrechnung()7. Nächste Schritte
Sie haben die Grundlagen der XRechnung-Implementierung kennengelernt. Für den produktiven Einsatz empfehlen wir:
- Branchenerweiterungen prüfen: Bau, Gesundheit, Logistik und Automotive haben zusätzliche Anforderungen.
- ZUGFeRD parallel einrichten: Viele B2B-Empfänger bevorzugen das Hybridformat.
- Fristen beachten: Die E-Rechnungspflicht 2027 betrifft alle B2B-Unternehmen.
Das könnte Sie auch interessieren
E-Rechnung mit DATEV: So richten Sie XRechnung ein
XRechnung in DATEV einrichten: Module, Schritt-für-Schritt Konfiguration, GoBD-konforme Archivierung und häufige Fehler bei der Umstellung auf E-Rechnung.
Weiterlesen E-RechnungEN 16931 Branchenerweiterungen: E-Rechnungen für Bau, Gesundheit und Logistik
EN 16931 allein reicht für viele Branchen nicht. So funktionieren Branchenerweiterungen für Bau, Gesundheit, Logistik und Automotive — technisch und praktisch.
Weiterlesen E-RechnungXRechnung-Pflicht 2027: Was Unternehmen jetzt wissen müssen
Ab 2027 wird die elektronische Rechnung im B2B-Bereich Pflicht. Erfahren Sie, welche Fristen gelten, wer betroffen ist und wie Sie Ihr Unternehmen rechtzeitig vorbereiten.
Weiterlesen