ComplianceE-InvoiceXRechnung

E-Invoicing Mandate 2025: Complete Guide for Developers

E-invoicing becomes mandatory for B2B in 2025. Technical guide with code examples for XRechnung, ZUGFeRD, and Peppol. Implementation checklist included.

E-Invoicing Mandate 2025: Complete Guide for Developers
Patrick Jerominek

Patrick Jerominek

Cofounder

January 20, 2026
15 min reading time

Starting January 1, 2025, electronic invoicing (e-invoicing) is mandatory for B2B transactions in Germany. This fundamental change affects every piece of software that creates or processes invoices -- from ERP systems to accounting software to e-commerce platforms.

In this comprehensive guide, you'll learn everything you need to know as a developer: legal foundations, technical requirements, code examples, and a practical implementation checklist.


EU Directive 2014/55/EU

The European Directive 2014/55/EU has required public contracting authorities to receive and process electronic invoices since 2020. Germany implements this directive through the E-Invoice Regulation (ERechV).

The Growth Opportunities Act (Wachstumschancengesetz)

The Wachstumschancengesetz (Growth Opportunities Act), passed on March 27, 2024, extends the e-invoicing mandate to the entire B2B sector. Key changes at a glance:

  • Section 14 UStG (German VAT Act) has been updated and now defines binding requirements for electronic invoices
  • An e-invoice must be issued, transmitted, and received in a structured electronic format
  • The format must enable automated processing
  • PDF files are no longer considered e-invoices (except ZUGFeRD with embedded XML)

Phased Rollout

DateRequirementAffected
01.01.2025Ability to receive e-invoicesAll B2B companies
01.01.2027Sending e-invoicesCompanies with > 800,000 EUR prior-year revenue
01.01.2028Sending e-invoicesAll companies

Important: The obligation to receive e-invoices applies from 2025 to all companies -- regardless of size.


What Changes Concretely?

Until now, companies could exchange invoices in any format: PDF, paper, or proprietary formats. Starting in 2025, B2B invoices must be in a structured electronic format that is machine-processable.

This means for your software:

  1. Receiving: You must be able to accept e-invoices in XRechnung or ZUGFeRD format
  2. Processing: The structured data must be correctly parsed and imported into your system
  3. Archiving: E-invoices must be stored in compliance with GoBD regulations (10 years, immutable). The Archive API supports you with this.

Try the Playground now to see how e-invoices look and how the API works.


XRechnung vs. ZUGFeRD vs. Peppol

As a developer, you face the question: Which format should I implement? Here's a decision tree:

Decision Tree

text
1Invoice recipient?
2 Public administration (federal/state/municipal)
3 XRechnung (mandatory!)
4 International business partner (EU)
5 Peppol BIS Billing
6 German B2B companies
7 Recipient wants PDF view?
8 ZUGFeRD
9 Only structured data needed?
10 XRechnung

Technical Differences

FeatureXRechnungZUGFeRD 2.xPeppol BIS
Base standardEN 16931EN 16931EN 16931
XML syntaxUBL 2.1 or CIICII (Cross Industry Invoice)UBL 2.1
PDF includedNoYes (PDF/A-3)No
ValidationKoSIT validation toolKoSIT validation toolPeppol Validation
Use caseB2G, B2BB2B with PDF needsInternational B2B
File sizeSmall (~20 KB)Larger (~500 KB+)Small (~20 KB)

UBL vs. CII -- What's the Difference?

UBL (Universal Business Language) and CII (Cross Industry Invoice) are two XML syntaxes for the same semantic standard EN 16931:

  • UBL 2.1: Used by XRechnung (Germany), Peppol, FatturaPA (Italy)
  • CII: Used by ZUGFeRD, Factur-X (France)

Both contain the same business information; only the XML structure differs. With the Converter API, you can switch between formats.


Technical Requirements

1. Receiving E-Invoices (XML Parsing)

The first step is parsing incoming e-invoices. The Parser API makes this simple. Here's an example of reading an XRechnung:

typescript
1// TypeScript/Node.js - Parse XRechnung
2async function processIncomingInvoice(xmlContent: string) {
3 const response = await fetch("https://service.invoice-api.xhub.io/api/v1/invoice/de/xrechnung/parse", {
4 method: "POST",
5 headers: {
6 "Authorization": `Bearer ${process.env.XHUB_API_KEY}`,
7 "Content-Type": "application/xml"
8 },
9 body: xmlContent
10 });
11 
12 const result = await response.json();
13 // result: { success, invoice, format, hash, errors, warnings }
14 console.log("Invoice number:", result.invoice.invoiceNumber);
15 console.log("Total amount:", result.invoice.total);
16 
17 return result.invoice;
18}
python
1# Python - Parse XRechnung
2import requests
3 
4def process_incoming_invoice(xml_content: str):
5 response = requests.post(
6 "https://service.invoice-api.xhub.io/api/v1/invoice/de/xrechnung/parse",
7 headers={
8 "Authorization": f"Bearer {API_KEY}",
9 "Content-Type": "application/xml"
10 },
11 data=xml_content
12 )
13 
14 result = response.json()
15 # result: {success, invoice, format, hash, errors, warnings}
16 print(f"Invoice number: {result['invoice']['invoiceNumber']}")
17 print(f"Total amount: {result['invoice']['total']}")
18 
19 return result['invoice']

2. Validating E-Invoices

Before processing an e-invoice, you should validate it. KoSIT (Coordination Office for IT Standards) provides Schematron rules.

bash
1# cURL - Validate e-invoice
2curl -X POST https://service.invoice-api.xhub.io/api/v1/invoice/de/xrechnung/validate \
3 -H "Authorization: Bearer $XHUB_API_KEY" \
4 -H "Content-Type: application/xml" \
5 --data-binary @rechnung.xml
6 
7# Response
8{
9 "valid": true,
10 "format": "XRechnung 3.0.2",
11 "schematronPassed": true,
12 "warnings": [],
13 "errors": []
14}

You can find the complete API documentation at /docs/api/validator.

3. Creating and Sending E-Invoices

Creating compliant e-invoices is the most complex part. You need to correctly populate all mandatory fields and comply with the Schematron rules.

typescript
1// TypeScript/Node.js - Create e-invoice
2const response = await fetch("https://service.invoice-api.xhub.io/api/v1/invoice/de/xrechnung/generate", {
3 method: "POST",
4 headers: {
5 "Authorization": `Bearer ${process.env.XHUB_API_KEY}`,
6 "Content-Type": "application/json"
7 },
8 body: JSON.stringify({
9 invoice: {
10 type: "invoice",
11 invoiceNumber: "RE-2025-001",
12 issueDate: "2025-01-15",
13 dueDate: "2025-02-15",
14 currency: "EUR",
15 seller: {
16 name: "Meine Firma GmbH",
17 vatId: "DE123456789",
18 street: "Musterstraße 1",
19 city: "Berlin",
20 postalCode: "10115",
21 countryCode: "DE",
22 bankAccount: {
23 iban: "DE89370400440532013000",
24 bic: "COBADEFFXXX"
25 }
26 },
27 buyer: {
28 name: "Kunde AG",
29 vatId: "DE987654321",
30 street: "Kundenweg 42",
31 city: "München",
32 postalCode: "80331",
33 countryCode: "DE"
34 },
35 countrySpecific: {
36 countryCode: "DE", // required discriminator
37 leitwegId: "991-12345-67" // For public contracting authorities (B2G)
38 },
39 items: [
40 {
41 position: 1,
42 description: "Software development",
43 quantity: 40,
44 unit: "HUR",
45 unitPrice: 120.00,
46 taxRate: 19,
47 netAmount: 4800.00,
48 taxAmount: 912.00,
49 grossAmount: 5712.00
50 },
51 {
52 position: 2,
53 description: "Server hosting (January 2025)",
54 quantity: 1,
55 unit: "MON",
56 unitPrice: 299.00,
57 taxRate: 19,
58 netAmount: 299.00,
59 taxAmount: 56.81,
60 grossAmount: 355.81
61 }
62 ],
63 subtotal: 5099.00,
64 total: 6067.81,
65 taxSummary: [
66 { taxRate: 19, netAmount: 5099.00, taxAmount: 968.81 }
67 ],
68 paymentTerms: {
69 dueDays: 30,
70 description: "Payable within 30 days, net"
71 }
72 }
73 })
74});
75 
76const result = await response.json();
77// Response: { success, format, filename, mimeType, hash, data (base64), errors, warnings }
78console.log("Format:", result.format, "File:", result.filename);
python
1# Python - Create e-invoice
2import requests
3import os
4 
5response = requests.post(
6 "https://service.invoice-api.xhub.io/api/v1/invoice/de/xrechnung/generate",
7 headers={
8 "Authorization": f"Bearer {os.environ['XHUB_API_KEY']}",
9 "Content-Type": "application/json"
10 },
11 json={
12 "invoice": {
13 "type": "invoice",
14 "invoiceNumber": "RE-2025-001",
15 "issueDate": "2025-01-15",
16 "dueDate": "2025-02-15",
17 "currency": "EUR",
18 "seller": {
19 "name": "Meine Firma GmbH",
20 "vatId": "DE123456789",
21 "street": "Musterstraße 1",
22 "city": "Berlin",
23 "postalCode": "10115",
24 "countryCode": "DE"
25 },
26 "buyer": {
27 "name": "Kunde AG",
28 "vatId": "DE987654321",
29 "street": "Kundenweg 42",
30 "city": "München",
31 "postalCode": "80331",
32 "countryCode": "DE"
33 },
34 "items": [
35 {
36 "position": 1,
37 "description": "Software development",
38 "quantity": 40,
39 "unit": "HUR",
40 "unitPrice": 120.00,
41 "taxRate": 19,
42 "netAmount": 4800.00,
43 "taxAmount": 912.00,
44 "grossAmount": 5712.00
45 }
46 ],
47 "subtotal": 4800.00,
48 "total": 5712.00,
49 "taxSummary": [
50 { "taxRate": 19, "netAmount": 4800.00, "taxAmount": 912.00 }
51 ],
52 "paymentTerms": { "dueDays": 30 }
53 }
54 }
55)
56 
57result = response.json()
58# Response: {success, format, filename, mimeType, hash, data (base64), errors, warnings}
59print(f"Format: {result['format']}, File: {result['filename']}")

You can find the complete API documentation for creating e-invoices at /docs/api/creator.


Implementation Checklist

Use this checklist to ensure your software is ready for the e-invoicing mandate:

Receiving (Mandatory from 01.01.2025)

  • Able to parse XRechnung (UBL)
  • Able to parse XRechnung (CII)
  • Able to parse ZUGFeRD 2.x (PDF with embedded XML)
  • Validation of incoming invoices implemented
  • Error messages for invalid invoices displayed
  • GoBD-compliant archiving implemented

Sending (Mandatory from 01.01.2027/2028)

  • XRechnung export implemented
  • ZUGFeRD export implemented (if PDF is desired)
  • Leitweg-ID supported for public contracting authorities
  • Validation before sending implemented
  • All mandatory fields per EN 16931 populated
  • Unit tests for e-invoice generation

General

  • API integration tested (sandbox environment)
  • Error handling for API outages implemented
  • Retry logic for failed requests
  • Logging and monitoring set up -- use Webhooks for real-time notifications

Common Errors and Solutions

Certain validation errors occur particularly frequently when implementing e-invoices:

BR-DE-01: Missing Leitweg-ID

Error: BR-DE-01: An invoice to public contracting authorities must contain a Leitweg-ID.

Solution: If the invoice recipient is a public administration, you must provide the Leitweg-ID:

json
1{
2 "buyer": {
3 "name": "Bundesministerium für Digitales"
4 },
5 "countrySpecific": {
6 "countryCode": "DE",
7 "leitwegId": "991-12345-67"
8 }
9}

The Leitweg-ID consists of three parts: coarse addressing (3 digits), fine addressing (up to 8 digits), and check digit (2 digits).

BR-DE-15: Missing Bank Details

Error: BR-DE-15: An invoice must contain payment information.

Solution: Payment information is mandatory in Germany:

json
1{
2 "seller": {
3 "bankAccount": {
4 "iban": "DE89370400440532013000",
5 "bic": "COBADEFFXXX"
6 }
7 },
8 "paymentTerms": {
9 "dueDays": 30,
10 "description": "Payable within 30 days to the account shown"
11 }
12}

BR-CO-10: Totals Don't Match

Error: BR-CO-10: The sum of line item amounts does not equal the total amount.

Solution: Make sure your calculations are exact. Use decimal types instead of float:

typescript
1// ❌ Wrong - Float imprecision
2const total = 0.1 + 0.2; // = 0.30000000000000004
3 
4// ✅ Correct - Integer cent calculation
5const totalCents = 10 + 20; // = 30
6const total = totalCents / 100; // = 0.30

A complete list of all error codes can be found in the documentation.


FAQ -- Frequently Asked Questions

Do I need to be able to receive e-invoices even if I don't have to send them yet?

Yes. Starting January 1, 2025, every B2B company in Germany must be able to receive e-invoices -- regardless of revenue. The sending obligation takes effect later (2027/2028), but you must be able to receive immediately.

Are PDF invoices banned starting in 2025?

Not exactly. PDF invoices without structured data are no longer considered e-invoices. However, you can still accept them as "other invoices" until the transition period ends (2027/2028), if your business partner cannot send an e-invoice. The ZUGFeRD format contains a PDF but counts as an e-invoice because the XML data is embedded.

What happens if I ignore the mandate?

Legally, violations of the invoicing obligations under Section 14 UStG can result in fines. More practically relevant: Without e-invoicing capability, you cannot issue invoices to public contracting authorities and may lose business partners who only accept e-invoices.

Do I have to implement e-invoicing myself or can I use an API?

You can do both. Self-implementation requires processing the 247-page KoSIT specification, Schematron validation, and regular updates when formats change. With an API like Invoice-api.xhub, you save this complexity and can go live in just a few hours. No API experience? Use our no-code integrations with Zapier, Make, or n8n. For a step-by-step guide, see our n8n e-invoice integration with ready-made workflow templates.

How do I archive e-invoices in compliance with GoBD?

E-invoices must be stored immutably for 10 years. This means:

  • Store the original XML (not just the processed data)
  • Document the timestamp of receipt
  • Ensure tamper protection (e.g., through hash values)
  • Guarantee readability throughout the entire retention period

Next Steps

You now have a comprehensive overview of the e-invoicing mandate 2025. Here are your next steps:

  1. Test the Playground: Experiment with the API in the Playground -- no sign-up, no cost.

  2. Get an API key: Register for free and get your API key for the sandbox environment.

  3. Start integrating: Use our quickstart guide or the SDKs for Node.js, Python, or the REST API directly.

  4. Read the documentation: Find deeper technical details in the Validator documentation and Creator documentation.


Conclusion

The e-invoicing mandate 2025 is not optional -- it's reality. But with the right tools, you don't have to spend weeks on implementation.

Invoice-api.xhub takes the complexity off your hands:

  • All formats (XRechnung, ZUGFeRD, Peppol) from a single API
  • Automatic validation against current KoSIT schemas
  • Simple JSON API instead of XML handling
  • SDKs for all popular languages

Questions? Contact us.

Get started now -- the first 100 e-invoices per month are free.

Share article
Patrick Jerominek

Written by

Patrick Jerominek

Cofounder

Builds APIs that developers love. Writes about e-invoicing, TypeScript, and everything in between.

Ready to master e-invoicing?

Get started in under 5 minutes with Invoice-api.xhub. No credit card required.