Blog

PDF/A en Factur-X uitgelegd voor engineers, zonder juridisch jargon

Wat PDF/A-profielen werkelijk betekenen, waarom Factur-X in de EU verplicht wordt, en de kleinste praktische route naar conforme output vanuit een JSON-renderlaag.

Als u engineer bent en net te horen kreeg “de facturen moeten volgend kwartaal PDF/A-3 met Factur-X zijn”, terwijl uw enige context is dat iemand van legal die woorden gebruikte, is deze post voor u.

We halen de toon van standaarden-documentatie eruit en leggen uit wat deze profielen werkelijk beperken, waarom overheden ze verplicht zijn gaan stellen en wat de kleinste praktische route is om een conforme PDF uit een renderlaag voor gestructureerde data te produceren.

PDF/A in twee paragrafen

PDF is een flexibel formaat. Te flexibel: dezelfde PDF-specificatie laat u JavaScript insluiten, linken naar externe resources die over 50 jaar misschien niet meer bestaan, content versleutelen met omkeerbare cryptografie, externe fonts refereren en nog tientallen andere dingen doen die een document niet zelfvoorzienend maken.

PDF/A (“A” voor Archival) is een profiel van PDF dat de onderdelen verbiedt die zouden voorkomen dat het document over 50 jaar identiek rendert. De regels op hoofdlijnen:

  • Alle fonts moeten zijn ingesloten.
  • Geen JavaScript, geen externe links, geen audio/video.
  • Geen encryptie.
  • Alle transparantie moet zijn afgevlakt of ondersteund worden door de profielversie.
  • Kleuren moeten apparaatonafhankelijk zijn (ICC-profiel vereist).
  • Alle content moet in het bestand zitten: geen referenties die van het netwerk afhangen.

Er zijn meerdere versies, elk met meer tolerantie voor nieuwere functies:

Profiel Jaar Wat het toevoegt
PDF/A-1b 2005 Oorspronkelijke baseline, het strengst
PDF/A-2b 2011 Staat JPEG2000, transparantie en lagen toe
PDF/A-3b 2012 Staat willekeurige bestandsbijlagen toe, de basis van Factur-X
PDF/A-4 2020 ISO 32000-2 (PDF 2.0) als basis, eenvoudiger conformiteitsniveaus

Het achtervoegsel “b” betekent “basic” conformiteit: visuele getrouwheid. Er bestaan ook “u” (Unicode-mapping) en “a” (accessibility-tagged) varianten. Voor de meeste factuur- en bonprocessen is “b” wat u nodig hebt, omdat fiscale bewaring draait om visuele reproduceerbaarheid, niet om screen-readersemantiek.

Praktische conclusie: als uw renderlaag zegt PDF/A-3b te ondersteunen, hoort dat één configuratieflag te zijn ({ profile: "PDF/A-3b" } of equivalent). Als u achteraf een tweede tool moet draaien (Ghostscript, qpdf, Acrobat) om te converteren, is dat een operationeel gat dat u moet meenemen.

Waarom juist PDF/A-3 telt: het draagt e-facturen

PDF/A-3 voegde één mogelijkheid toe die enorm belangrijk bleek: willekeurige bestandsbijlagen binnen de PDF.

Dat klinkt saai. Dat is het niet. Het is de technische basis voor de e-factuurmandaten die nu in Europa worden uitgerold.

De architectuur: één PDF-bestand dat tegelijk bestaat uit:

  1. Een mensleesbare factuur (visuele layout, totalen, branding), het deel dat een mens leest.
  2. Een machineleesbare XML-factuur, het deel dat software van een belastingautoriteit parseert.

Beide zitten in één bestand, beide beschrijven dezelfde factuur, en de PDF/A-3-wrapper garandeert dat het bestand over decennia nog parseerbaar blijft.

De twee belangrijkste XML-formaten:

  • Factur-X (Frankrijk): XML-profiel gebaseerd op UN/CEFACT Cross Industry Invoice
  • ZUGFeRD (Duitsland): inhoudelijk identiek aan Factur-X (de twee standaarden zijn technisch samengevoegd in 2018)
  • EN 16931: de Europese norm waaraan beide implementaties voldoen

Voor de meeste processen zijn “Factur-X” en “ZUGFeRD” uitwisselbare termen. Ze delen een schema, delen het insluitmechanisme, en één PDF die conform is met de ene standaard is doorgaans ook conform met de andere.

Wat verplicht is, waar en wanneer

Een niet-uitputtende momentopname voor engineers die Q2/Q3 2026-rollouts plannen:

Land Status Vereist formaat
Duitsland B2B verplicht vanaf 2025-01-01 voor ontvangst van facturen; vanaf 2027 ook voor uitgifte EN 16931 (Factur-X / ZUGFeRD / XRechnung)
Frankrijk Uitgifte verplicht voor grote ondernemingen 2026-09; mkb 2027-09 Factur-X via Chorus Pro
Italië B2B verplicht sinds 2019 FatturaPA via SDI
Polen Verplicht sinds 2024-07 KSeF
Spanje Verplicht vanaf 2026 (B2B) Facturae via FACe
België Verplicht vanaf 2026-01 Peppol BIS 3

Het patroon: elke EU-lidstaat implementeert een vorm van EN 16931-conforme e-facturatie op een tijdlijn van 2024-2027. Als uw klanten in een van deze markten actief zijn, moet uw PDF-generator XML naast de visuele factuur kunnen insluiten.

De kleinste praktische route

Laat de voorschriften uit standaarden-documentatie even los. Dit is de engineeringweergave:

   ┌─────────────────────┐
   │  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       │
   └─────────────────────┘

De twee niet-triviale stappen:

Stap 1: bouw de XML

Dit is vervelend maar mechanisch. U mapt uw factuurdata (regels, belastingen, totalen, partijen) naar EN 16931 XML-veldnamen. Er bestaan meerdere Java/Node/Python-pakketten die dit voor u doen; zoek in uw taal naar een Factur-X-pakket. Schrijf het niet vanaf nul tenzij u werkelijk plezier haalt uit XML-schemaspecificaties.

Stap 2: render PDF/A-3 en sluit de XML in

Hier maakt de keuze van renderlaag uit.

Zonder ingebouwde ondersteuning: u rendert een gewone PDF en verwerkt die daarna met een tool die converteert naar PDF/A-3 en de XML als ingesloten bestand toevoegt. Gangbare stacks: Ghostscript + qpdf, of een betaalde tool zoals Aspose. Twee extra stappen, twee extra foutpunten, en u moet zeker weten dat nabewerking de visuele layout niet laat verschuiven.

Met ingebouwde ondersteuning (de aanpak van gPdf): één call.

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

Dat is de hele route. De renderlaag geeft PDF/A-3b uit, sluit uw XML in als factur-x.xml (of zugferd-invoice.xml, beide worden door elke consument herkend) en retourneert de bytes.

Veelvoorkomende valkuilen

Een paar dingen leren teams vaak op de harde manier:

“PDF/A” en “met PDF/A-conforme fonts” zijn niet hetzelfde

Een PDF/A-3-bestand vereist dat alle fonts zijn ingesloten met volledige dekking voor de gebruikte glyphs. Als uw factuur een Japanse klantnaam bevat en de renderlaag terugvalt op een font dat niet volledig kan worden ingesloten, wijzen validatietools het bestand af. Controleer of uw renderlaag CJK-fonts insluit in PDF/A-modus; veel doen dat standaard niet.

Visueel en XML moeten overeenkomen

De XML-factuur en de visuele factuur horen dezelfde factuur te beschrijven. Fiscale auditors vergelijken ze. Als uw code XML uitgeeft met total: 119.00 en de visuele PDF Total: 120.00 toont door een afrondingsbug of verouderde template, hebt u een fiscale discrepantie in het dossier. Genereer beide vanuit één gezaghebbende bron, bij voorkeur in hetzelfde codepad.

“Profile”-niveaus in EN 16931

Factur-X heeft profielen: MINIMUM, BASIC, EN 16931, EXTENDED. Ze verschillen in hoeveel data in de XML staat. Gebruik BASIC tenzij uw klant specifiek meer vereist: het dekt belastingcodes, regels, partijen en totalen, genoeg voor ongeveer 95% van B2B-facturatie. Het EN 16931-profiel voegt extra detail toe voor randgevallen.

Controle vóór indiening

Controleer de gegenereerde PDF altijd met een PDF/A-validator (veraPDF is de open-source standaard) en controleer de XML tegen het EN 16931-schema voordat u naar de belastingautoriteit verstuurt. Mislukte indieningen bij Chorus Pro / SDI tellen mee in uw betrouwbaarheidsmetrics bij de regulator.

TL;DR

PDF/A is een profiel voor zelfvoorzienende documenten. PDF/A-3 laat u bestanden insluiten. Factur-X / ZUGFeRD is “EN 16931 XML binnen een PDF/A-3”. E-factuurmandaten in de EU maken deze combinatie van 2025-2027 het de facto B2B-factuurformaat.

Als uw renderlaag PDF/A-3 + Factur-X als één configuratieflag behandelt, is migratie mechanisch. Als dat niet zo is, bouwt u een meerstaps operationele pijplijn. gPdf’s /api/v1/e-invoice/render is de variant met één configuratieflag: de API-referentie bevat het volledige schema, of probeer een voorbeeldrender in de Playground.