Created with AI

XRechnung for developers: the UBL format in detail

XRechnung is the German standard for electronic invoices to the public sector – and, since the German B2B e-invoicing mandate, relevant well beyond it. This article explains the format from a developer's perspective: we dissect a complete example invoice in the UBL syntax and explain the most important fields.

What is an XRechnung?

An XRechnung is not a PDF file but a structured, machine-readable XML file. The standard is operated by the Koordinierungsstelle für IT-Standards (KoSIT) on behalf of the German IT Planning Council. The currently valid version is 3.0.2 (since July 2024, most recently updated with the "Winter 2025/26" bugfix release).

Technically, XRechnung is a CIUS (Core Invoice Usage Specification) of the European standard EN 16931: a national specialization that supplements the European requirements with German business rules. Like EN 16931, XRechnung permits two XML syntaxes:

  • UBL 2.1 (Universal Business Language, an OASIS standard, ISO/IEC 19845)
  • UN/CEFACT Cross Industry Invoice (CII)

This article uses UBL. The CII syntax is primarily used by ZUGFeRD.

  • B2G: EU Directive 2014/55/EU obliges public-sector bodies to receive and process EN 16931 compliant e-invoices. Suppliers to the German federal government have had to submit their invoices electronically since 2020-11-27 (§ 3 E-Rechnungsverordnung); the Leitweg-ID is a mandatory field (§ 5 ERechV).
  • B2B: Since 2025-01-01, e-invoicing under § 14 UStG has been the standard for transactions between domestic German businesses. Every business must be able to receive e-invoices; transition periods under § 27(38) UStG apply to issuing them (with the recipient's consent: other invoice formats until the end of 2026, or until the end of 2027 for businesses with a previous-year turnover of up to €800,000).
  • The Federal Ministry of Finance guidance of 2024-10-15 (amended by the guidance of 2025-10-15) explicitly confirms XRechnung as a permissible format.

Anatomy of an XRechnung

1. Header and metadata

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-2026-001</cbc:ID>
	<cbc:IssueDate>2026-06-15</cbc:IssueDate>
	<cbc:DueDate>2026-07-15</cbc:DueDate>
	<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
	<cbc:Note>Notiz für die XRechnung</cbc:Note>
	<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
	<cbc:BuyerReference>PROJEKT-2026-XR</cbc:BuyerReference>
</Invoice>
  • CustomizationID: The specification identifier. It declares the invoice as compliant with EN 16931 and the XRechnung 3.0 standard.
  • ProfileID: The business process identifier; the default value is the Peppol billing process urn:fdc:peppol.eu:2017:poacc:billing:01:1.0.
  • ID (BT-1): The unique invoice number.
  • IssueDate (BT-2) / DueDate (BT-9): Issue and due dates in the format YYYY-MM-DD.
  • InvoiceTypeCode (BT-3): The invoice type according to UNTDID 1001; "380" is the commercial invoice.
  • DocumentCurrencyCode (BT-5): The currency according to ISO 4217.
  • BuyerReference (BT-10): The buyer reference. In invoices to German authorities this carries the Leitweg-ID, which addresses the recipient within the administration.

2. The supplier

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 (BT-34): The electronic address. The schemeID attribute qualifies the address type according to the EAS code list – "EM" stands for an email address.
  • PartyTaxScheme/CompanyID (BT-31): The VAT identification number.
  • PartyLegalEntity/RegistrationName (BT-27): The official company name.
  • Contact: A contact person with phone and email.

3. The customer

The cac:AccountingCustomerParty block is structured analogously and contains the buyer's data – electronic address (BT-49), postal address and VAT ID.

4. Payment details

xml
<cac:PaymentMeans>
	<cbc:PaymentMeansCode>58</cbc:PaymentMeansCode>
	<cac:PayeeFinancialAccount>
		<cbc:ID>DE12345678901234567890</cbc:ID>
		<cbc:Name>Muster GmbH</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 (BT-81): The payment means according to UNTDID 4461. Code "58" is the SEPA credit transfer, "30" the generic credit transfer.
  • PayeeFinancialAccount: IBAN (BT-84), account holder (BT-85) and BIC (BT-86).
  • PaymentTerms/Note (BT-20): Free text for payment terms such as the payment deadline or an early payment discount.

5. Tax and document totals

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>
  • TaxSubtotal: A breakdown per tax rate with the taxable amount (BT-116) and the tax amount (BT-117).
  • TaxCategory/ID (BT-118): The tax category according to UNTDID 5305. "S" stands for transactions taxed at the standard rate – the reduced German rate of 7 % is also encoded as "S" with the corresponding percentage.
  • LegalMonetaryTotal: Sum of the line net amounts (BT-106), net total (BT-109), gross total (BT-112) and amount due (BT-115). These totals must add up exactly – validators check this strictly.

6. The invoice lines

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>
  • InvoicedQuantity (BT-129): The quantity. The unitCode attribute (BT-130) carries the unit of measure according to UN/ECE Recommendation N°20 or N°21 – "HUR" is the hour, "H87" the piece.
  • LineExtensionAmount (BT-131): The net amount of the line (quantity × unit price).
  • ClassifiedTaxCategory (BT-151/BT-152): The tax category and rate of the line.
  • Price/PriceAmount (BT-146): The net unit price.

The complete example

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-2026-001</cbc:ID>
	<cbc:IssueDate>2026-06-15</cbc:IssueDate>
	<cbc:DueDate>2026-07-15</cbc:DueDate>
	<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
	<cbc:Note>Notiz für die XRechnung</cbc:Note>
	<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
	<cbc:BuyerReference>PROJEKT-2026-XR</cbc:BuyerReference>
	<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>58</cbc:PaymentMeansCode>
		<cac:PayeeFinancialAccount>
			<cbc:ID>DE12345678901234567890</cbc:ID>
			<cbc:Name>Muster GmbH</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>

Validation

Every generated XRechnung should be validated before productive use. KoSIT provides open-source tools for this: the generic validator and the official validation configuration for XRechnung, which contains the XML schema and the Schematron business rules for both syntaxes.

The easier way: creating XRechnung invoices via API

Building the XML by hand is laborious and error-prone – every field has defined semantics, and the EN 16931 business rules (for example on totals) are checked strictly. RechnungsAPI abstracts the entire process behind a JSON REST API and produces validated XRechnung invoices from it, including an optional PDF rendering. Our tutorial on creating XRechnung invoices via API shows how.

Sources