Eine ZUGFeRD-Rechnung ist ein PDF/A-3b mit eingebettetem CII-XML nach EN 16931. Drei Dinge müssen stimmen: die PDF/A-3b-Konformität, die eingebettete Datei mit normiertem Namen (aktuell factur-x.xml) samt AFRelationship und das XMP-Extension-Schema mit dem Profil. Per API holst du die fertige Datei mit einem Call: GET /invoices/{id}/pdf.

Ein ZUGFeRD-Dokument sieht aus wie ein PDF — technisch ist es ein PDF/A-3b mit einer eingebetteten XML-Datei. Genau diese Einbettung ist der Teil, an dem selbstgebaute Lösungen scheitern: Die Bytes müssen an der richtigen Stelle stehen, richtig benannt und richtig zugeordnet sein, sonst lehnt der Empfänger die Datei ab. Dieser Beitrag zeigt, wie das XML ins PDF kommt — und wie du dir den Embedder sparst.

Was „ZUGFeRD-PDF/A-3“ konkret bedeutet

ZUGFeRD (bzw. Factur-X) ist ein hybrides Format: ein für Menschen lesbares PDF plus ein für Maschinen lesbares CII-XML nach EN 16931, beides in einer Datei. Damit das funktioniert, sind drei Dinge gleichzeitig wahr:

  1. Die Hülle ist ein PDF/A-3b. PDF/A ist das Archivprofil von PDF (eingebettete Schriften, definierter Farbraum, keine externen Abhängigkeiten). Nur die Version 3 erlaubt beliebige eingebettete Dateien — die Vorgänger PDF/A-1 und A-2 nicht. Die Stufe b (basic) verlangt visuelle Reproduzierbarkeit, nicht die volle Tag-Struktur von Stufe a.
  2. Das CII-XML liegt als eingebettete Datei drin. Nicht als Anhang „irgendwo“, sondern als EmbeddedFile mit einer Dokument-Zuordnung (AFRelationship, meist Data) auf Dokumentebene, damit ein Reader die Rechnung als das führende Nutzdatum erkennt.
  3. Der Metadaten-Stream deklariert das Format. Ein XMP-Extension-Schema im PDF-Metadaten-Block nennt DocumentType (INVOICE), DocumentFileName, Version und ConformanceLevel (also das ZUGFeRD-Profil).

Der Dateiname ist normiert — nicht frei wählbar

Die eingebettete XML-Datei muss exakt heißen, wie es der jeweilige Standard vorschreibt. Das ist ein häufiger, stiller Fehler:

StandardstandDateiname der eingebetteten XML
ZUGFeRD 1.0ZUGFeRD-invoice.xml
ZUGFeRD 2.0zugferd-invoice.xml
ZUGFeRD 2.1+ / Factur-Xfactur-x.xml

Weicht der Name ab, findet der Empfänger das strukturierte Original nicht — das PDF gilt dann als reines Bild-PDF und erfüllt die E-Rechnungspflicht nicht.

Warum der sichtbare Teil und das XML deckungsgleich sein müssen

Unter der E-Rechnungspflicht ist bei einem hybriden Beleg das XML der führende, maßgebliche Teil — das PDF ist die visuelle Kopie. Weichen Sichtbeleg und XML voneinander ab (andere Summe, anderes Datum), ist das ein echtes Problem, kein Schönheitsfehler. Deshalb sollten beide aus derselben Datenquelle entstehen und nicht getrennt gerendert werden.

Der pragmatische Weg: per API statt Embedder selbst bauen

Du kannst PDF/A-3b-Konformität, XMP-Extension-Schema, AFRelationship und die Namenskonvention mit einer PDF-Bibliothek selbst zusammensetzen — und jede Format-Aktualisierung selbst nachziehen. Oder du delegierst die Erzeugung an eine E-Rechnung API. Der Flow ist derselbe wie bei ZUGFeRD/Factur-X per API:

1) Rechnung anlegen — Kunde und Positionen; der Server rechnet Summen und USt.

HTTP
POST /invoices
Authorization: Bearer sk_test_…
Idempotency-Key: 6f1c2a…
Content-Type: application/json

{
  "currency": "EUR",
  "buyer": {
    "name": "Achsfeld Transporte GmbH",
    "addressLine1": "Gewerbestraße 8",
    "postalCode": "59192",
    "city": "Bergkamen",
    "countryCode": "DE"
  },
  "invoiceTypeCode": "380",
  "deliveryDate": "2026-07-31",
  "lineItems": [
    { "description": "Ladevorgänge Juli 2026", "quantity": "1",
      "unitCode": "C62", "unitPriceNet": "420.00", "taxRatePercent": "19" }
  ]
}

2) Ausstellen — die Nummer wird atomar vergeben; aus einem EN-16931-Datenmodell entsteht das ZUGFeRD-PDF/A-3 mit dem eingebetteten CII-XML — Sichtbeleg und strukturierte Daten stammen aus einer Quelle und sind deshalb deckungsgleich:

HTTP
PATCH /invoices/{id}/finalize
Authorization: Bearer sk_test_…

3) PDF/A-3 abholen — die fertige hybride Datei:

HTTP
GET /invoices/{id}/pdf
Authorization: Bearer sk_test_…
# → application/pdf: PDF/A-3b mit eingebettetem factur-x.xml

Brauchst du für die Vorschau ein Bild vor dem Ausstellen, liefert GET /invoices/{id}/preview.pdf einen nicht persistierten, gewässerzeichneten Entwurf mit demselben Renderer — die Vorschau ist byte-treu zu dem, was das Finalisieren erzeugt.

Checkliste: woran du eine korrekte ZUGFeRD-PDF erkennst

  • PDF/A-3b, nicht A-2 oder ein „normales“ PDF (per Preflight prüfbar).
  • Genau eine eingebettete XML mit dem normkonformen Dateinamen (factur-x.xml bei aktuellen Profilen).
  • XMP-Extension-Schema vorhanden, mit passendem ConformanceLevel (Profil).
  • Das eingebettete XML ist valides CII nach EN 16931 — wie du das prüfst, steht unter KoSIT-Validierung.
  • Sichtbeleg und XML stimmen überein — Summen, Datum, Nummer; siehe oben.

Fortlauf erzeugt ZUGFeRD 2.x im Profil EN 16931 (COMFORT) als PDF/A-3b serverseitig und preflight-geprüft, aus demselben Datenmodell wie die XRechnung — kein zweiter Renderpfad, keine Divergenz zwischen PDF und XML.

Der gezeigte Code ist illustrativ: Die vollständige Dokumentation steht dir in der API-Referenz zur Verfügung — dort steht auch die Base-URL, offen und ohne Anmeldung. Den Test-Key legst du dir selbst im Kontobereich an (Schritt für Schritt im Quickstart).

Selbst ausprobieren? Der Zugang ist kostenlos und ohne Karte — Produkt-Einstieg für Entwickler →

Oder den eigenen Abrechnungsfluss konkret durchsprechen: 30 Min, technisch, mit dem Gründer →

Häufige Fragen

Wie kommt das XML in eine ZUGFeRD-PDF?
Das CII-XML wird als eingebettete Datei (EmbeddedFile) in ein PDF/A-3b gelegt und auf Dokumentebene über AFRelationship zugeordnet. Ein XMP-Extension-Schema im Metadaten-Stream deklariert Profil (ConformanceLevel), Version und Dateinamen. Der Dateiname folgt der Konvention: factur-x.xml ab ZUGFeRD 2.1/Factur-X, zugferd-invoice.xml bei ZUGFeRD 2.0.
Warum PDF/A-3 und nicht ein normales PDF?
Nur PDF/A-3 erlaubt beliebige eingebettete Dateien und garantiert zugleich die Langzeit-Reproduzierbarkeit (eingebettete Schriften, definierter Farbraum). PDF/A-2 lässt eingebettete Fremddateien nicht zu. ZUGFeRD verlangt konkret die Konformitätsstufe PDF/A-3b (visuell reproduzierbar), nicht A-3a.
Kann ich ZUGFeRD-PDF/A-3 mit einer Standard-PDF-Bibliothek erzeugen?
Technisch ja, aber du trägst dann die Fehlerquellen selbst: PDF/A-3b-Preflight, das korrekte XMP-Extension-Schema, die richtige AFRelationship, der normkonforme Dateiname und vor allem die Konsistenz zwischen sichtbarem PDF und eingebettetem XML. Eine API kapselt diese Regeln; du schickst die Rechnungsdaten und bekommst ein valides PDF/A-3 zurück.