Click or drag to resize
Pdf Library for .NET

Electronic Invoices (ZUGFeRD / Factur-X)

A hybrid electronic invoice carries the same invoice twice: the page a person reads, and the xml a machine reads, embedded inside the same pdf. ZUGFeRD (Germany) and Factur-X (France) are the same standard under two names, and both are what most European e-invoicing rules ask for.

SelectPdf turns a document into such an invoice with a single call: AddZugferdInvoice(Stream, ZugferdProfile, PdfAttachmentRelationship) embeds the invoice xml as an associated file and writes the metadata that invoice software looks for. The name of the embedded file is derived from the profile rather than taken from you - the standards fix it and recipients look it up by name.

Note  Note

The carrier must be a PDF/A-3 document (PdfStandard.PdfA3B, PdfStandard.PdfA3U or PdfStandard.PdfA3A), which the invoice standards require. A document that is not PDF/A-3 is refused with a message naming the fix, rather than producing a file no invoice software will accept.

Note  Note

Electronic invoices are available only in the full commercial SelectPdf library. They are not available in the free SelectPdf community edition.

Important note  Important

SelectPdf embeds and identifies the invoice xml you supply. Producing that xml - and making sure its content matches the visible invoice - is your application's job; SelectPdf does not generate or validate it.

Create a hybrid invoice from an HTML invoice

Convert the invoice page as PDF/A-3, then attach the xml to the converted document before saving it. Use PdfStandard.PdfA3A together with AccessibilityStandard if the visible invoice should also be accessible, which the standards recommend.

// the carrier: a PDF/A-3 document produced from the invoice page
HtmlToPdf converter = new HtmlToPdf();
converter.Options.PdfStandard = PdfStandard.PdfA3B;

PdfDocument doc =
    converter.ConvertUrl("https://www.example.com/invoice/2026-001");

// embed the invoice xml and mark the document as an electronic invoice
using (FileStream xml = File.OpenRead("factur-x.xml"))
{
    doc.AddZugferdInvoice(xml, ZugferdProfile.En16931,
        PdfAttachmentRelationship.Alternative);
}

// save pdf document
doc.Save("invoice-2026-001.pdf");

// close pdf document
doc.Close();

There is an overload that takes the path of the xml file instead of a stream. Either way the xml is read immediately, so the file or stream is yours to release as soon as the call returns.

Choosing the profile

The ZugferdProfile value says how much of the EN 16931 semantic model the embedded xml carries. It is recorded in the invoice metadata as the conformance level, so it must describe the xml you actually embed.

Profile

Meaning

Minimum

Accounting information only ("Buchungshilfe"). Not a complete invoice.

BasicWL

Header and footer data without invoice lines ("without lines").

Basic

A subset of EN 16931 covering simple invoices, with lines.

En16931

The full European semantic standard (formerly COMFORT). The usual choice.

Extended

EN 16931 plus additional business terms for more complex processes.

XRechnung

The German public-sector reference profile. The embedded file is named xrechnung.xml instead of factur-x.xml.

How the xml relates to the visible invoice

The PdfAttachmentRelationship value records that relationship, and recipients rely on it:

  • Alternative - the xml and the visible page carry exactly the same invoice content. This is mandatory in Germany for the BASIC, EN 16931, EXTENDED and XRECHNUNG profiles, and is the usual value.

  • Data - the visible page carries more than the xml does. Always the case for the MINIMUM and BASIC WL profiles, which are not complete invoices.

  • Source - the visible page was generated from the xml.

Turn an existing pdf into an invoice

An invoice that already exists as a pdf can be converted to PDF/A-3 first with ConvertToPdfA(PdfStandard) and then given the xml. A document that is already PDF/A-3 needs no conversion.

// load the existing invoice and make it an archival PDF/A-3 document
PdfDocument doc = new PdfDocument("invoice.pdf");
doc.ConvertToPdfA(PdfStandard.PdfA3B);

// embed the invoice xml and mark the document as an electronic invoice
doc.AddZugferdInvoice("factur-x.xml", ZugferdProfile.En16931,
    PdfAttachmentRelationship.Alternative);

doc.Save("invoice-hybrid.pdf");
doc.Close();
The deprecated ZUGFeRD 2.0 metadata

Some recipients still require the older ZUGFeRD 2.0 metadata schema. An overload taking ZugferdSchema writes that instead of the current Factur-X 1.0 schema; the embedded file is then named zugferd-invoice.xml. Use it only when a recipient asks for it.

doc.AddZugferdInvoice(xml, ZugferdProfile.Basic,
    PdfAttachmentRelationship.Alternative, ZugferdSchema.Zugferd20);
Custom metadata of your own

A PDF/A document may only carry metadata from the schemas the standard predefines, unless the schema itself is described inside the document. That is the mechanism the invoice metadata is built on, and it is available for metadata a recipient's system needs to find in your documents: AddXmpExtensionSchema(String, String, String, IDictionaryString, String) declares the schema and writes the values of its properties, so the document stays conformant.

Dictionary<string, string> properties = new Dictionary<string, string>();
properties["OrderNumber"] = "PO-4711";
properties["Department"] = "Accounts payable";

doc.AddXmpExtensionSchema("acme", "urn:acme:pdfa:custom:1p0#",
    "ACME custom schema", properties);
See Also