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.
Legal Background
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
| Date | Requirement | Affected |
|---|---|---|
| 01.01.2025 | Ability to receive e-invoices | All B2B companies |
| 01.01.2027 | Sending e-invoices | Companies with > 800,000 EUR prior-year revenue |
| 01.01.2028 | Sending e-invoices | All 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:
- Receiving: You must be able to accept e-invoices in XRechnung or ZUGFeRD format
- Processing: The structured data must be correctly parsed and imported into your system
- 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
1Invoice recipient?2├─ Public administration (federal/state/municipal)3│ └─ → XRechnung (mandatory!)4├─ International business partner (EU)5│ └─ → Peppol BIS Billing6└─ German B2B companies7 ├─ Recipient wants PDF view?8 │ └─ → ZUGFeRD9 └─ Only structured data needed?10 └─ → XRechnungTechnical Differences
| Feature | XRechnung | ZUGFeRD 2.x | Peppol BIS |
|---|---|---|---|
| Base standard | EN 16931 | EN 16931 | EN 16931 |
| XML syntax | UBL 2.1 or CII | CII (Cross Industry Invoice) | UBL 2.1 |
| PDF included | No | Yes (PDF/A-3) | No |
| Validation | KoSIT validation tool | KoSIT validation tool | Peppol Validation |
| Use case | B2G, B2B | B2B with PDF needs | International B2B |
| File size | Small (~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:
1// TypeScript/Node.js - Parse XRechnung2async 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: xmlContent10 });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}1# Python - Parse XRechnung2import requests3 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_content12 )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.
1# cURL - Validate e-invoice2curl -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.xml6 7# Response8{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.
1// TypeScript/Node.js - Create e-invoice2const 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 discriminator37 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.0050 },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.8161 }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);1# Python - Create e-invoice2import requests3import os4 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.0045 }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:
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:
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:
1// ❌ Wrong - Float imprecision2const total = 0.1 + 0.2; // = 0.300000000000000043 4// ✅ Correct - Integer cent calculation5const totalCents = 10 + 20; // = 306const total = totalCents / 100; // = 0.30A 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:
-
Test the Playground: Experiment with the API in the Playground -- no sign-up, no cost.
-
Get an API key: Register for free and get your API key for the sandbox environment.
-
Start integrating: Use our quickstart guide or the SDKs for Node.js, Python, or the REST API directly.
-
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.

