Germany
XRechnung and ZUGFeRD e-invoicing requirements for Germany, with Beliq configuration examples.
Germany mainly uses two EN 16931-based e-invoicing formats:
- XRechnung: mandatory for many public-sector invoices (B2G) and increasingly used in B2B
- ZUGFeRD: a PDF invoice with embedded XML data for system processing
Mandate timeline
Germany is phasing in mandatory B2B e-invoicing. Receiving a structured invoice is already required; issuing is phased in by prior-year turnover.
| Date | What changes |
|---|---|
| 1 January 2025 | Every domestic business must be able to receive an EN 16931 e-invoice. |
| 1 January 2027 | Issuing becomes mandatory for businesses with prior-year turnover above EUR 800,000. |
| 1 January 2028 | Issuing becomes mandatory for all remaining domestic businesses except those under the small-business scheme (Kleinunternehmer). |
Paper invoices, and PDF invoices where the recipient consents, stay permitted for every business through 31 December 2026, and through 31 December 2027 for businesses with prior-year turnover up to EUR 800,000. Non-conforming EDI stays permitted through 31 December 2027 where the recipient consents (§ 27 Abs. 38 Nr. 3 UStG). In every phase, among other cases, invoices for supplies under the small-business scheme (§ 19 UStG), invoices up to EUR 250 gross and tickets need not be e-invoices. The European Commission country page says the 2028 date extends to all remaining businesses, so it is not the source here.
Last verified against the German Federal Ministry of Finance (BMF) e-invoicing FAQ (as of March 2026) and § 27 Abs. 38 UStG on 20 October 2026. Official source.
For the dates Beliq tracks across every covered country, see the mandate calendar.
XRechnung
XRechnung is Germany’s official CIUS profile of EN 16931, maintained by KoSIT. It adds German-specific business rules on top of EN 16931.
Key requirements
| Rule | Description |
|---|---|
| Buyer reference (BT-10) | Required (BR-DE-15). For B2G this is the “Leitweg-ID” that identifies the receiving government entity |
| Seller contact (BG-6) | Required (BR-DE-2): contact point (BT-41), telephone (BT-42) and email (BT-43) |
| Electronic addresses (BT-34, BT-49) | Required for both parties; Beliq returns 400 when it cannot resolve one. Give each an email, a peppol block, or a vatId with a supported country. A peppol block is the stronger choice when the invoice travels over Peppol, and it is honoured on the CII binding too |
| Payment instructions (BG-16) | Required (BR-DE-1) |
| Payment means | At least one payment means must be specified |
| VAT identifiers | Either vatId (BT-31) or taxId must be provided for the seller |
Generating XRechnung invoices
Use standard: "xrechnung" with output: "xml":
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer blq_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"standard": "xrechnung",
"profile": "xrechnung",
"output": "xml",
"invoice": {
"number": "RE-2026-0042",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Muster GmbH",
"vatId": "DE123456789",
"email": "rechnung@muster.example",
"contactName": "Klaus Muster",
"phone": "+49 30 1234567",
"address": {
"street": "Hauptstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE"
}
},
"buyer": {
"name": "Stadtverwaltung Beispielstadt",
"email": "eingangsrechnung@beispielstadt.example",
"address": {
"city": "Beispielstadt",
"postalCode": "12345",
"countryCode": "DE"
}
},
"lines": [
{
"description": "Beratungsleistung April 2026",
"quantity": 40,
"unitCode": "HUR",
"unitPrice": 95.00,
"lineTotal": 3800.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 3800.00, "taxAmount": 722.00 }
],
"paymentMeans": {
"typeCode": "58",
"iban": "DE89370400440532013000"
},
"totalNetAmount": 3800.00,
"totalTaxAmount": 722.00,
"totalGrossAmount": 4522.00
}
}'import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'xrechnung',
profile: 'xrechnung',
output: 'xml',
invoice: {
number: 'RE-2026-0042',
issueDate: '2026-04-13',
dueDate: '2026-05-13',
currencyCode: 'EUR',
buyerReference: '04011000-12345-03',
seller: {
name: 'Muster GmbH',
vatId: 'DE123456789',
email: 'rechnung@muster.example',
contactName: 'Klaus Muster',
phone: '+49 30 1234567',
address: { street: 'Hauptstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: {
name: 'Stadtverwaltung Beispielstadt',
email: 'eingangsrechnung@beispielstadt.example',
address: { city: 'Beispielstadt', postalCode: '12345', countryCode: 'DE' },
},
lines: [
{
description: 'Beratungsleistung April 2026',
quantity: 40,
unitCode: 'HUR',
unitPrice: 95.00,
lineTotal: 3800.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 3800.00, taxAmount: 722.00 }],
paymentMeans: { typeCode: '58', iban: 'DE89370400440532013000' },
totalNetAmount: 3800.00,
totalTaxAmount: 722.00,
totalGrossAmount: 4522.00,
},
});
// `xml` is the same document curl writes to stdout.
console.log(generated.xml);import os
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="xrechnung",
profile="xrechnung",
output="xml",
invoice={
"number": "RE-2026-0042",
"issueDate": "2026-04-13",
"dueDate": "2026-05-13",
"currencyCode": "EUR",
"buyerReference": "04011000-12345-03",
"seller": {
"name": "Muster GmbH",
"vatId": "DE123456789",
"email": "rechnung@muster.example",
"contactName": "Klaus Muster",
"phone": "+49 30 1234567",
"address": {
"street": "Hauptstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Stadtverwaltung Beispielstadt",
"email": "eingangsrechnung@beispielstadt.example",
"address": {"city": "Beispielstadt", "postalCode": "12345", "countryCode": "DE"},
},
"lines": [
{
"description": "Beratungsleistung April 2026",
"quantity": 40,
"unitCode": "HUR",
"unitPrice": 95.00,
"lineTotal": 3800.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 3800.00, "taxAmount": 722.00}],
"paymentMeans": {"typeCode": "58", "iban": "DE89370400440532013000"},
"totalNetAmount": 3800.00,
"totalTaxAmount": 722.00,
"totalGrossAmount": 4522.00,
},
)
# `xml` is the same document curl writes to stdout.
print(generated.xml)XML syntax
XRechnung supports both UBL 2.1 and CII D16B. Beliq generates CII, and the request has no field that picks UBL. For XRechnung in UBL, send the CII to POST /v1/convert with sourceFormat=cii&targetFormat=xrechnung.
Submission channels
XRechnung invoices are submitted to government entities via:
- ZRE (Zentraler Rechnungseingang): for federal agencies
- OZG-RE: for state and municipal authorities
Beliq generates and validates the XML. Submission to government portals is handled by your ERP or AP system.
Validation
Beliq validates XRechnung invoices against:
- CII D16B or UBL 2.1 XSD schema
- EN 16931 core Schematron rules (currently v1.3.16)
- XRechnung-specific Schematron rules (currently v2.6.0)
See the validation artifacts page for version details.
ZUGFeRD 2.x
ZUGFeRD (Zentraler User Guide des Forums elektronische Rechnung Deutschland) is a hybrid format that embeds CII D22B XML inside a PDF/A-3 document. Beliq targets ZUGFeRD 2.x, jointly published with Factur-X 1.09.2, and it is widely used in German B2B invoicing because one file supports both people and systems.
Profiles
ZUGFeRD supports multiple profiles that determine the level of detail in the embedded XML:
| Profile | Beliq value | Description |
|---|---|---|
| Minimum | minimum |
Minimal structured data (invoice number, date, totals) |
| Basic WL | basicwl |
Basic without lines: header data only, no line items |
| Basic | basic |
Complete header data and line items |
| EN 16931 (Comfort) | en16931 |
Full EN 16931 compliance; recommended for most use cases |
| Extended | extended |
Additional fields beyond EN 16931 |
Generating ZUGFeRD invoices
Use standard: "zugferd" with output: "pdf":
curl -X POST https://api.beliq.eu/v1/generate \
-H "Authorization: Bearer blq_live_abc123..." \
-H "Content-Type: application/json" \
-d '{
"standard": "zugferd",
"profile": "en16931",
"output": "pdf",
"invoice": {
"number": "RE-2026-0042",
"issueDate": "2026-04-13",
"currencyCode": "EUR",
"seller": {
"name": "Muster GmbH",
"vatId": "DE123456789",
"address": {
"street": "Hauptstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE"
}
},
"buyer": {
"name": "Kunde AG",
"address": {
"city": "München",
"postalCode": "80331",
"countryCode": "DE"
}
},
"lines": [
{
"description": "Software-Lizenz",
"quantity": 1,
"unitCode": "C62",
"unitPrice": 499.00,
"lineTotal": 499.00,
"vatRate": 19,
"vatCategoryCode": "S"
}
],
"taxSummary": [
{ "vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 499.00, "taxAmount": 94.81 }
],
"totalNetAmount": 499.00,
"totalTaxAmount": 94.81,
"totalGrossAmount": 593.81
}
}' --output invoice.pdfimport { writeFile } from 'node:fs/promises';
import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const generated = await beliq.generate({
standard: 'zugferd',
profile: 'en16931',
output: 'pdf',
invoice: {
number: 'RE-2026-0042',
issueDate: '2026-04-13',
currencyCode: 'EUR',
seller: {
name: 'Muster GmbH',
vatId: 'DE123456789',
address: { street: 'Hauptstraße 1', city: 'Berlin', postalCode: '10115', countryCode: 'DE' },
},
buyer: { name: 'Kunde AG', address: { city: 'München', postalCode: '80331', countryCode: 'DE' } },
lines: [
{
description: 'Software-Lizenz',
quantity: 1,
unitCode: 'C62',
unitPrice: 499.00,
lineTotal: 499.00,
vatRate: 19,
vatCategoryCode: 'S',
},
],
taxSummary: [{ vatCategoryCode: 'S', vatRate: 19, taxableAmount: 499.00, taxAmount: 94.81 }],
totalNetAmount: 499.00,
totalTaxAmount: 94.81,
totalGrossAmount: 593.81,
},
});
await writeFile('invoice.pdf', generated.bytes);import os
from pathlib import Path
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
generated = beliq.generate(
standard="zugferd",
profile="en16931",
output="pdf",
invoice={
"number": "RE-2026-0042",
"issueDate": "2026-04-13",
"currencyCode": "EUR",
"seller": {
"name": "Muster GmbH",
"vatId": "DE123456789",
"address": {
"street": "Hauptstraße 1",
"city": "Berlin",
"postalCode": "10115",
"countryCode": "DE",
},
},
"buyer": {
"name": "Kunde AG",
"address": {"city": "München", "postalCode": "80331", "countryCode": "DE"},
},
"lines": [
{
"description": "Software-Lizenz",
"quantity": 1,
"unitCode": "C62",
"unitPrice": 499.00,
"lineTotal": 499.00,
"vatRate": 19,
"vatCategoryCode": "S",
},
],
"taxSummary": [{"vatCategoryCode": "S", "vatRate": 19, "taxableAmount": 499.00, "taxAmount": 94.81}],
"totalNetAmount": 499.00,
"totalTaxAmount": 94.81,
"totalGrossAmount": 593.81,
},
)
Path("invoice.pdf").write_bytes(generated.content)The resulting PDF is a hybrid with the CII XML embedded. With the default verify: true the XML is validated before assembly. Before the PDF is returned, veraPDF checks it against its PDF/A-3b profile, and a file in which it reports a violation is not returned (the PDF/A check on a hybrid PDF).
Parsing ZUGFeRD invoices
Upload a ZUGFeRD PDF to the parse endpoint to extract the embedded invoice data:
curl -X POST https://api.beliq.eu/v1/parse \
-H "Authorization: Bearer blq_live_abc123..." \
-H "Content-Type: application/octet-stream" \
--data-binary @invoice.pdfimport { readFile } from 'node:fs/promises';
import { Beliq } from '@beliq/sdk';
const beliq = new Beliq({ apiKey: process.env.BELIQ_API_KEY! });
const parsed = await beliq.parse(await readFile('invoice.pdf'));
console.log(parsed.format, parsed.profileDetected);
console.log(parsed.invoice);import os
from pathlib import Path
from beliq import Beliq
beliq = Beliq(api_key=os.environ["BELIQ_API_KEY"])
parsed = beliq.parse(Path("invoice.pdf").read_bytes())
print(parsed.format, parsed.profile_detected)
print(parsed.invoice)Beliq searches for known attachment filenames (factur-x.xml, zugferd-invoice.xml, ZUGFeRD-invoice.xml) and extracts the XML for parsing.
Common validation errors
| Rule ID | Message | Fix |
|---|---|---|
BR-DE-15 |
Buyer reference (BT-10) is missing | Add buyerReference to your invoice |
BR-DE-1 |
Payment instructions (BG-16) are missing | Add paymentMeans to your invoice |
BR-DE-2 |
Seller contact (BG-6) is missing | Add contactName to the seller object; BR-DE-5, BR-DE-6 and BR-DE-7 then ask for the name (BT-41), phone (BT-42) and email (BT-43) |
PEPPOL-EN16931-R020 / R010 |
Seller or buyer electronic address is missing | Add email, a peppol block, or a vatId to that party. On standard: "xrechnung" Beliq rejects this at the request boundary with 400, so a verified generate should not reach this rule |
BR-01 |
Specification identifier missing | This is set automatically by Beliq; email hello@beliq.eu if you see this |
BR-06 |
VAT identifier is missing | Add vatId (e.g. DE123456789) to the seller |
Resources
- XRechnung format reference: element layout, CIUS rules and pinned artefact versions
- ZUGFeRD format reference: profiles, hybrid PDF/A-3 packaging and pinned artefact versions
- XRechnung specification: official KoSIT documentation
- ZUGFeRD specification: official FeRD documentation
- EN 16931 business rules: CEN/TC 434 Schematron rules