Germany ๐ฉ๐ช
XRechnung requirements and e-invoicing compliance for the German market.
Overviewโ
| Aspect | Details |
|---|---|
| B2G Mandate | Required (federal since 2020, states 2022-2024) |
| B2B Mandate | 2025 (receiving), 2027-2028 (sending) |
| Required CIUS | XRechnung (mandatory for B2G) |
| Primary Scheme | 0204 (Leitweg-ID for B2G), 9930 (VAT) |
| Government Portal | ZRE (federal), various state portals |
Germany has mandated B2B e-invoicing:
- 2025: All businesses must be able to receive e-invoices
- 2027: Businesses >โฌ800k turnover must send e-invoices
- 2028: All businesses must send e-invoices
XRechnung CIUSโ
XRechnung is Germany's national extension of EN16931, mandatory for B2G.
Customization IDโ
<!-- XRechnung 3.0.1 (current version) -->
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
Profile IDโ
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
Identifier Schemesโ
Leitweg-ID (0204) โ B2G Requiredโ
The routing ID for German public administration:
# Format: 04-xxx-xxxxx-xx (structure varies by state)
participant = {
"scheme": "0204",
"identifier": "04011000-12345-67",
"name": "Bundesministerium fรผr Wirtschaft",
"country": "DE"
}
Structure:
- Coarse routing: Entity type + region
- Fine routing: Specific department
- Check digit for validation
VAT Number (9930) โ B2Bโ
For business-to-business invoicing:
# Format: DE + 9 digits
participant = {
"scheme": "9930",
"identifier": "DE123456789",
"name": "Example GmbH",
"country": "DE"
}
Looking Up Leitweg-IDsโ
Government entities are listed in:
- LeitID-Service (official lookup)
- Invoice portal documentation
Government Portalsโ
Federal (ZRE)โ
All federal invoices go through the Zentrale Rechnungseingangsplattform:
# Sending to federal government
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/documents",
headers={"X-API-Key": "your_api_key"},
json={
"receiver_scheme": "0204",
"receiver_id": "04011000-12345-67",
# The buyer reference is MANDATORY and is carried in the UBL document
# as cbc:BuyerReference (Leitweg-ID format), not as a request field.
"document": invoice_xml
}
)
Requirements:
- โ XRechnung format
- โ Leitweg-ID as buyer endpoint
- โ Buyer reference (often Leitweg-ID or PO number)
State Portalsโ
Each German state has its own portal:
| State | Portal | Mandate Date |
|---|---|---|
| Baden-Wรผrttemberg | service-bw.de | 01/2022 |
| Bayern | eBill Bayern | 04/2024 |
| Berlin | ZRE | 11/2020 |
| Brandenburg | ZRE | 11/2020 |
| Nordrhein-Westfalen | eRechnung.NRW | 04/2020 |
Invoice Requirementsโ
Mandatory for XRechnungโ
<Invoice>
<!-- XRechnung CustomizationID -->
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0</cbc:CustomizationID>
<!-- CRITICAL: Buyer Reference (Leitweg-ID often used) -->
<cbc:BuyerReference>04011000-12345-67</cbc:BuyerReference>
<!-- German sender with VAT -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="9930">DE123456789</cbc:EndpointID>
<cac:PartyTaxScheme>
<cbc:CompanyID>DE123456789</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- Government receiver with Leitweg-ID -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0204">04011000-12345-67</cbc:EndpointID>
</cac:Party>
</cac:AccountingCustomerParty>
</Invoice>
Banking Informationโ
The payment reference the buyer quotes (the Verwendungszweck, BT-83) is
payment.payment_id. It is cbc:PaymentID in the UBL below, and
ram:PaymentReference in the CII inside the ZUGFeRD PDF, whatever the payment means
and whether or not an account is given.
SEPA payment information is expected:
<cac:PaymentMeans>
<cbc:PaymentMeansCode>58</cbc:PaymentMeansCode>
<cbc:PaymentID>Rechnungsnr-2024-001</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>DE89370400440532013000</cbc:ID>
<cbc:Name>Muster GmbH</cbc:Name>
<cac:FinancialInstitutionBranch>
<cbc:ID>COBADEFFXXX</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
Direct debit (SEPA-Lastschrift)โ
A direct debit between two German parties needs three things: the mandate reference
(payment.mandate_reference), the buyer's account to debit (payment.debited_account), and
your SEPA Creditor Identifier (payment.creditor_id). The German rules require the last two
whenever a mandate is present: DE-R-030 and DE-R-031, or BR-DE-30 and BR-DE-31 in
XRechnung. The creditor identifier is written as the seller's party identification with
scheme SEPA, or as the payee's when you give a payee. If one is missing,
POST /api/v1/invoices answers validation_failed with BUS_046.
German VATโ
VAT Formatโ
# German VAT: DE + 9 digits
def validate_german_vat(vat: str) -> bool:
if not vat.startswith("DE"):
return False
if len(vat) != 11:
return False
return vat[2:].isdigit()
VAT Ratesโ
The Code column is the VAT category, which is a different field from the percentage: the
category says why a rate applies, the percentage says what it is. Both German positive rates
are category S carrying their own percentage.
| Code | Rate | Description |
|---|---|---|
| S | 19% | Standard rate |
| S | 7% | Reduced rate |
| Z | 0% | Zero rate |
| E | 0% | Exempt |
AA is rejectedEarlier revisions of this page gave AA for the 7% rate. It is not a permitted VAT category.
EN 16931 allows only AE, B, E, G, K, L, M, O, S and Z
(UNCL5305), and rules BR-CL-17
and BR-CL-18 reject anything else โ the invoice fails validation and is never delivered. Send
the reduced rate as S with 7 in the percentage.
Example XRechnung 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">
<!-- XRechnung 3.0 -->
<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>DE-RG-2024-001234</cbc:ID>
<cbc:IssueDate>2024-01-15</cbc:IssueDate>
<cbc:DueDate>2024-02-15</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>EUR</cbc:DocumentCurrencyCode>
<!-- MANDATORY for XRechnung -->
<cbc:BuyerReference>04011000-12345-67</cbc:BuyerReference>
<!-- Seller (German company) -->
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="9930">DE123456789</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Beispiel GmbH</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Musterstraรe 1</cbc:StreetName>
<cbc:CityName>Berlin</cbc:CityName>
<cbc:PostalZone>10115</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>Beispiel GmbH</cbc:RegistrationName>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>Max Mustermann</cbc:Name>
<cbc:ElectronicMail>rechnung@beispiel.de</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingSupplierParty>
<!-- Buyer (German government) -->
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0204">04011000-12345-67</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>Bundesministerium</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Regierungsstraรe 1</cbc:StreetName>
<cbc:CityName>Berlin</cbc:CityName>
<cbc:PostalZone>10117</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Bundesministerium</cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>58</cbc:PaymentMeansCode>
<cbc:PaymentID>RG-2024-001234</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>DE89370400440532013000</cbc:ID>
<cbc:Name>Beispiel GmbH</cbc:Name>
<cac:FinancialInstitutionBranch>
<cbc:ID>COBADEFFXXX</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="EUR">19.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="EUR">100.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="EUR">19.00</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">100.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="EUR">100.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="EUR">119.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="EUR">119.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:InvoicedQuantity unitCode="HUR">10</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="EUR">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>IT-Beratung</cbc:Description>
<cbc:Name>Beratungsleistung</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">10.00</cbc:PriceAmount>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
GoRoute validation for German invoicesโ
Which German checks run depends on how you submit the invoice, so pick the endpoint that matches what you have.
If you build the invoice through GoRouteโ
POST /api/v1/invoices/validate is a dry run over the canonical invoice model, and it is
the path that applies the German rules:
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/invoices/validate",
headers={"X-API-Key": "your_api_key"},
json={"invoice": invoice_payload}
)
# German checks applied here:
# - DE_001 (error) Leitweg-ID required in buyer_reference for B2G (scheme 0204)
# - DE_002 (warning) Leitweg-ID format looks wrong
# - DE_003 (warning) German VAT number should be DE followed by 9 digits
If you already have UBL XMLโ
POST /api/v1/documents/validate checks the document itself with GoRoute's own checks โ
root element, header, parties, tax and monetary totals, lines and a set of business rules.
It does not run the XSD or the official Schematron on raw XML:
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/documents/validate",
headers={"X-API-Key": "your_api_key"},
json={
"document": invoice_xml, # UBL XML string
"profile": "en16931"
}
)
GoRoute's validation endpoints do not run KoSIT's XRechnung Schematron (BR-DE-*) today.
POST /api/v1/invoices/validate/deep runs the CEN EN 16931 and Peppol BIS 3.0 rules on the
UBL GoRoute renders, and POST /api/v1/documents/validate runs GoRoute's own checks on raw
XML. For XRechnung, run KoSIT's validator with the
XRechnung configuration in your own pipeline before you send. GoRoute accepts XRechnung in
UBL only; XRechnung CII is refused โ see
ZUGFeRD, Factur-X and XRechnung CII.
Buyers not on Peppol: ZUGFeRD by emailโ
Most German businesses receive their e-invoices by email as a ZUGFeRD PDF โ a
PDF/A-3 with the EN 16931 invoice embedded as factur-x.xml (the same file France
calls Factur-X). GoRoute produces it from the same canonical invoice it renders to UBL.
- Which PDFs are hybrids.
GET /api/v1/transactions/{transaction_id}/pdfreturns the PDF/A-3 with the CII XML inside for invoices and credit notes, whether the document went over Peppol or not, when both of these hold. First, the seller is in one of 32 countries: the EU, plus Iceland, Liechtenstein, Norway, Switzerland and the United Kingdom โ the set is wider than the EU. Second, GoRoute holds the invoice as structured data, which it does forPOST /api/v1/invoices, a saved draft, a CSV or Excel import, a batch send and a connector, but not for raw UBL posted toPOST /api/v1/documents. For a raw-UBL document the download quietly returns the plain PDF: there is no error and no warning, so if your buyers expect ZUGFeRD, send structured invoices. Pass?hybrid=falsefor the plain PDF.GET /api/v1/transactions/{transaction_id}/document/content?syntax=ciireturns the XML alone. The full rules are on Delivery and formats. - The account to pay into. The embedded XML states a credit transfer (payment
means code 30) only when it can name the account:
payment.bank_account.iban, or on an invoice the invoice seller's ownbank_account. Without one it states code 1, "instrument not defined", because a credit transfer with no account fails the EN 16931 rules (CII-SR-470) and XRechnung's (BR-DE-23-a). A credit note never names the seller's own account, since its money goes to the buyer; to name the account a refund is paid into, give it inpayment.bank_account. - XRechnung always states how to pay. When the document went out as XRechnung, the
embedded XML is XRechnung CII, and XRechnung wants payment instructions on every
invoice and credit note (BR-DE-1). Without
payment, an invoice with an amount due states a credit transfer into the seller's ownbank_account(code 30), or code 1 if there is none; a credit note, or an invoice with nothing to pay, states code 1. A card payment (payment.means: card) is stated as code 1 with the text "Kartenzahlung" and no account: XRechnung's code 48 needs the card's details (BR-DE-24-a), which GoRoute does not take. A ZUGFeRD or Factur-X hybrid states nothing without payment details, and a card as code 48. - The channel is chosen per document.
POST /api/v1/invoicesacceptsdelivery_channel(auto,peppol,email) anddocument_format(auto,ubl,xrechnung,cii,zugferd). Inauto, a buyer registered on Peppol gets the document over the network in the profile they advertise (BIS 3.0, or XRechnung when that is all a public buyer accepts); a buyer who is not on Peppol gets the document issued for email: the transaction is stored in the terminal stateissuedwithdelivery_channel: "email", nothing is transmitted, and the PDF is what you send. The response'sdeliveryobject says what was chosen and why. - A buyer with only a VAT number is addressed as
9930:DEโฆautomatically. - Where a mandate forbids email (Belgian B2B, Oman, Italy, Poland) an email
delivery is refused with
EMAIL_NOT_ALLOWED; Germany, France, the Netherlands, Australia and New Zealand allow it.
response = requests.post(
"https://app.goroute.ai/peppol-api/api/v1/invoices",
headers={"X-API-Key": "your_api_key"},
json={"invoice": invoice_payload, "delivery_channel": "auto"},
)
delivery = response.json()["delivery"]
# {"channel": "email", "format": "cii", "hybrid_pdf": true, "hybrid_profile": "zugferd",
# "buyer_on_network": false, "reason": "The buyer is not on the Peppol network; ..."}
if delivery["channel"] == "email":
pdf = requests.get(f".../transactions/{response.json()['transaction_id']}/pdf", headers=...)
# attach pdf.content to your email: it is the ZUGFeRD invoice
The WooCommerce plugin does this for every German order: a business buyer not on Peppol receives the ZUGFeRD PDF with the order email.
B2B Mandate Preparationโ
What to Do Nowโ
- Register on Peppol to receive invoices
- Update accounting systems to process e-invoices
- Test with partners before mandate dates
- Archive digitally (GoBD compliance)
Timelineโ
Resourcesโ
Next Stepsโ
Further readingโ
- XRechnung and ZUGFeRD explained
- Germany overview
- 2026 e-invoicing mandate tracker โ every country, one page
- How to choose a Peppol Access Point
- One API for multi-country e-invoicing
Ready to build? The free developer sandbox gives you test credentials and a registered participant, provisioned within 24 hours on business days. Recorded ERP integration walkthroughs are on the tutorials page.