Wer Rechnungen aus einem eigenen System schreibt, einem Shop, einer Branchensoftware oder einer Tabelle, hat die Daten für eine E-Rechnung meist schon. Es fehlt nur die Übersetzung in XRechnung oder ZUGFeRD. Dieser Artikel zeigt, welche Daten Sie brauchen, wie der Ablauf von JSON zur geprüften XRechnung aussieht und wo die typischen Fehler entstehen.
Warum nicht einfach selbst XML schreiben
Eine XRechnung ist XML, also kann man sie theoretisch mit jeder Programmiersprache bauen. In der Praxis scheitert das selten am XML, sondern an den Regeln: Die EN 16931 und die deutschen BR-DE-Regeln prüfen Summen, Steuerkategorien, Codelisten und Pflichtfelder. Eine selbst gebaute Datei, die im eigenen Test funktioniert, fällt oft erst beim Kunden oder bei der Behörde durch.
Deshalb ist die Reihenfolge wichtig: erst das Datenmodell sauber haben, dann erzeugen, dann gegen das offizielle Regelwerk prüfen.
Das Datenmodell
Eine Rechnung nach EN 16931 besteht im Kern aus fünf Blöcken:
- Kopfdaten: Rechnungsnummer (BT-1), Rechnungsdatum (BT-2), Währung (BT-5), Käuferreferenz (BT-10).
- Verkäufer: Name, Anschrift, USt-IdNr. oder Steuernummer, Kontakt mit E-Mail und Telefon.
- Käufer: Name, Anschrift, bei öffentlichen Auftraggebern die Leitweg-ID als Käuferreferenz.
- Positionen: Bezeichnung, Menge, Einheit (Code aus UN/ECE-Empfehlung 20, etwa
HURfür Stunde oderC62für Stück), Einzelpreis, Steuersatz und Steuerkategorie. - Zahlung: Zahlungsart, bei Überweisung die IBAN, Zahlungsbedingungen.
Alles andere, also Positionssummen, Nettosumme, Steuer je Satz, Bruttosumme, Zahlbetrag, wird aus diesen Daten berechnet. Rechnen Sie diese Summen nicht an mehreren Stellen, sondern an genau einer. Doppelt gerechnete Summen sind eine häufige Quelle für Abweichungen.
Ein kompletter Ablauf
Die Muster GmbH berechnet der Kunde AG zehn Stunden Beratung zu je 120,00 € und drei Softwarelizenzen zu je 9,99 €, alles mit 19 % Umsatzsteuer.
Schritt 1: Rechnungsdaten als JSON
Die API von formkorrekt nimmt die Rechnungsdaten als JSON und gibt die fertige Datei zurück. Mit target wählen Sie das Format: xrechnung-ubl, xrechnung-cii oder zugferd-en16931 (PDF/A-3). Die Datei RE-2026-0042.json:
{"target": "xrechnung-ubl", "invoice": {
"number": "RE-2026-0042", "issue_date": "2026-09-25", "delivery_date": "2026-09-24", "currency": "EUR",
"seller": {"name": "Muster GmbH", "vat_id": "DE123456789", "email": "rechnung@muster.example",
"contact": {"name": "Erika Muster", "phone": "+49 30 1234567", "email": "erika.muster@muster.example"},
"address": {"street": "Musterstr. 1", "zip": "10115", "city": "Berlin", "country": "DE"}},
"buyer": {"name": "Kunde AG", "buyer_reference": "K-1001", "email": "einkauf@kunde.example",
"address": {"street": "Kundenweg 2", "zip": "80331", "city": "München", "country": "DE"}},
"lines": [{"name": "Beratung", "quantity": 10, "unit": "HUR", "unit_price": 120.00, "vat_rate": 19.0},
{"name": "Softwarelizenz", "quantity": 3, "unit": "C62", "unit_price": 9.99, "vat_rate": 19.0}],
"payment": {"iban": "DE02120300000000202051", "terms_days": 14}}}
Der Aufruf:
curl -X POST https://formkorrekt.com/v1/invoices/generate \
-H "Authorization: Bearer $KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: RE-2026-0042" \
-d @RE-2026-0042.json -o RE-2026-0042.xml
Beachten Sie: Summen stehen nicht im JSON. Die API berechnet sie aus den Positionen, genau nach den Regeln der Norm.
Schritt 2: Was herauskommt
Aus den Positionen ergibt sich:
| Betrag | |
|---|---|
| Beratung, 10 × 120,00 € | 1.200,00 € |
| Softwarelizenz, 3 × 9,99 € | 29,97 € |
| Nettosumme | 1.229,97 € |
| Umsatzsteuer 19 % | 233,69 € |
| Bruttosumme und Zahlbetrag | 1.463,66 € |
Die Datei RE-2026-0042.xml ist eine XRechnung in UBL-Syntax.
Schritt 3: Prüfung
Jede erzeugte Datei wird vor der Auslieferung gegen XRechnung 3.0.2 geprüft. Besteht sie, trägt die Antwort den Header X-Validation-Status: valid. Besteht sie nicht, bekommen Sie keine Datei, sondern eine Fehlerantwort (HTTP 422) mit jeder verletzten Regel und einem Korrekturhinweis. Dann liegt der Fehler in Ihren Daten, und Sie korrigieren ihn an der Quelle.
Der Header Idempotency-Key sorgt dafür, dass ein wiederholter Aufruf mit demselben Schlüssel (hier: der Rechnungsnummer) innerhalb von 24 Stunden nur einmal abgerechnet wird, etwa nach einem Netzwerkabbruch. Die Datei wird dabei neu erzeugt; gespeichert wird sie nicht. Abgerechnet wird eine Erzeugung als drei Dokumente, weil die Gegenprüfung enthalten ist.
Schritt 4: Versand und Archiv
Die XML-Datei ist die Rechnung. Archivieren Sie genau diese Datei, nicht einen Ausdruck. Für den Versand reicht in der Regel eine E-Mail. Öffentliche Auftraggeber verlangen oft den Upload über ihre Rechnungseingangsplattform.
Typische Stolpersteine
Rundung
Die Norm rechnet so: Positionsbetrag = Menge × Einzelpreis, auf zwei Stellen gerundet. Die Steuer wird je Steuersatz auf die Summe der Positionsbeträge berechnet und erst dann gerundet (Regel BR-CO-17). Viele Kassensysteme runden die Steuer dagegen pro Position.
Ein Beispiel mit drei einzelnen Positionen zu je 9,99 € bei 19 %:
- pro Position gerundet: 3 × 1,90 € = 5,70 €
- auf die Summe gerechnet: 29,97 € × 19 % = 5,6943 €, gerundet 5,69 €
Die offizielle Regel toleriert diesen Cent, aber die Summen müssen untereinander aufgehen, und manche Empfängersysteme prüfen strenger. Lösung: Steuer im eigenen System ebenfalls je Steuersatz auf die Summe berechnen, oder die Summen gar nicht selbst liefern, sondern berechnen lassen.
Steuerkategorien
Ein Steuersatz allein reicht nicht. Jede Position braucht eine Steuerkategorie: S für den Normalsatz, Z für den Nullsatz, E für steuerbefreite Umsätze, AE bei Steuerschuldnerschaft des Leistungsempfängers, K für innergemeinschaftliche Lieferungen. E und AE brauchen zusätzlich einen Befreiungsgrund bzw. Hinweis, AE und K die USt-IdNr. des Käufers. Das Beispiel oben verwendet nur den Normalsatz. Die im Quickstart dokumentierten Felder je Position sind Name, Menge, Einheit, Einzelpreis und Steuersatz; eigene Felder für Steuerkategorie oder Befreiungsgrund sind dort nicht beschrieben. Für Reverse-Charge-, Export- oder steuerfreie Rechnungen prüfen Sie deshalb vorher in der API-Referenz, ob Ihr Fall abgedeckt ist. Welche Kategorie für einen bestimmten Umsatz richtig ist, entscheidet das Steuerrecht, nicht die Software.
Skonto
Skonto wird in der E-Rechnung nicht vom Rechnungsbetrag abgezogen. Die Rechnung weist den vollen Betrag aus, das Skonto steht in den Zahlungsbedingungen. XRechnung sieht dafür eine feste Schreibweise im Feld Zahlungsbedingungen (BT-20) vor, zum Beispiel #SKONTO#TAGE=10#PROZENT=2.00#, damit die Software des Empfängers es automatisch auswerten kann. Freitext wie „2 % Skonto bei Zahlung in 10 Tagen“ ist für Menschen verständlich, für die Maschine aber nicht. Die Zahlungsfelder im JSON sind iban, terms_days und terms_text; terms_text übernimmt Ihren Wortlaut unverändert in die Zahlungsbedingungen, ein eigenes Skonto-Feld gibt es nicht. Wenn Sie Skonto gewähren, klären Sie vorher, wie Sie es abbilden.
Rabatte und Zuschläge
Ein Rabatt auf die ganze Rechnung ist ein Abschlag auf Dokumentebene mit eigenem Steuersatz. Wer ihn nur als Freitext darstellt, bekommt Summenfehler. Ein Feld für Abschläge beschreibt der Quickstart ebenfalls nicht; ein Positionsrabatt lässt sich über einen entsprechend niedrigeren Einzelpreis abbilden. Mehr dazu im Artikel E-Rechnung prüfen: häufige Fehler.
Häufige Fragen
XRechnung oder ZUGFeRD erzeugen? Für Behörden XRechnung, für Unternehmen je nach Empfänger. ZUGFeRD im Profil EN 16931 ist für Empfänger praktisch, die Rechnungen noch ansehen. Details in XRechnung oder ZUGFeRD.
Muss die Käuferreferenz immer gefüllt sein? Bei XRechnung ja. Bei öffentlichen Auftraggebern ist es die Leitweg-ID, sonst eine mit dem Kunden vereinbarte Referenz.
Kann ich eine bestehende fehlerhafte XRechnung reparieren statt neu zu erzeugen?
Eindeutig berechenbare Fehler wie Summen oder Datumsformate ja, über /v1/invoices/repair. Fehlende Inhalte wie eine Käuferreferenz nicht, die müssen Sie selbst liefern.
Weiterlesen: E-Rechnungspflicht 2025 bis 2028 · XRechnung oder ZUGFeRD · E-Rechnung prüfen: häufige Fehler · E-Rechnung in der Kanzlei