Papierrechnung schwebt auf ein Tablet mit derselben Rechnung als Datensatz
Recht & Standards

E-Rechnung aus der eigenen Webapp: XRechnung und ZUGFeRD mit PHP

Carola Schulte
3. August 2026
12 min

Eine Rechnung als PDF per E-Mail ist seit dem 1. Januar 2025 keine elektronische Rechnung mehr. Jedenfalls nicht im Sinne des Umsatzsteuergesetzes. Seit diesem Datum gilt in Deutschland für Geschäfte zwischen Unternehmen ein neuer Begriff: Eine E-Rechnung ist ein strukturierter Datensatz nach einer europäischen Norm, den eine Software ohne Umweg über ein menschliches Auge verarbeiten kann. Das PDF, das jeder kennt, heißt jetzt „sonstige Rechnung" und läuft aus.

Für die meisten kleinen und mittleren Betriebe ist das bislang im Hintergrund geblieben, weil es Übergangsfristen gibt und weil die Buchhaltungssoftware das Thema für sie erledigt. Für Betriebe, die ihre Rechnungen aus einer eigenen Anwendung heraus erzeugen, aus einem Kundenportal, einem Auftragssystem, einer Zeiterfassung, wird es dagegen konkret. Dieser Beitrag erklärt, was sich ändert, was die beiden Formate unterscheidet, und wie die Erzeugung in einer PHP-Anwendung aussieht.

Ein Hinweis vorab: Ich bin Entwicklerin, keine Steuerberaterin. Fristen und Schwellenwerte gebe ich nach bestem Wissen wieder, aber die verbindliche Auskunft dazu gehört in die Steuerkanzlei.

TL;DR - Die Kurzfassung

  • Seit 01.01.2025 muss jedes Unternehmen in Deutschland E-Rechnungen empfangen können. Ein E-Mail-Postfach reicht dafür. Aufbewahrt wird der strukturierte Teil unverändert, seit 2025 acht Jahre.
  • Die Pflicht zum Ausstellen kommt gestaffelt: ab 2027 für Unternehmen mit mehr als 800.000 Euro Vorjahresumsatz, ab 2028 für alle. Kleinunternehmer nach § 19 UStG sind dauerhaft ausgenommen. Bis dahin ist PDF mit Zustimmung des Empfängers noch erlaubt.
  • Zwei Formate, eine Norm: XRechnung ist reines XML, ZUGFeRD ist ein PDF mit eingebettetem XML. Beide erfüllen die EN 16931.
  • Die eigentliche Arbeit liegt nicht in der Bibliothek, sondern in den Daten: Leitweg-ID, Steuernummern, Positionsdaten und Steuersätze müssen sauber vorliegen.
  • Vor dem Versand validieren, mit dem passenden Prüfwerkzeug je Format. Ein Validator sagt Ihnen, ob eine Rechnung formal der Spezifikation entspricht, bevor das System des Kunden sie zurückweist.

Was gilt seit wann

Der Zeitplan kommt aus dem Wachstumschancengesetz und betrifft Leistungen zwischen inländischen Unternehmen. Privatkunden sind nicht betroffen, Kleinbetragsrechnungen bis 250 Euro und Fahrausweise ebenfalls nicht.

AbWas gilt
01.01.2025Jedes Unternehmen muss E-Rechnungen empfangen und archivieren können. Es gibt keinen Anspruch mehr darauf, eine Papier- oder PDF-Rechnung zu bekommen.
bis 31.12.2026Übergang: Papier ist weiter erlaubt, PDF nur mit Zustimmung des Empfängers.
01.01.2027Ausstellungspflicht für Unternehmen mit mehr als 800.000 Euro Umsatz im Vorjahr.
01.01.2028Ausstellungspflicht für alle.

Die wichtigste Fußnote zu dieser Tabelle für kleine Betriebe: Kleinunternehmer nach § 19 UStG sind von der Ausstellungspflicht dauerhaft befreit (Jahressteuergesetz 2024). Empfangen können müssen sie trotzdem. Wer als Ein-Personen-Betrieb die Staffelung liest und glaubt, 2028 umstellen zu müssen, sollte das mit der Steuerkanzlei klären, bevor er etwas baut.

Für Lieferanten öffentlicher Auftraggeber gilt das alles schon länger: Rechnungen an Bundesbehörden müssen seit November 2020 als XRechnung eingereicht werden, Bund und Länder haben dafür jeweils eigene Vorgaben. Wer also für eine Kommune oder ein Landesamt arbeitet, kennt das Thema bereits.

Die Empfangspflicht ist der Teil, der oft unterschätzt wird. Für den Empfang selbst genügt laut Finanzministerium ein E-Mail-Postfach. Aber daneben steht die Aufbewahrungspflicht, und die hat es in sich: Der strukturierte Teil der Rechnung muss in seiner ursprünglichen Form unverändert aufbewahrt werden, seit 2025 acht Jahre lang (das Bürokratieentlastungsgesetz IV hat die Frist für Buchungsbelege von zehn auf acht Jahre verkürzt; für Handelsbücher und Jahresabschlüsse bleibt es bei zehn). Eine XRechnung ist eine XML-Datei, und die öffnet sich im Browser als Zeichenwüste. Sie brauchen also mindestens einen Betrachter, um den Inhalt zu prüfen, und Sie dürfen das XML nicht in ein PDF umwandeln und das XML wegwerfen, weil das Original der strukturierte Datensatz ist.

XRechnung und ZUGFeRD: Was der Unterschied ist

Beide Formate setzen dieselbe europäische Norm um, die EN 16931. Die legt fest, welche Angaben eine elektronische Rechnung enthält und wie sie heißen. Der Unterschied liegt in der Verpackung.

XRechnung ist der deutsche Standard für die öffentliche Verwaltung. Eine XRechnung ist eine reine XML-Datei, in einer von zwei erlaubten Syntaxen (UBL oder CII). Es gibt kein Bild, keine Gestaltung, keine Firmenfarbe. Der Empfänger liest sie mit Software. Für Behörden ist sie Pflicht, für Geschäfte zwischen Unternehmen eine von mehreren Möglichkeiten.

ZUGFeRD ist ein hybrides Format: ein PDF, in das die XML-Rechnung als Anhang eingebettet ist. Der Mensch sieht das gewohnte Rechnungsdokument, die Software liest das XML aus dem Anhang. Das PDF muss dafür dem Archivierungsformat PDF/A-3 entsprechen. Zulässig ist ZUGFeRD ab Version 2.0.1, aktuell ist 2.5.2. ZUGFeRD kennt mehrere Profile, die sich im Umfang der strukturierten Angaben unterscheiden. MINIMUM und BASIC WL enthalten keine Positionszeilen und gelten nur als Buchungshilfe, nicht als E-Rechnung. BASIC mit Positionen erfüllt die Pflicht, bildet aber weniger Felder strukturiert ab. EN 16931 und XRECHNUNG bilden die Norm vollständig ab und sind für den Geschäftsverkehr die robustere Wahl, weil die Buchhaltung des Empfängers dann alles bekommt, was sie verarbeiten kann.

Ein Grundsatz, der aus dem hybriden Format folgt: Bei Abweichungen zwischen PDF-Bild und XML ist das XML maßgeblich. Das PDF ist die Ansicht, die Rechnung ist der Datensatz. Nicht das, was der Mensch sieht, ist die Rechnung, sondern das, was die Maschine liest. Das hat eine praktische Konsequenz, auf die ich unten beim Code zurückkomme.

Welches Format nehmen? Meine Empfehlung für Betriebe, die an andere Unternehmen liefern: ZUGFeRD im Profil EN 16931. Der Kunde bekommt weiterhin ein PDF, das er ausdrucken und ansehen kann, und seine Buchhaltung bekommt die Daten. Wer auch an Behörden liefert, erzeugt zusätzlich XRechnung. Mit einer guten Bibliothek sind das dieselben Daten in zwei Ausgaben.

Die eigentliche Arbeit: Die Daten

Hier liegt der Aufwand, nicht in der Technik. Eine E-Rechnung ist streng. Was auf einer gedruckten Rechnung als Freitext durchgeht, muss hier in festen Feldern mit festen Codes stehen. Ein paar Beispiele aus Projekten, in denen die Umstellung länger dauerte als geplant:

  • Steuernummern. Umsatzsteuer-ID oder Steuernummer des Ausstellers sind Pflicht, im richtigen Format. In vielen Datenbanken steht das in einem Freitextfeld namens „Bemerkung".
  • Leitweg-ID. Bei Rechnungen an Behörden identifiziert sie den Empfänger. Ohne sie wird die Rechnung abgelehnt. Sie muss beim Kunden gespeichert werden, nicht auf jeder Rechnung neu abgetippt.
  • Steuersätze pro Position. Jede Rechnungsposition trägt ihren Steuersatz und eine Kategorie (Regelsatz, ermäßigt, steuerfrei, Reverse Charge). Ein Gesamtbetrag mit „zzgl. 19 % MwSt." reicht nicht.
  • Mengeneinheiten als Code. „Stück" ist H87, „Stunde" ist HUR, „Pauschale" ist LS. Die Codes kommen aus einer UN-Liste. Wer Freitext-Einheiten in der Datenbank hat, braucht eine Zuordnungstabelle.
  • Zahlungsbedingungen als Daten. Fälligkeitsdatum, Skonto und Bankverbindung als Felder, nicht als Satz im Fußtext.
  • Rundung. Die Norm rechnet Summen nach festen Regeln. Wenn Ihre Anwendung Positionen anders rundet als die Norm, stimmt die Summe im XML nicht mit der Summe der Positionen überein, und der Validator lehnt ab.

Der erste Schritt in jedem Projekt ist deshalb kein Code, sondern ein Abgleich: Welche Felder verlangt die Norm, wo stehen sie heute in der Anwendung, und wo stehen sie gar nicht. Erfahrungsgemäß fehlen drei bis fünf Felder, und die müssen ins Datenmodell und in die Erfassungsmasken, bevor die erste Rechnung erzeugt werden kann.

Die Umsetzung in PHP

Für die Erzeugung gibt es in der PHP-Welt eine freie und verbreitete Bibliothek: horstoeko/zugferd. Sie erzeugt ZUGFeRD in allen Profilen und XRechnung in der CII-Syntax (UBL beherrscht sie nicht), kann bestehende E-Rechnungen einlesen und läuft ohne Framework. Das Projekt selbst sagt inzwischen, dass die Codebasis in die Jahre gekommen ist und ein Nachfolger entsteht; die bestehende Version wird weiter gepflegt. Für den Einstieg ist sie trotzdem die richtige Wahl, weil sie stabil und dokumentiert ist. Der Aufbau einer Rechnung ist ein Builder, der die Struktur der Norm abbildet. Ein gekürztes Beispiel:

use horstoeko\zugferd\ZugferdDocumentBuilder;
use horstoeko\zugferd\ZugferdProfiles;
use horstoeko\zugferd\ZugferdDocumentPdfBuilder;

$doc = ZugferdDocumentBuilder::CreateNew(ZugferdProfiles::PROFILE_EN16931);

$doc->setDocumentInformation('RE-2026-0815', '380', new \DateTime('2026-08-03'), 'EUR')
    ->setDocumentSeller('Musterbetrieb GmbH', 'DE123456789')
    ->addDocumentSellerTaxRegistration('VA', 'DE123456789')
    ->setDocumentSellerAddress('Werkstraße 1', '', '', '21335', 'Lüneburg', 'DE')
    ->setDocumentBuyer('Kunde AG', 'K-4711')
    ->setDocumentBuyerAddress('Hafenweg 9', '', '', '20457', 'Hamburg', 'DE')
    ->setDocumentPaymentTerm('Zahlbar bis 17.08.2026 ohne Abzug', new \DateTime('2026-08-17'))
    ->addDocumentPaymentMeanToCreditTransfer('DE02120300000000202051', 'Musterbetrieb GmbH');

$doc->addNewPosition('1')
    ->setDocumentPositionProductDetails('Entwicklung Kundenportal, Sprint 7')
    ->setDocumentPositionNetPrice(1200.00)
    ->setDocumentPositionQuantity(5, 'DAY')        // Tage
    ->addDocumentPositionTax('S', 'VAT', 19)       // Regelsatz
    ->setDocumentPositionLineSummation(6000.00);

$doc->addDocumentTax('S', 'VAT', 6000.00, 1140.00, 19)
    ->setDocumentSummation(7140.00, 7140.00, 6000.00, 0, 0, 6000.00, 1140.00);

// Variante A: XRechnung (reines XML)
$doc->writeFile('/pfad/RE-2026-0815.xml');

// Variante B: ZUGFeRD (bestehendes PDF/A-3 + eingebettetes XML)
$pdf = new ZugferdDocumentPdfBuilder($doc, '/pfad/RE-2026-0815-layout.pdf');
$pdf->generateDocument()->saveDocument('/pfad/RE-2026-0815.pdf');

Die Codes in den Aufrufen (380 für Rechnung, S für Regelsatz, VA für die USt-ID, DAY für Tage) sind die Codes der Norm. Die Bibliothek prüft sie nicht auf fachliche Richtigkeit, sie schreibt sie ins XML. Ob die Rechnung formal stimmt, sagt der Validator. Ob fünf Tage wirklich geleistet wurden und 19 Prozent der richtige Satz sind, weiß weder die Bibliothek noch der Validator, das bleibt bei Ihnen und der Steuerkanzlei.

Und hier die angekündigte Konsequenz aus „das XML ist maßgeblich": In Variante B nimmt die Bibliothek ein fertiges Layout-PDF entgegen, das typischerweise ein anderer Codepfad erzeugt hat, etwa mit mPDF. Wenn dieser Codepfad Beträge anders rundet oder eine Position anders summiert als der Builder, zeigt das PDF eine andere Summe als das XML, und der Kunde bucht das XML. Deshalb speisen sich bei mir beide Ausgaben aus derselben, vorher fertig berechneten Datenstruktur, und ein Abgleich der Endsumme zwischen PDF-Daten und XML gehört in den Test.

Für die ZUGFeRD-Variante braucht die Anwendung zusätzlich ein PDF im Format PDF/A-3. Wer seine Rechnungs-PDFs heute mit einer Bibliothek wie mPDF oder TCPDF erzeugt, findet dort Unterstützung für PDF/A, bei aktuellen TCPDF-Versionen sogar ausdrücklich für hybride ZUGFeRD-Dokumente. PDF/A ist aber mehr als ein Schalter: Schriften müssen eingebettet sein, Metadaten und Farbprofil müssen stimmen, Anhänge müssen korrekt deklariert sein, und es dürfen keine externen Verweise im Dokument stecken. Ein PDF/A-Prüfwerkzeug wie veraPDF gehört deshalb zum Test. Wie die PDF-Erzeugung grundsätzlich aufgebaut wird, steht im Beitrag über PDF-Generierung in PHP.

Validieren, bevor der Kunde es tut, mit dem richtigen Werkzeug

Der zweite feste Baustein ist die automatische Prüfung vor dem Versand. Dabei gibt es eine Falle, die zu genau der Sorte Fehlalarm führt, vor der dieser Beitrag schützen will: Welcher Validator, hängt vom Format ab. Für XRechnung ist der KoSIT-Validator das Werkzeug, ein freies Java-Programm der Koordinierungsstelle für IT-Standards mit einer Prüfkonfiguration für XRechnung. XRechnung ist aber eine nationale Verschärfung der Norm mit zusätzlichen Geschäftsregeln, etwa ist die Käuferreferenz dort Pflicht, in EN 16931 nicht. Wer eine ZUGFeRD-Rechnung im Profil EN 16931 gegen das XRechnung-Szenario prüft, bekommt Fehler, die keine sind. ZUGFeRD gehört gegen die Regeln von EN 16931 und des ZUGFeRD-Profils validiert, etwa mit dem freien Mustangproject, das auch die PDF/A-Einbettung mitprüft. Beide liefern einen Bericht, in dem jede verletzte Regel mit Nummer und Erklärung steht. Bei mir läuft die Prüfung als Kommandozeilenaufruf direkt aus der Anwendung heraus, bevor eine Rechnung als „versandfertig" markiert wird:

// XRechnung: KoSIT-Validator mit XRechnung-Szenario
$cmd = sprintf('java -jar %s -s %s %s 2>&1',
    escapeshellarg('/opt/validator/validationtool.jar'),
    escapeshellarg('/opt/validator/scenarios-xrechnung.xml'),
    escapeshellarg($xmlPath));
// ZUGFeRD: stattdessen z.B. java -jar Mustang-CLI.jar --action validate --source rechnung.pdf
exec($cmd, $output, $rc);
if ($rc !== 0) {
    // Bericht speichern, Rechnung nicht freigeben, Alarm an die Buchhaltung
}

Das kostet eine Sekunde pro Rechnung und erspart die Rückfrage des Kunden zwei Wochen später, dass seine Software die Rechnung nicht annimmt. Denn das ist der praktische Unterschied zur PDF-Welt: Eine fehlerhafte PDF-Rechnung liest ein Mensch trotzdem. Eine fehlerhafte E-Rechnung wird vom System des Kunden möglicherweise automatisiert zurückgewiesen. Und der Grund, warum seine Buchhaltung darauf besteht: Ohne ordnungsgemäße E-Rechnung ist, sobald die Pflicht greift, der Vorsteuerabzug des Empfängers gefährdet. Deshalb wird nicht gezahlt, bis eine korrekte Rechnung da ist. Ein Validator prüft dabei die Regeln der Spezifikation; ein Empfänger kann darüber hinaus eigene Anforderungen haben, etwa eine Bestellnummer als Pflichtfeld.

Die andere Richtung: Empfangen und verarbeiten

Dieselbe Bibliothek kann E-Rechnungen auch lesen. Das eröffnet für Betriebe mit vielen Eingangsrechnungen eine Möglichkeit, die vorher teure Software brauchte: Die Rechnung des Lieferanten kommt als ZUGFeRD-PDF ins Postfach, die Anwendung zieht das XML heraus, legt die Positionen an, ordnet sie der Bestellung zu und schlägt eine Kontierung vor. Kein Abtippen, keine Texterkennung, keine Übertragungsfehler.

use horstoeko\zugferd\ZugferdDocumentPdfReader;

$doc = ZugferdDocumentPdfReader::readAndGuessFromFile('/eingang/lieferant-4711.pdf');
$doc->getDocumentInformation($invoiceNo, $type, $date, $currency);
$doc->getDocumentSummation($grandTotal, $duePayable, $lineTotal, ...);
// Positionen durchlaufen, Bestellung zuordnen, in die Buchhaltung übergeben

Für die Archivierung gilt: Das Original ist die Datei, wie sie ankam. Sie wird unverändert, in ursprünglicher Form und GoBD-konform abgelegt, acht Jahre. Wie ein solches Archiv aufgebaut ist, steht im Beitrag über Audit-Trails und Revisionssicherheit.

Die häufigsten Fehler

  • Das XML wegwerfen. Eine ZUGFeRD-Rechnung in ein normales PDF „umwandeln" und ablegen. Das Original ist das strukturierte Dokument.
  • Freitext, wo Codes hingehören. Einheiten, Steuerkategorien und Dokumenttypen aus der Norm, nicht aus dem Gewohnheitswortschatz.
  • Rundungsdifferenzen. Die Summenbildung der Norm nachrechnen, nicht die der eigenen Anwendung übernehmen.
  • Zu kleines ZUGFeRD-Profil. MINIMUM und BASIC WL sind keine E-Rechnung. BASIC erfüllt die Pflicht, EN 16931 ist die robustere Wahl.
  • Nicht oder falsch validieren. Jede Rechnung vor dem Versand durch den Validator, automatisch, und zwar den für das Format: KoSIT für XRechnung, Mustangproject für ZUGFeRD.
  • PDF und XML aus getrennten Codepfaden. Wenn beide unterschiedlich rechnen, gilt das XML, und das PDF lügt.
  • Zu spät anfangen. Die Datenbereinigung dauert länger als die Programmierung. Wer 2027 ausstellen muss, sollte 2026 die Daten in Ordnung bringen.

Checkliste: Ist Ihre Anwendung bereit?

  • Können Sie heute eine XRechnung empfangen, lesen und acht Jahre unverändert aufbewahren?
  • Wissen Sie, ab wann Ihre Ausstellungspflicht gilt (Umsatzgrenze), oder ob Sie als Kleinunternehmer ausgenommen sind?
  • Stehen USt-ID, Leitweg-ID und Bankverbindung als Felder in der Datenbank, nicht im Freitext?
  • Trägt jede Rechnungsposition Steuersatz, Steuerkategorie und eine Einheit aus der Codeliste?
  • Erzeugt Ihre PDF-Ausgabe PDF/A-3 mit eingebetteten Schriften?
  • Läuft vor dem Versand eine automatische Validierung mit dem passenden Werkzeug für Ihr Format?
  • Kommen PDF-Layout und XML aus derselben Datenbasis, und wird die Endsumme abgeglichen?
  • Ist mit der Steuerkanzlei abgestimmt, welches Format Ihre Kunden erwarten?

Fazit: Ein Datenprojekt mit einem kleinen Technikanteil

Die E-Rechnung ist keine Formatfrage. Die Bibliothek ist frei, der Validator ist frei, und der Code für eine Rechnung passt auf eine Bildschirmseite. Die Arbeit steckt darin, die Rechnungsdaten so sauber zu haben, dass eine Maschine sie ohne Rückfrage verarbeiten kann. Wer das aus der eigenen Anwendung heraus löst, statt Rechnungen in ein fremdes Portal zu tippen, hat am Ende nicht nur die Pflicht erfüllt, sondern einen Prozess, der ohne Abtippen und ohne Medienbruch läuft, in beide Richtungen.


Ihre Anwendung erzeugt Rechnungen, und 2027 rückt näher? Schreiben Sie mir kurz, womit Sie heute fakturieren und an wen. Ich sehe mir Ihre Rechnungsdaten an, sage Ihnen, welche Felder fehlen, und wie die Erzeugung von XRechnung oder ZUGFeRD in Ihre Anwendung passt.

Verwandt auf eigene-anwendung.de: E-Rechnung für kleine Betriebe: Fristen, Formate, Praxis, die Kundensicht: Fristen, Ausnahmen und was ein kleiner Betrieb jetzt tun muss.

Weitere interessante Artikel

PDF-Generierung in PHP: Rechnungen, Reports, Verträge

PDF-Dokumente mit PHP erstellen: TCPDF, FPDF, Dompdf, wkhtmltopdf im Vergleich.

CRM & ERP Integration: Salesforce, SAP, DATEV anbinden

CRM und ERP anbinden: Salesforce, SAP und DATEV mit der eigenen Webapp verbinden, Datenflüsse sauber planen und Fehlerquellen vermeiden.

Audit-Trails & Revisionssicherheit: Wer hat wann was geändert?

Audit-Trails in PHP implementieren: Change-Tracking, Event-Sourcing-Patterns, GoBD-konforme Logs.