XRechnung für Entwickler: Ein tiefer Einblick in das UBL-Format

Seit einigen Jahren ist die elektronische Rechnungsstellung an öffentliche Auftraggeber in Deutschland Pflicht. Das Herzstück dieser Digitalisierungsoffensive ist der Standard XRechnung. Für Entwickler, die Rechnungs-Workflows in ihre Software integrieren, ist ein tiefes Verständnis dieses Formats unerlässlich.

Dieser Artikel dient als technischer Leitfaden, der das XRechnung-Format anhand eines praktischen Beispiels im UBL-Format (Universal Business Language) aufschlüsselt. Wir werden eine Beispielrechnung Zeile für Zeile analysieren, um die Struktur, die wichtigsten Felder und die dahinterliegenden Geschäftsregeln zu verstehen.

Inhaltsverzeichnis

Was ist eine XRechnung?

Eine XRechnung ist keine PDF-Datei. Es handelt sich um eine strukturierte, maschinenlesbare Datendatei im XML-Format. Ihr Hauptzweck ist die vollständige Automatisierung des Rechnungsprozesses – vom Versand über den Empfang bis hin zur Buchung.

Der Standard basiert auf der europäischen Norm EN 16931. XRechnung ist eine sogenannte CIUS (Core Invoice Usage Specification) dieser Norm. Das bedeutet, sie ist eine nationale Konkretisierung für Deutschland, die die europäischen Vorgaben um nationale Geschäftsregeln und Pflichtfelder ergänzt.

Für die technische Umsetzung sind zwei XML-Syntaxen zugelassen:

In diesem Artikel konzentrieren wir uns auf UBL, die in der Praxis weit verbreitete Syntax.

Anatomie einer XRechnung: Das XML-Beispiel zerlegt

Betrachten wir eine vollständige XRechnung und zerlegen sie in ihre logischen Bestandteile. Jeder Abschnitt wird durch ein Code-Snippet und eine detaillierte Erklärung der einzelnen Felder illustriert.

1. Header und Metadaten

Jede XRechnung beginnt mit der XML-Deklaration und dem Root-Element <Invoice>, das die notwendigen Namensräume definiert. Darauf folgen essenzielle Metadaten, die die Rechnung identifizieren und kontextualisieren.

xml
<?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:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
	<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
	<cbc:ID>RE-2024-001</cbc:ID>
	<cbc:IssueDate>2024-02-28</cbc:IssueDate>
	<cbc:DueDate>2024-03-29</cbc:DueDate>
	<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
	<cbc:Note>Notiz für die XRechnung</cbc:Note>
	<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
	<cbc:BuyerReference>PROJEKT-2024-XR</cbc:BuyerReference>
</Invoice>
  • CustomizationID: Dies ist der wichtigste Identifikator. Er gibt an, dass die Rechnung dem Standard XRechnung in der Version 3.0.2 entspricht und konform zur europäischen Norm EN 16931 ist.
  • ProfileID: Definiert den verwendeten Geschäftsprozess, hier im Kontext des Peppol-Netzwerks.
  • ID: Die Rechnungsnummer. Sie muss vom Rechnungssteller eindeutig vergeben werden.
  • IssueDate: Das Ausstellungsdatum der Rechnung.
  • DueDate: Das Fälligkeitsdatum der Zahlung.
  • InvoiceTypeCode: Ein Code, der den Rechnungstyp angibt. "380" steht für eine Handelsrechnung (Commercial invoice). Weitere Codes finden sich in der UNTDID 1001 Codeliste.
  • Note: Ein Freitextfeld für allgemeine Anmerkungen zur Rechnung.
  • DocumentCurrencyCode: Der Währungscode gemäß ISO 4217 (z. B. "EUR").
  • BuyerReference: Die Leitweg-ID. Dieses Feld ist für die öffentliche Verwaltung entscheidend, da es die Rechnung dem korrekten Empfänger und Bearbeitungsprozess zuordnet. Es kann auch für andere Referenzen des Käufers genutzt werden.

2. Der Rechnungssteller (Supplier)

Dieser Block enthält alle relevanten Informationen über das Unternehmen, das die Rechnung ausstellt.

xml
<cac:AccountingSupplierParty>
	<cac:Party>
		<cbc:EndpointID schemeID="EM">info@example.com</cbc:EndpointID>
		<cac:PartyName>
			<cbc:Name>Muster GmbH</cbc:Name>
		</cac:PartyName>
		<cac:PostalAddress>
			<cbc:StreetName>Musterstraße 55a</cbc:StreetName>
			<cbc:CityName>Hamburg</cbc:CityName>
			<cbc:PostalZone>12345</cbc:PostalZone>
			<cac:Country>
				<cbc:IdentificationCode>DE</cbc:IdentificationCode>
			</cac:Country>
		</cac:PostalAddress>
		<cac:PartyTaxScheme>
			<cbc:CompanyID>DE123456789</cbc:CompanyID>
			<cac:TaxScheme>
				<cbc:ID>VAT</cbc:ID>
			</cac:TaxScheme>
		</cac:PartyTaxScheme>
		<cac:PartyLegalEntity>
			<cbc:RegistrationName>Muster GmbH</cbc:RegistrationName>
		</cac:PartyLegalEntity>
		<cac:Contact>
			<cbc:Name>Max Mustermann</cbc:Name>
			<cbc:Telephone>+49123456789</cbc:Telephone>
			<cbc:ElectronicMail>max.mustermann@example.com</cbc:ElectronicMail>
		</cac:Contact>
	</cac:Party>
</cac:AccountingSupplierParty>
  • EndpointID: Die elektronische Adresse des Rechnungsstellers. Das Attribut schemeID gibt den Typ an, hier "EM" für E-Mail. Die zulässigen Werte stammen aus der Electronic Address Scheme (EAS) Codeliste.
  • PartyName/Name: Der Name des Unternehmens.
  • PostalAddress: Die postalische Anschrift, unterteilt in Straße, Stadt, Postleitzahl und Land.
  • PartyTaxScheme/CompanyID: Die Umsatzsteuer-Identifikationsnummer des Unternehmens.
  • PartyLegalEntity/RegistrationName: Der offizielle, im Handelsregister eingetragene Name.
  • Contact: Kontaktinformationen eines Ansprechpartners (Name, Telefon, E-Mail).

3. Der Rechnungsempfänger (Customer)

Analog zum Rechnungssteller werden hier die Daten des Rechnungsempfängers erfasst.

xml
<cac:AccountingCustomerParty>
	<cac:Party>
		<cbc:EndpointID schemeID="EM">buchhaltung@beispiel-ug.de</cbc:EndpointID>
		<cac:PartyName>
			<cbc:Name>Beispiel UG (haftungsbeschränkt)</cbc:Name>
		</cac:PartyName>
		<cac:PostalAddress>
			<!-- ... Anschrift wie oben ... -->
		</cac:PostalAddress>
		<cac:PartyTaxScheme>
			<cbc:CompanyID>DE987654321</cbc:CompanyID>
			<!-- ... -->
		</cac:PartyTaxScheme>
		<cac:PartyLegalEntity>
			<cbc:RegistrationName>Beispiel UG (haftungsbeschränkt)</cbc:RegistrationName>
		</cac:PartyLegalEntity>
		<!-- ... Kontakt wie oben ... -->
	</cac:Party>
</cac:AccountingCustomerParty>

Die Felder entsprechen denen des Rechnungsstellers, beziehen sich aber auf den Käufer.

4. Zahlungsanweisungen

Dieser Abschnitt definiert, wie die Zahlung zu erfolgen hat.

xml
<cac:PaymentMeans>
	<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
	<cac:PayeeFinancialAccount>
		<cbc:ID>DE12345678901234567890</cbc:ID>
		<cbc:Name>Muster Bank</cbc:Name>
		<cac:FinancialInstitutionBranch>
			<cbc:ID>MUSTDE12XXX</cbc:ID>
		</cac:FinancialInstitutionBranch>
	</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
	<cbc:Note>Zahlbar innerhalb von 30 Tagen netto</cbc:Note>
</cac:PaymentTerms>
  • PaymentMeansCode: Gibt die Zahlungsart an. Der Code "30" steht für eine SEPA-Überweisung (Credit Transfer). Eine Liste der Codes ist unter UNTDID 4461 zu finden.
  • PayeeFinancialAccount: Enthält die Bankverbindung des Zahlungsempfängers.
    • ID: Die IBAN.
    • Name: Der Name des Kontoinhabers oder der Bank.
    • FinancialInstitutionBranch/ID: Die BIC (Bank Identifier Code).
  • PaymentTerms/Note: Ein Freitextfeld für die Zahlungsbedingungen (z.B. Zahlungsziele, Skonto).

5. Steuer- und Gesamtsummen

Diese Blöcke sind für die maschinelle Verarbeitung von zentraler Bedeutung. Sie fassen alle Beträge zusammen.

xml
<cac:TaxTotal>
	<cbc:TaxAmount currencyID="EUR">149.15</cbc:TaxAmount>
	<cac:TaxSubtotal>
		<cbc:TaxableAmount currencyID="EUR">785.00</cbc:TaxableAmount>
		<cbc:TaxAmount currencyID="EUR">149.15</cbc:TaxAmount>
		<cac:TaxCategory>
			<cbc:ID>S</cbc:ID>
			<cbc:Percent>19</cbc:Percent>
			<cac:TaxScheme>
				<cbc:ID>VAT</cbc:ID>
			</cac:TaxScheme>
		</cac:TaxCategory>
	</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
	<cbc:LineExtensionAmount currencyID="EUR">785.00</cbc:LineExtensionAmount>
	<cbc:TaxExclusiveAmount currencyID="EUR">785.00</cbc:TaxExclusiveAmount>
	<cbc:TaxInclusiveAmount currencyID="EUR">934.15</cbc:TaxInclusiveAmount>
	<cbc:PayableAmount currencyID="EUR">934.15</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
  • TaxTotal: Der Container für alle Steuerinformationen.
    • TaxAmount: Die Summe aller Steuerbeträge der Rechnung.
    • TaxSubtotal: Eine Aufschlüsselung pro Steuersatz.
      • TaxableAmount: Die Bemessungsgrundlage (Nettobetrag) für diesen Steuersatz.
      • TaxAmount: Der berechnete Steuerbetrag für diesen Steuersatz.
      • TaxCategory/ID: Der Code für die Steuerkategorie. "S" steht für den Normalsatz (Standard rate). Die Codes sind in UNTDID 5305 definiert.
      • Percent: Der angewandte Steuersatz in Prozent.
  • LegalMonetaryTotal: Die abschließenden Gesamtbeträge der Rechnung.
    • LineExtensionAmount: Summe aller Nettobeträge der Rechnungspositionen.
    • TaxExclusiveAmount: Gesamtbetrag der Rechnung ohne Umsatzsteuer.
    • TaxInclusiveAmount: Gesamtbetrag der Rechnung mit Umsatzsteuer (Bruttobetrag).
    • PayableAmount: Der zu zahlende Betrag.

6. Die Rechnungspositionen (Invoice Lines)

Der Kern der Rechnung: Hier werden die einzelnen gelieferten Produkte oder Dienstleistungen aufgeführt. Eine Rechnung muss mindestens eine Position enthalten.

xml
<cac:InvoiceLine>
	<cbc:ID>1</cbc:ID>
	<cbc:InvoicedQuantity unitCode="HUR">3</cbc:InvoicedQuantity>
	<cbc:LineExtensionAmount currencyID="EUR">285.00</cbc:LineExtensionAmount>
	<cac:Item>
		<cbc:Description>Analyse und Erarbeitung eines Konzepts für die Digitalisierung</cbc:Description>
		<cbc:Name>Beratung und Konzeption</cbc:Name>
		<cac:ClassifiedTaxCategory>
			<cbc:ID>S</cbc:ID>
			<cbc:Percent>19</cbc:Percent>
			<cac:TaxScheme>
				<cbc:ID>VAT</cbc:ID>
			</cac:TaxScheme>
		</cac:ClassifiedTaxCategory>
	</cac:Item>
	<cac:Price>
		<cbc:PriceAmount currencyID="EUR">95.00</cbc:PriceAmount>
	</cac:Price>
</cac:InvoiceLine>
  • ID: Eine fortlaufende Nummer zur Identifizierung der Rechnungsposition.
  • InvoicedQuantity: Die in Rechnung gestellte Menge. Das Attribut unitCode gibt die Maßeinheit an (z. B. "HUR" für Stunde, "H87" für Stück). Die Codes stammen aus den Listen Recommendation 20 und Recommendation 21.
  • LineExtensionAmount: Der Nettogesamtbetrag für diese Position (Menge × Einzelpreis).
  • Item: Details zum Produkt oder zur Dienstleistung.
    • Description: Eine ausführlichere Beschreibung.
    • Name: Der Name des Artikels.
    • ClassifiedTaxCategory: Die auf diese Position anzuwendende Steuerkategorie (wie im TaxTotal-Block).
  • Price/PriceAmount: Der Netto-Einzelpreis pro Einheit.

Das vollständige Beispiel

Hier ist noch einmal die gesamte XRechnung im Überblick, um zu zeigen, wie alle Teile zusammen ein kohärentes Dokument bilden.

xml
<?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:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
	<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
	<cbc:ID>RE-2024-001</cbc:ID>
	<cbc:IssueDate>2024-02-28</cbc:IssueDate>
	<cbc:DueDate>2024-03-29</cbc:DueDate>
	<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
	<cbc:Note>Notiz für die XRechnung</cbc:Note>
	<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
	<cbc:BuyerReference>PROJEKT-2024-XR</cbc:BuyerReference>
	<cac:AdditionalDocumentReference>
		<cbc:ID>RE-2024-001</cbc:ID>
	</cac:AdditionalDocumentReference>
	<cac:AccountingSupplierParty>
		<cac:Party>
			<cbc:EndpointID schemeID="EM">info@example.com</cbc:EndpointID>
			<cac:PartyName>
				<cbc:Name>Muster GmbH</cbc:Name>
			</cac:PartyName>
			<cac:PostalAddress>
				<cbc:StreetName>Musterstraße 55a</cbc:StreetName>
				<cbc:CityName>Hamburg</cbc:CityName>
				<cbc:PostalZone>12345</cbc:PostalZone>
				<cac:Country>
					<cbc:IdentificationCode>DE</cbc:IdentificationCode>
				</cac:Country>
			</cac:PostalAddress>
			<cac:PartyTaxScheme>
				<cbc:CompanyID>DE123456789</cbc:CompanyID>
				<cac:TaxScheme>
					<cbc:ID>VAT</cbc:ID>
				</cac:TaxScheme>
			</cac:PartyTaxScheme>
			<cac:PartyLegalEntity>
				<cbc:RegistrationName>Muster GmbH</cbc:RegistrationName>
			</cac:PartyLegalEntity>
			<cac:Contact>
				<cbc:Name>Max Mustermann</cbc:Name>
				<cbc:Telephone>+49123456789</cbc:Telephone>
				<cbc:ElectronicMail>max.mustermann@example.com</cbc:ElectronicMail>
			</cac:Contact>
		</cac:Party>
	</cac:AccountingSupplierParty>
	<cac:AccountingCustomerParty>
		<cac:Party>
			<cbc:EndpointID schemeID="EM">buchhaltung@beispiel-ug.de</cbc:EndpointID>
			<cac:PartyName>
				<cbc:Name>Beispiel UG (haftungsbeschränkt)</cbc:Name>
			</cac:PartyName>
			<cac:PostalAddress>
				<cbc:StreetName>Musterweg 3c</cbc:StreetName>
				<cbc:CityName>Berlin</cbc:CityName>
				<cbc:PostalZone>54321</cbc:PostalZone>
				<cac:Country>
					<cbc:IdentificationCode>DE</cbc:IdentificationCode>
				</cac:Country>
			</cac:PostalAddress>
			<cac:PartyTaxScheme>
				<cbc:CompanyID>DE987654321</cbc:CompanyID>
				<cac:TaxScheme>
					<cbc:ID>VAT</cbc:ID>
				</cac:TaxScheme>
			</cac:PartyTaxScheme>
			<cac:PartyLegalEntity>
				<cbc:RegistrationName>Beispiel UG (haftungsbeschränkt)</cbc:RegistrationName>
			</cac:PartyLegalEntity>
			<cac:Contact>
				<cbc:Name>Erika Musterfrau</cbc:Name>
				<cbc:Telephone>+49987654321</cbc:Telephone>
				<cbc:ElectronicMail>erika.musterfrau@beispiel-ug.de</cbc:ElectronicMail>
			</cac:Contact>
		</cac:Party>
	</cac:AccountingCustomerParty>
	<cac:PaymentMeans>
		<cbc:PaymentMeansCode>30</cbc:PaymentMeansCode>
		<cac:PayeeFinancialAccount>
			<cbc:ID>DE12345678901234567890</cbc:ID>
			<cbc:Name>Muster Bank</cbc:Name>
			<cac:FinancialInstitutionBranch>
				<cbc:ID>MUSTDE12XXX</cbc:ID>
			</cac:FinancialInstitutionBranch>
		</cac:PayeeFinancialAccount>
	</cac:PaymentMeans>
	<cac:PaymentTerms>
		<cbc:Note>Zahlbar innerhalb von 30 Tagen netto</cbc:Note>
	</cac:PaymentTerms>
	<cac:TaxTotal>
		<cbc:TaxAmount currencyID="EUR">149.15</cbc:TaxAmount>
		<cac:TaxSubtotal>
			<cbc:TaxableAmount currencyID="EUR">785.00</cbc:TaxableAmount>
			<cbc:TaxAmount currencyID="EUR">149.15</cbc:TaxAmount>
			<cac:TaxCategory>
				<cbc:ID>S</cbc:ID>
				<cbc:Percent>19</cbc:Percent>
				<cac:TaxScheme>
					<cbc:ID>VAT</cbc:ID>
				</cac:TaxScheme>
			</cac:TaxCategory>
		</cac:TaxSubtotal>
	</cac:TaxTotal>
	<cac:LegalMonetaryTotal>
		<cbc:LineExtensionAmount currencyID="EUR">785.00</cbc:LineExtensionAmount>
		<cbc:TaxExclusiveAmount currencyID="EUR">785.00</cbc:TaxExclusiveAmount>
		<cbc:TaxInclusiveAmount currencyID="EUR">934.15</cbc:TaxInclusiveAmount>
		<cbc:PayableAmount currencyID="EUR">934.15</cbc:PayableAmount>
	</cac:LegalMonetaryTotal>
	<cac:InvoiceLine>
		<cbc:ID>1</cbc:ID>
		<cbc:InvoicedQuantity unitCode="HUR">3</cbc:InvoicedQuantity>
		<cbc:LineExtensionAmount currencyID="EUR">285.00</cbc:LineExtensionAmount>
		<cac:Item>
			<cbc:Description>Analyse und Erarbeitung eines Konzepts für die Digitalisierung</cbc:Description>
			<cbc:Name>Beratung und Konzeption</cbc:Name>
			<cac:ClassifiedTaxCategory>
				<cbc:ID>S</cbc:ID>
				<cbc:Percent>19</cbc:Percent>
				<cac:TaxScheme>
					<cbc:ID>VAT</cbc:ID>
				</cac:TaxScheme>
			</cac:ClassifiedTaxCategory>
		</cac:Item>
		<cac:Price>
			<cbc:PriceAmount currencyID="EUR">95.00</cbc:PriceAmount>
		</cac:Price>
	</cac:InvoiceLine>
	<cac:InvoiceLine>
		<cbc:ID>2</cbc:ID>
		<cbc:InvoicedQuantity unitCode="H87">1</cbc:InvoicedQuantity>
		<cbc:LineExtensionAmount currencyID="EUR">500.00</cbc:LineExtensionAmount>
		<cac:Item>
			<cbc:Description>Entwicklung eines Corporate Designs inkl. Logo</cbc:Description>
			<cbc:Name>Logo-Design</cbc:Name>
			<cac:ClassifiedTaxCategory>
				<cbc:ID>S</cbc:ID>
				<cbc:Percent>19</cbc:Percent>
				<cac:TaxScheme>
					<cbc:ID>VAT</cbc:ID>
				</cac:TaxScheme>
			</cac:ClassifiedTaxCategory>
		</cac:Item>
		<cac:Price>
			<cbc:PriceAmount currencyID="EUR">500.00</cbc:PriceAmount>
		</cac:Price>
	</cac:InvoiceLine>
</Invoice>

Der einfachere Weg: XRechnung per API erstellen

Die manuelle Erstellung des detaillierten XML-Formats kann, wie das Beispiel zeigt, aufwändig und fehleranfällig sein. Für Entwickler, die eine schnellere und robustere Lösung suchen, bieten spezialisierte Dienste eine erhebliche Vereinfachung. Ein solcher Dienst ist RechnungsAPI, eine SaaS-Plattform, die den gesamten Prozess der E-Rechnungs-Erstellung hinter einer einfachen JSON REST API abstrahiert. RechnungsAPI übernimmt auch die Erstellung einer anschaulichen PDF-Datei, welche in die XRechnung XML eingebettet werden kann.

Fazit und nächste Schritte

Das Erstellen einer XRechnung erfordert Sorgfalt. Jedes Feld hat eine klare semantische Bedeutung, und die Geschäftsregeln (z.B. korrekte Berechnung der Summen) müssen eingehalten werden.

Für Entwickler ist der nächste logische Schritt, die Validierung zu prüfen. Die Koordinierungsstelle für IT-Standards (KoSIT) stellt einen Validator zur Verfügung, mit dem erstellte XRechnungen auf Konformität geprüft werden können. Dies ist ein unverzichtbarer Schritt vor dem produktiven Einsatz.

Die Arbeit mit XML kann mühsam sein. Daher ist es ratsam, bestehende Bibliotheken und Frameworks in Ihrer Programmiersprache zu evaluieren, die die Erstellung von UBL-Dokumenten abstrahieren und vereinfachen. Dies reduziert den manuellen Aufwand und minimiert Fehlerquellen.