Concept · Hybrid e-invoicing
What is ZUGFeRD / Factur-X,
and why does it matter?
ZUGFeRD and Factur-X are two names for the same thing: a hybrid electronic invoice. It is a single PDF that a person can read and print like any invoice, while a structured XML twin sits sealed inside the very same file so accounting software can import it automatically, no retyping, no scanning. One document, two readers. This guide explains it in plain language, with examples.
The simplest analogy: a letter with a barcode
Imagine a posted invoice that a colleague can read at a glance, and in the corner a barcode that a scanner reads in an instant. Today those are two separate things: a paper (or PDF) invoice for people, and, if you are lucky, a separate data file for the computer, sent alongside and easily lost or mismatched.
ZUGFeRD / Factur-X puts both into one file that can never drift apart. The page you see and the data the machine reads are the same invoice, bound together. The human never has to type the numbers into the accounting system, and the machine never has to guess at a scan. It is the difference between handing someone a photo of a form and handing them a form that also fills itself in.
What goes wrong with an ordinary PDF invoice
A plain PDF is just a picture of an invoice to a computer. To get the numbers into an ERP, someone has to read them and type them in, or run fragile OCR. Every hop is slow and a chance to introduce an error in a figure that has to be exactly right.
With ZUGFeRD / Factur-X the middle step disappears: the ERP reads the embedded XML directly from the same file the person already received.
One file, two faces
The visible PDF page and the embedded XML describe the same invoice. The person reads the page; the software reads the data. Because they live in one file, they are guaranteed to match.
The page a person sees
A normal, printable invoice layout.
The XML a machine reads
factur-x.xml, embedded in the same file.
ZUGFeRD or Factur-X? Same standard, two names
They are developed jointly and are technically aligned. ZUGFeRD is the
German name, Factur-X is the French one. Since ZUGFeRD 2.1 they share the
same embedded file name (factur-x.xml) and both implement the
European semantic standard EN 16931. A file produced as one is
valid as the other.
ZUGFeRD
Germany · FeRD
Factur-X
France · FNFE-MPE
Both are built on PDF/A-3, the archival PDF that is allowed to embed arbitrary files. That is what lets a long-lived, self-contained invoice also carry its structured data inside.
What turns a PDF into a ZUGFeRD / Factur-X invoice
Three things are added on top of a normal, well-formed invoice page.
A PDF/A-3 base
The page is rendered as archival PDF/A-3, the level that permits embedding other files and guarantees long-term fidelity.
The embedded XML
The Cross-Industry Invoice is attached as factur-x.xml with the correct relationship, marking it the data twin of the page.
Factur-X XMP metadata
An fx identification block in the XMP records the document type, version and profile so any reader can detect it.
The profiles: from MINIMUM to EXTENDED
A profile says how much structured data the XML carries. You pick
the one your recipient and your jurisdiction require. EN 16931
(also called Comfort) is the common interoperable level for B2B.
| Profile | Line items? | What it carries |
|---|---|---|
| MINIMUM | No | Header totals only. Often used for booking aids, not a full legal invoice on its own. |
| BASIC WL | No | Header and document-level data without line items ("without lines"). |
| BASIC | Yes | Adds invoice line items on top of BASIC WL. |
| EN 16931 | Yes | The full European semantic core. The recommended, widely interoperable level for B2B. |
| EXTENDED | Yes | EN 16931 plus extra fields for complex, sector-specific or cross-border cases. |
rust-pdf writes all five profiles into the Factur-X XMP, and the output validates as PDF/A-3 + Factur-X under veraPDF.
Where it is used, and increasingly required
Structured e-invoicing is moving from optional to mandatory across Europe, and the hybrid PDF format is a natural fit because it satisfies people and systems at once.
Germany
Businesses must be able to receive structured B2B e-invoices, with sending obligations phasing in. ZUGFeRD is a recognised format.
France
The national e-invoicing reform is rolling out a mandate for structured invoices, with Factur-X among the accepted formats.
EU / EN 16931
The European semantic standard underpins both formats and the EU's ViDA ("VAT in the Digital Age") direction of travel.
Public sector
Administrations increasingly accept or require structured invoices for supplier payments, where a hybrid file eases adoption.
Enterprise AP/AR
Accounts-payable teams post incoming hybrid invoices automatically, cutting re-keying, OCR cost and disputes.
Long-term archiving
Because the base is PDF/A-3, the invoice is also an archival record that stays readable and self-contained for decades.
Plain PDF vs ZUGFeRD / Factur-X at a glance
| Plain PDF invoice | ZUGFeRD / Factur-X | |
|---|---|---|
| Human-readable | Yes | Yes |
| Machine-readable | Only via OCR | Yes, embedded XML |
| Posting to ERP | Manual re-keying | Automatic |
| Data & page can mismatch | Yes (separate files) | No, one file |
| Satisfies EU e-invoice mandates | No | Yes (EN 16931) |
| Long-term archival | Not guaranteed | PDF/A-3 by design |
How to create a valid ZUGFeRD / Factur-X file with rust-pdf
Render the visible invoice page as usual, then one call embeds the
Cross-Industry Invoice XML as factur-x.xml, switches the
document to PDF/A-3, and writes the Factur-X identification into the
XMP at your chosen profile. The output is checked by veraPDF.
# pip install rustpdf
import rustpdf
xml = open("invoice.xml", "rb").read() # EN 16931 Cross-Industry Invoice
with rustpdf.Document() as doc:
doc.facturx(xml, rustpdf.FacturxProfile.EN16931) # -> PDF/A-3 + Factur-X
doc.set_info(title="Invoice INV-2026-0042")
f = doc.add_font_file("Roboto-Regular.ttf")
doc.add_page()
doc.show_text(f, 22, 72, 760, "Invoice INV-2026-0042")
doc.save("invoice_facturx.pdf") # veraPDF-valid hybrid invoice
// dotnet add package RustPdf
using RustPdf;
byte[] xml = File.ReadAllBytes("invoice.xml"); // EN 16931 CII
using var doc = new Document();
doc.Facturx(xml, FacturxProfile.En16931) // -> PDF/A-3 + Factur-X
.SetInfo(title: "Invoice INV-2026-0042");
int f = doc.AddFontFile("Roboto-Regular.ttf");
doc.AddPage();
doc.ShowText(f, 22, 72, 760, "Invoice INV-2026-0042");
byte[] bytes = doc.ToBytes(); // hybrid invoice
// go get github.com/rustpdf/rustpdf-go@latest
xml, _ := os.ReadFile("invoice.xml") // EN 16931 CII
doc, _ := rustpdf.New()
defer doc.Close()
doc.Facturx(xml, rustpdf.FacturxEN16931) // -> PDF/A-3 + Factur-X
doc.SetInfo(rustpdf.Info{Title: "Invoice INV-2026-0042"})
f, _ := doc.AddFontFile("Roboto-Regular.ttf")
doc.AddPage()
doc.ShowText(f, 22, 72, 760, "Invoice INV-2026-0042", 0)
data, _ := doc.ToBytes() // hybrid invoice
// npm install rustpdf
const { Document, FacturxProfile } = require("rustpdf");
const fs = require("fs");
const xml = fs.readFileSync("invoice.xml"); // EN 16931 CII
const doc = new Document();
doc.facturx(xml, FacturxProfile.EN16931) // -> PDF/A-3 + Factur-X
.setInfo({ title: "Invoice INV-2026-0042" });
const f = doc.addFontFile("Roboto-Regular.ttf");
doc.addPage();
doc.showText(f, 22, 72, 760, "Invoice INV-2026-0042");
const bytes = doc.toBytes(); // hybrid invoice
You supply the EN 16931 invoice XML (from your accounting system or an invoice library); rust-pdf handles the PDF/A-3 packaging, the embedding and the metadata. Full details in the documentation.
ZUGFeRD / Factur-X FAQ
What is ZUGFeRD / Factur-X?
ZUGFeRD (Germany) and Factur-X (France) are the same hybrid e-invoice standard under two names. A hybrid e-invoice is a single PDF/A-3 file that is both human-readable, the visible invoice page a person can read and print, and machine-readable, an XML file embedded inside it that an accounting system can import automatically. One file satisfies both the person and the software, with no separate XML to send or risk losing.
What is the difference between ZUGFeRD and Factur-X?
There is no technical difference at the interoperable level. ZUGFeRD is the German name and Factur-X is the French name for the same specification, developed jointly by FNFE-MPE in France and FeRD in Germany. Since ZUGFeRD 2.1, the two are aligned: the embedded file is named factur-x.xml in both, and both implement the European semantic standard EN 16931. A file produced as Factur-X is valid ZUGFeRD and vice versa.
Why does an invoice need to be both PDF and XML?
People need to read, check and archive an invoice, which a PDF does well. Accounting and ERP systems need structured data they can post automatically without retyping or OCR, which XML does well. A plain PDF forces the recipient to key the numbers in by hand, which is slow and error-prone. A hybrid e-invoice carries both inside one file, so the same document serves the human and the machine and the two can never disagree.
What are the ZUGFeRD / Factur-X profiles?
Profiles describe how much structured data the XML carries. MINIMUM and BASIC WL hold only header totals, with no line items. BASIC adds line items. EN 16931 (also called Comfort) is the full European semantic core and is the common interoperable level for B2B. EXTENDED adds further fields for complex or cross-border cases. You pick the profile that matches what your recipient and your jurisdiction require.
How do I create a valid ZUGFeRD / Factur-X file?
Render the visible invoice as PDF/A-3, embed the Cross-Industry Invoice XML as factur-x.xml with the correct AFRelationship, and write the Factur-X identification into the XMP metadata at the chosen profile. With rust-pdf this is one call, for example doc.facturx(xml, FacturxProfile.EN16931), in Python, C#, Go, Node, Java, PHP, Ruby, Delphi or Swift. The output validates as PDF/A-3 plus Factur-X under veraPDF.
Generate ZUGFeRD / Factur-X invoices in your language
One core, the same hybrid e-invoice output across nine languages. Prototype for free, license the corporate features when you ship.