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 & CEO

January 20, 2026
15 min reading time

E-Invoicing Mandate 2025: Complete Guide for Developers

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/generate/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 invoice = await response.json();
13 console.log("Invoice number:", invoice.invoiceNumber);
14 console.log("Total amount:", invoice.totalAmount);
15 
16 return invoice;
17}
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/generate/parse",
7 headers={
8 "Authorization": f"Bearer {API_KEY}",
9 "Content-Type": "application/xml"
10 },
11 data=xml_content
12 )
13 
14 invoice = response.json()
15 print(f"Invoice number: {invoice['invoiceNumber']}")
16 print(f"Total amount: {invoice['totalAmount']}")
17 
18 return 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/generate/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 type: "xrechnung-3.0",
10 invoiceNumber: "RE-2025-001",
11 issueDate: "2025-01-15",
12 seller: {
13 name: "Meine Firma GmbH",
14 vatId: "DE123456789",
15 address: {
16 street: "Musterstraße 1",
17 city: "Berlin",
18 postalCode: "10115",
19 country: "DE"
20 }
21 },
22 buyer: {
23 name: "Kunde AG",
24 vatId: "DE987654321",
25 leitweg: "991-12345-67", // For public contracting authorities
26 address: {
27 street: "Kundenweg 42",
28 city: "München",
29 postalCode: "80331",
30 country: "DE"
31 }
32 },
33 items: [
34 {
35 description: "Softwareentwicklung",
36 quantity: 40,
37 unit: "Stunden",
38 unitPrice: 120.00,
39 vatRate: 19
40 },
41 {
42 description: "Server-Hosting (Januar 2025)",
43 quantity: 1,
44 unit: "Monat",
45 unitPrice: 299.00,
46 vatRate: 19
47 }
48 ],
49 paymentTerms: {
50 dueDate: "2025-02-15",
51 iban: "DE89370400440532013000",
52 bic: "COBADEFFXXX"
53 }
54 })
55});
56 
57const invoice = await response.json();
58console.log("E-invoice created:", invoice.id);
59console.log("Download XML:", invoice.downloadUrl);
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 "type": "xrechnung-3.0",
13 "invoiceNumber": "RE-2025-001",
14 "issueDate": "2025-01-15",
15 "seller": {
16 "name": "Meine Firma GmbH",
17 "vatId": "DE123456789",
18 "address": {
19 "street": "Musterstraße 1",
20 "city": "Berlin",
21 "postalCode": "10115",
22 "country": "DE"
23 }
24 },
25 "buyer": {
26 "name": "Kunde AG",
27 "vatId": "DE987654321",
28 "address": {
29 "street": "Kundenweg 42",
30 "city": "München",
31 "postalCode": "80331",
32 "country": "DE"
33 }
34 },
35 "items": [
36 {
37 "description": "Softwareentwicklung",
38 "quantity": 40,
39 "unit": "Stunden",
40 "unitPrice": 120.00,
41 "vatRate": 19
42 }
43 ]
44 }
45)
46 
47invoice = response.json()
48print(f"E-invoice created: {invoice['id']}")

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 "leitweg": "991-12345-67"
5 }
6}

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 "paymentTerms": {
3 "dueDate": "2025-02-15",
4 "iban": "DE89370400440532013000",
5 "bic": "COBADEFFXXX"
6 }
7}

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.

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 & CEO

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.