Blog

PDF/A und Factur-X für Entwickler erklärt (ohne Juristensprache)

Was PDF/A-Profile tatsächlich bedeuten, warum Factur-X in der EU bis 2026 verpflichtend wird und wie die kleinste praktikable Pipeline für Compliance aus einem JSON-Renderer aussieht.

Wenn Sie Entwickler sind und gerade hören, dass “die Rechnungen bis zum nächsten Quartal PDF/A-3 mit Factur-X brauchen”, und Ihr einziger Kontext ist, dass Legal diese Wörter gesagt hat, ist dieser Beitrag für Sie.

Kein juristisches Deep Dive. Nur die technische Semantik: was PDF/A wirklich einschränkt, warum Factur-X / ZUGFeRD darauf aufsetzt und wie die kleinste Pipeline aussieht, die in Produktion nicht auseinanderfällt.

PDF/A in zwei Absätzen

PDF/A (“A” für Archival) ist ein Profil von PDF, das die Teile verbietet, die verhindern würden, dass ein Dokument in 50 Jahren identisch rendert. Die Regeln auf hoher Ebene:

  • Alle Fonts müssen eingebettet sein.
  • Keine externen Ressourcen wie Bilder, Fonts oder Color Profiles von URLs.
  • Keine Verschlüsselung, die die Archivierung verhindert.
  • Metadaten müssen vollständig und im XMP-Format vorhanden sein.
  • Farben müssen definiert sein, typischerweise mit ICC-Profilen.
  • JavaScript, Audio, Video und andere flüchtige Inhalte sind verboten.

PDF/A ist nicht ein einziger Standard. Es gibt Profile:

Profil Jahr Wofür es grob steht
PDF/A-1b 2005 Ursprüngliche Baseline, am strengsten
PDF/A-2b 2011 Erlaubt JPEG2000, Transparenz und Ebenen
PDF/A-3b 2012 Erlaubt beliebige Dateianhänge, die Grundlage von Factur-X
PDF/A-4 2020 Basis ISO 32000-2 (PDF 2.0), vereinfachte Konformitätsstufen

Praktischer Schluss: Wenn Ihr Renderer sagt, er unterstützt PDF/A-3b, sollte das ein einzelnes Konfigurationsflag sein ({ profile: "PDF/A-3b" } oder äquivalent). Wenn Sie nach dem Rendern ein zweites Tool wie Ghostscript, qpdf oder Acrobat ausführen müssen, um die Datei zu konvertieren, besitzen Sie jetzt eine mehrstufige Compliance-Pipeline.

Warum gerade PDF/A-3 wichtig ist: Es ist der Träger für E-Rechnungen

PDF/A-3 hat eine Fähigkeit hinzugefügt, die sich als weltverändernd erwiesen hat: beliebige Dateianhänge im PDF.

Das klingt erst einmal gefährlich, ist aber genau das, was E-Rechnungen brauchen:

  • Das sichtbare PDF zeigt die Rechnung für Menschen.
  • Der angehängte XML-Teil enthält dieselbe Rechnung strukturiert für Maschinen.

Beides liegt in einer Datei, beides repräsentiert dieselbe Rechnung, und die PDF/A-3-Hülle stellt sicher, dass die Datei auch in Jahrzehnten noch parsebar bleibt.

Die Namen, die Sie hören werden:

  • Factur-X (Frankreich): XML-Profil auf Basis von UN/CEFACT Cross Industry Invoice
  • ZUGFeRD (Deutschland): inhaltlich identisch mit Factur-X; die beiden Standards wurden 2018 technisch zusammengeführt
  • EN 16931: die europäische Norm, der beide Implementierungen entsprechen

Für die meisten Workflows sind “Factur-X” und “ZUGFeRD” austauschbare Begriffe. Sie teilen ein Schema, teilen den Einbettungsmechanismus, und ein einzelnes PDF, das mit einem konform ist, ist im Allgemeinen auch mit dem anderen konform.

Was ist wo und wann verpflichtend?

Stand 2026:

Land Pflicht Format
Frankreich Ausstellung für Großunternehmen ab 2026-09 verpflichtend; KMU ab 2027-09 Factur-X über Chorus Pro
Deutschland B2B-Pflicht ab 2025-01-01 für Rechnungsempfang; ab 2027 auch für Ausstellung EN 16931 (Factur-X / ZUGFeRD / XRechnung)
Italien Bereits verpflichtend über SDI FatturaPA (nicht PDF/A-basiert, aber EN-16931-nah)
Polen KSeF verpflichtend ab 2026 FA(2) XML
EU allgemein ViDA schiebt strukturierte E-Rechnungen EU-weit nach vorn EN-16931-Familie

Das Muster: Jeder EU-Mitgliedstaat implementiert eine Variante EN-16931-konformer E-Rechnung auf einer Timeline zwischen 2024 und 2027. Wenn Ihre Kunden in einem dieser Märkte tätig sind, muss Ihr PDF-Generator angehängtes XML sauber ausgeben, nicht nur “schönes PDF”.

Die kleinste praktikable Pipeline

Vergessen Sie kurz, was die Standarddokumente vorschreiben. Hier ist die Engineering-Sicht:

   ┌─────────────────────┐
   │  Your invoice data  │  (already a JSON object somewhere)
   └─────────┬───────────┘


   ┌─────────────────────┐
   │ Build EN 16931 XML  │  (deterministic mapping; well-tested libs exist)
   └─────────┬───────────┘


   ┌─────────────────────┐
   │ Render PDF/A-3b +   │
   │ attach the XML      │  (single API call to gPdf — or two-step elsewhere)
   └─────────┬───────────┘


   ┌─────────────────────┐
   │  Hand off to        │
   │  Chorus Pro / SDI / │
   │  Peppol / etc       │
   └─────────────────────┘

Die zwei nicht trivialen Schritte:

Schritt 1: XML bauen

Das ist lästig, aber mechanisch. Sie mappen Ihre Rechnungsdaten (Positionen, Steuern, Summen, Parteien) auf EN-16931-XML-Feldnamen. Mehrere Java-/Node-/Python-Bibliotheken erledigen das für Sie; suchen Sie in Ihrer Sprache nach “factur-x library”. Schreiben Sie das nicht von Grund auf neu, außer Sie genießen XML-Schema-Spezifikationen wirklich.

Schritt 2: PDF/A-3 rendern und XML anhängen

Hier zählt die Renderer-Auswahl.

Ohne integrierte Unterstützung: Sie rendern ein normales PDF, danach konvertiert ein Tool zu PDF/A-3 und hängt das XML als eingebettete Datei an. Übliche Stacks sind Ghostscript + qpdf oder ein kostenpflichtiges Tool wie Aspose. Zwei zusätzliche Schritte, zwei zusätzliche Fehlerpunkte, und Sie müssen sicherstellen, dass die Nachbearbeitung das sichtbare Layout nicht verschiebt.

Mit integrierter Unterstützung (gPdfs Ansatz): ein Aufruf.

curl -X POST https://api.gpdf.com/api/v1/e-invoice/render \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  --data '{
    "settings": {
      "profile": "pdfa-3b",
      "e_invoice": {
        "standard": "factur_x",
        "profile": "en16931",
        "document_type": "invoice",
        "xml": {
          "format": "cii",
          "encoding": "utf8",
          "content": "<?xml version=\"1.0\"?><rsm:CrossIndustryInvoice>...</rsm:CrossIndustryInvoice>"
        }
      }
    },
    "pages": [{ "size": "a4", "elements": [/* invoice layout */] }]
  }' \
  --output invoice-with-einvoice.pdf

Das ist die ganze Pipeline. Der Renderer gibt PDF/A-3b aus, hängt Ihr XML als factur-x.xml oder zugferd-invoice.xml an - beide werden von allen Verbrauchern erkannt - und gibt die Bytes zurück.

Häufige Stolperfallen

“PDF/A” und “mit PDF/A-konformen Fonts” sind nicht dasselbe

Eine PDF/A-3-Datei verlangt, dass alle Fonts eingebettet sind und die im Dokument verwendeten Glyphen vollständig abdecken. Wenn Ihre Rechnung einen japanischen Kundennamen enthält und der Renderer auf einen Font zurückfällt, der nicht vollständig einbettbar ist, schlägt die Validierung fehl.

Sichtbare Rechnung und XML müssen übereinstimmen

Wenn im PDF “Gesamt: 1.000,00 EUR” steht, das XML aber 999,99 EUR enthält, haben Sie keine E-Rechnung. Sie haben zwei widersprüchliche Rechnungen in einer Hülle. Das Mapping aus Ihrer Quellrechnung muss deterministisch und testbar sein.

“Profile” in EN 16931

Factur-X hat Profile: MINIMUM, BASIC, EN 16931, EXTENDED. Sie unterscheiden sich darin, wie viel Dateninhalt im XML steckt. Verwenden Sie BASIC, sofern Ihr Kunde nicht ausdrücklich mehr verlangt. Es deckt Steuercodes, Positionen, Parteien und Summen ab, ohne dass Sie jedes optionale Feld modellieren müssen.

Validierung vor Einreichung

Validieren Sie das erzeugte PDF immer gegen einen PDF/A-Validator (veraPDF ist der Open-Source-Standard) und validieren Sie das XML gegen das EN-16931-Schema, bevor Sie an die Steuerbehörde liefern. Fehlgeschlagene Einreichungen an Chorus Pro oder KSeF sind kein Debugging-Ort.

TL;DR

PDF/A ist ein Profil für selbstenthaltene Dokumente. PDF/A-3 erlaubt Dateianhänge. Factur-X / ZUGFeRD ist “ein EN-16931-XML, das in einem PDF/A-3 hängt”. E-Rechnungsmandate in der EU machen diese Kombination zum De-facto-B2B-Rechnungsformat.

Wenn Ihr Renderer PDF/A-3 + Factur-X als ein Konfigurationsflag behandelt, ist die Migration mechanisch. Wenn nicht, bauen Sie eine mehrstufige Betriebs-Pipeline. gPdfs /api/v1/e-invoice/render ist die Ein-Flag-Version: Sie bringen das XML, wir hängen es korrekt an und geben ein validierbares Archiv-PDF zurück. Die API reference enthält das vollständige Schema; einen Sample Render können Sie im Playground testen.