Back to blogTechnical Guides

Factur-X: The Technical Reference (XML, Profiles, EN 16931 Mapping)

A complete developer reference for Factur-X — the hybrid PDF/A-3 + CII XML format used across France, Germany, and Luxembourg. XML anatomy, profile hierarchy, EN 16931 rule mapping, validation errors, and code samples.

Invoice Navigator TeamJuly 7, 202612 min read

Factur-X is a hybrid invoice format: a PDF/A-3 document with a structured CII XML file embedded as an attachment. One artifact, two representations — a human-readable PDF and a machine-readable XML — bound by the same source of truth.

If you build ERP integrations, you already know the visible surface. This reference is the layer underneath: how the XML sits inside the PDF, which profile does what, how the EN 16931 semantic model maps to Factur-X elements, and where the validators trip.

This is a companion to our Factur-X vs ZUGFeRD comparison, EN 16931 rules guide, and France ERP integration guide. Where those tackle strategy, this tackles bytes.

What Factur-X Actually Is

Factur-X is the French half of a single Franco-German specification. The German half is called ZUGFeRD. Since ZUGFeRD 2.1 (2020), the two are technically identical — same XML schema, same PDF/A-3 container, same profile hierarchy. Factur-X 1.08 and ZUGFeRD 2.4 (both applicable January 15, 2026) are the same document with two covers.

The specification is jointly maintained by:

  • FNFE-MPE — Forum National de la Facture Électronique et des Marchés Publics Électroniques (France)
  • FeRD — Forum elektronische Rechnung Deutschland (Germany)

Both organizations publish the same technical artifact. When a French vendor sends "a Factur-X" and a German receiver expects "a ZUGFeRD" — they are exchanging the exact same file.

The container is PDF/A-3, an ISO-standardized archival PDF variant that allows embedded file attachments (unlike PDF/A-1 and PDF/A-2, which forbid them). The attachment is a single XML file — always named factur-x.xml for the French flavor, zugferd-invoice.xml for the German flavor. Otherwise identical.

The XML syntax is UN/CEFACT Cross Industry Invoice (CII), one of the two syntaxes EN 16931 permits — the other being UBL 2.1. Factur-X is CII-only. If you need UBL, you're not building Factur-X.

The Profile Hierarchy

Factur-X defines five cumulative profiles. Each profile is a superset of the previous one, containing more mandatory fields:

ProfileData richnessEN 16931 compliant?Legal for FR B2B mandate?
MINIMUM20 fields — buyer, seller, totals, VATNoNo
BASIC WL (Without Lines)+ payment terms, referencesNoNo
BASIC+ one aggregated line itemNoNo
EN 16931+ full line items, discounts, allowancesYesYes (minimum)
EXTENDED+ logistics, project references, contract dataYesYes

For France's September 2026 B2B mandate, only EN 16931 and EXTENDED are legal. Everything below fails the CIUS-FR overlay. Many PDF libraries default to MINIMUM or BASIC because those require the least data — this is one of the top three integration failures we see on the Invoice Navigator validator.

France additionally publishes EXTENDED-CTC-FR, an EXTENDED variant carrying the extra fields the Plateforme Agréée (formerly PDP) needs for lifecycle reporting to the DGFiP. If you're serving French customers, EXTENDED-CTC-FR is the safer emit target — see the France ERP integration guide for the specifics.

Anatomy of a Factur-X File

The outer container is a PDF/A-3 document. Inside the PDF's /Names/EmbeddedFiles name tree, a single /EmbeddedFile stream holds the XML. The PDF's XMP metadata block advertises the file to processors that never crack the PDF open.

XMP metadata block

The XMP block sits inside the PDF's document catalog and declares Factur-X presence:

<rdf:Description rdf:about=""
  xmlns:fx="urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#">
  <fx:DocumentType>INVOICE</fx:DocumentType>
  <fx:DocumentFileName>factur-x.xml</fx:DocumentFileName>
  <fx:Version>1.0</fx:Version>
  <fx:ConformanceLevel>EN 16931</fx:ConformanceLevel>
</rdf:Description>

ConformanceLevel is the profile name in CamelCase — MINIMUM, BASIC_WL, BASIC, EN 16931, or EXTENDED. A validator reads this before parsing the XML and rejects mismatches between the declared profile and the actual XML content.

The embedded XML

The XML root is <rsm:CrossIndustryInvoice>, with three prefix namespaces:

<?xml version="1.0" encoding="UTF-8"?>
<rsm:CrossIndustryInvoice
  xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
  xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100"
  xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100"
  xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
  <rsm:ExchangedDocumentContext>...</rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>...</rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>...</rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>

Three top-level sections:

  1. ExchangedDocumentContext — declares the profile via a URN. This is the single most common source of validation failure: the URN and the XMP ConformanceLevel must agree.
  2. ExchangedDocument — invoice header (ID, type code 380 for invoice, issue date, notes).
  3. SupplyChainTradeTransaction — the invoice body: line items, agreement (seller/buyer parties), delivery, and settlement (totals, VAT breakdown, payment terms).

Minimum viable EN 16931 body

The following is the smallest legal EN 16931 Factur-X body — a single line item, one VAT category, one payment term:

<rsm:CrossIndustryInvoice xmlns:rsm="..." xmlns:ram="..." xmlns:udt="...">
  <rsm:ExchangedDocumentContext>
    <ram:GuidelineSpecifiedDocumentContextParameter>
      <ram:ID>urn:cen.eu:en16931:2017</ram:ID>
    </ram:GuidelineSpecifiedDocumentContextParameter>
  </rsm:ExchangedDocumentContext>
  <rsm:ExchangedDocument>
    <ram:ID>2026-INV-000123</ram:ID>
    <ram:TypeCode>380</ram:TypeCode>
    <ram:IssueDateTime>
      <udt:DateTimeString format="102">20260707</udt:DateTimeString>
    </ram:IssueDateTime>
  </rsm:ExchangedDocument>
  <rsm:SupplyChainTradeTransaction>
    <ram:IncludedSupplyChainTradeLineItem>
      <ram:AssociatedDocumentLineDocument>
        <ram:LineID>1</ram:LineID>
      </ram:AssociatedDocumentLineDocument>
      <ram:SpecifiedTradeProduct>
        <ram:Name>Consulting services — June 2026</ram:Name>
      </ram:SpecifiedTradeProduct>
      <ram:SpecifiedLineTradeAgreement>
        <ram:NetPriceProductTradePrice>
          <ram:ChargeAmount>100.00</ram:ChargeAmount>
        </ram:NetPriceProductTradePrice>
      </ram:SpecifiedLineTradeAgreement>
      <ram:SpecifiedLineTradeDelivery>
        <ram:BilledQuantity unitCode="HUR">10</ram:BilledQuantity>
      </ram:SpecifiedLineTradeDelivery>
      <ram:SpecifiedLineTradeSettlement>
        <ram:ApplicableTradeTax>
          <ram:TypeCode>VAT</ram:TypeCode>
          <ram:CategoryCode>S</ram:CategoryCode>
          <ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
        </ram:ApplicableTradeTax>
        <ram:SpecifiedTradeSettlementLineMonetarySummation>
          <ram:LineTotalAmount>1000.00</ram:LineTotalAmount>
        </ram:SpecifiedTradeSettlementLineMonetarySummation>
      </ram:SpecifiedLineTradeSettlement>
    </ram:IncludedSupplyChainTradeLineItem>
    <ram:ApplicableHeaderTradeAgreement>
      <ram:SellerTradeParty>
        <ram:Name>ACME SAS</ram:Name>
        <ram:SpecifiedLegalOrganization>
          <ram:ID schemeID="0009">78467169500035</ram:ID>
        </ram:SpecifiedLegalOrganization>
        <ram:PostalTradeAddress>
          <ram:PostcodeCode>75002</ram:PostcodeCode>
          <ram:CityName>Paris</ram:CityName>
          <ram:CountryID>FR</ram:CountryID>
        </ram:PostalTradeAddress>
        <ram:SpecifiedTaxRegistration>
          <ram:ID schemeID="VA">FR12345678901</ram:ID>
        </ram:SpecifiedTaxRegistration>
      </ram:SellerTradeParty>
      <ram:BuyerTradeParty>
        <ram:Name>Client SARL</ram:Name>
        <ram:PostalTradeAddress>
          <ram:CountryID>FR</ram:CountryID>
        </ram:PostalTradeAddress>
      </ram:BuyerTradeParty>
    </ram:ApplicableHeaderTradeAgreement>
    <ram:ApplicableHeaderTradeDelivery/>
    <ram:ApplicableHeaderTradeSettlement>
      <ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
      <ram:ApplicableTradeTax>
        <ram:CalculatedAmount>200.00</ram:CalculatedAmount>
        <ram:TypeCode>VAT</ram:TypeCode>
        <ram:BasisAmount>1000.00</ram:BasisAmount>
        <ram:CategoryCode>S</ram:CategoryCode>
        <ram:RateApplicablePercent>20.00</ram:RateApplicablePercent>
      </ram:ApplicableTradeTax>
      <ram:SpecifiedTradeSettlementHeaderMonetarySummation>
        <ram:LineTotalAmount>1000.00</ram:LineTotalAmount>
        <ram:TaxBasisTotalAmount>1000.00</ram:TaxBasisTotalAmount>
        <ram:TaxTotalAmount currencyID="EUR">200.00</ram:TaxTotalAmount>
        <ram:GrandTotalAmount>1200.00</ram:GrandTotalAmount>
        <ram:DuePayableAmount>1200.00</ram:DuePayableAmount>
      </ram:SpecifiedTradeSettlementHeaderMonetarySummation>
    </ram:ApplicableHeaderTradeSettlement>
  </rsm:SupplyChainTradeTransaction>
</rsm:CrossIndustryInvoice>

That is a valid EN 16931 profile Factur-X body. Add <ram:SpecifiedTaxRegistration> for the buyer if the buyer is VAT-registered. Add a bank account for cross-border SEPA. Everything else in EN 16931 is optional.

EN 16931 Business Terms → Factur-X XPath

The EN 16931 semantic model uses BT-* (Business Term) and BG-* (Business Group) identifiers. Every Factur-X element maps to one BT or BG. The most common ones:

EN 16931 BTMeaningFactur-X XPath (relative to root)
BT-1Invoice numberExchangedDocument/ID
BT-2Issue dateExchangedDocument/IssueDateTime/DateTimeString
BT-3Invoice type codeExchangedDocument/TypeCode
BT-5Currency codeSupplyChainTradeTransaction/ApplicableHeaderTradeSettlement/InvoiceCurrencyCode
BT-27Seller name.../ApplicableHeaderTradeAgreement/SellerTradeParty/Name
BT-31Seller VAT.../SellerTradeParty/SpecifiedTaxRegistration/ID[@schemeID='VA']
BT-44Buyer name.../BuyerTradeParty/Name
BT-48Buyer VAT.../BuyerTradeParty/SpecifiedTaxRegistration/ID[@schemeID='VA']
BT-106Sum of line net amounts.../SpecifiedTradeSettlementHeaderMonetarySummation/LineTotalAmount
BT-109Invoice total without VAT.../TaxBasisTotalAmount
BT-110Total VAT amount.../TaxTotalAmount
BT-112Invoice total with VAT.../GrandTotalAmount
BT-115Amount due for payment.../DuePayableAmount

For the full 164-BT map, see the EN 16931 rules guide — this is a working developer subset.

Validation Layers and Common Failures

A Factur-X invoice gets validated at four progressively stricter layers. Each layer rejects for different reasons.

1. PDF/A-3 conformance. Fails when the outer PDF is PDF/A-1, PDF/A-2, or a plain PDF. Symptom: veraPDF or similar rejects with pdfa1a violations. Fix at the PDF generation library level.

2. XML Schema (XSD). The CII schemas from UN/CEFACT enforce structure and datatypes. Fails when required elements are missing, cardinality is wrong (too many <ApplicableTradeTax> for the profile), or datatypes are wrong (a string in a decimal field). Symptom: cvc-complex-type, cvc-datatype-valid.

3. EN 16931 Schematron. 155 rules covering semantic correctness — totals must reconcile, VAT categories must be consistent, dates must be plausible. The common failures:

RuleMeaningTypical cause
BR-CO-10Sum of line amounts must equal BT-106Rounding drift, wrong line count
BR-CO-13BT-109 = BT-106 − allowances + chargesMissing header-level allowances
BR-CO-15BT-112 = BT-109 + BT-110Off-by-one on rounding half-up vs half-even
BR-S-08Standard VAT category needs rate > 0Emitting CategoryCode = S with 0%
BR-CL-04Currency code must be ISO 4217Lowercase "eur" or "€" symbol

BR-CO-* rules are consistency rules. If your total won't reconcile, it's almost always rounding — see the most common e-invoice errors guide for the half-up vs banker's rounding trap.

4. Country CIUS Schematron. France layers CIUS-FR on top of EN 16931 for its mandate — extra mandatory fields (SIRET, French tax codes), stricter cardinalities. Germany's public sector uses XRechnung's CIUS with its own rule set (BR-DE-*). A Factur-X invoice can pass the EN 16931 layer and still fail CIUS. This is where most cross-border ERP integrations break.

Country Support Matrix

CountryAccepts Factur-X?CIUS layerNotes
FranceYesCIUS-FRMandatory for B2B from Sept 1, 2026. See France guide
GermanyYesXRechnung (public sector); none (B2B)Factur-X and XRechnung are both EN 16931 formats; both accepted
LuxembourgYesNoneFactur-X and XRechnung accepted equally via Peppol
NetherlandsVia Peppol onlyNoneUBL preferred; Factur-X converted server-side
BelgiumVia Peppol onlyNonePeppol BIS 3.0 (UBL) is the native format
ItalyNoFatturaPASDI accepts only FatturaPA XML; Factur-X must be converted
PolandNoKSeF FA(3)KSeF has its own XML; Factur-X not accepted

For a country-by-country map of formats and mandates, see the country pages.

Generating Factur-X — What Your Pipeline Needs

An emission pipeline has three stages:

1. Build the CII XML. From your invoice domain model, populate the CII structure. Any XML serializer works; there are also higher-level libraries (factur-x on PyPI, mustangproject for Java/Maven, Sylius/FacturX for PHP) that generate the XML from a typed domain object.

2. Build the PDF/A-3. Generate the visual invoice as a PDF/A-3-conformant document. The most common cause of PDF/A-3 failure is a color profile mismatch — embed sRGB IEC61966-2.1 or an equivalent OutputIntent. Do not embed non-embedded fonts.

3. Attach and stamp. Add the CII XML as a /EmbeddedFile stream. Set the /AFRelationship key to /Alternative for Factur-X 1.0.06+. Write the XMP metadata block. Re-serialize the PDF (many libraries need a save-optimize pass to fix the file offset table).

Before you ship, validate on all four layers. The public FNFE-MPE validator and the KoSIT XRechnung validator are the reference implementations. Both are useful for spot checks; neither is engineered for pipeline throughput. If you need per-invoice validation in a build pipeline or CI, Invoice Navigator's fixer API is designed for that path.

FAQ

What is the difference between Factur-X and ZUGFeRD?

Since ZUGFeRD 2.1 they are technically identical — same specification, same profiles, same XML schema. The only differences are the naming (Factur-X for France, ZUGFeRD for Germany), the internal XML filename (factur-x.xml vs zugferd-invoice.xml), and the maintaining organization. See the full breakdown in Factur-X vs ZUGFeRD.

Is Factur-X mandatory in France in 2026?

Factur-X itself is not mandatory — France's B2B mandate accepts three formats: Factur-X, UBL 2.1, and pure CII. Factur-X is the format the French market expects and where PA pilot traffic concentrates. The mandate starts September 1, 2026 for receiving; issuing follows a phased large-then-mid-then-small enterprise ramp.

Which Factur-X profile should I emit?

For the French B2B mandate, minimum is EN 16931. Recommended is EXTENDED-CTC-FR (or EXTENDED if you're not going through a French PA). Never emit MINIMUM, BASIC WL, or BASIC — they're not EN 16931 compliant and the PA will reject them.

Can I use Factur-X for Peppol?

Not directly. Peppol BIS Billing 3.0 uses UBL 2.1, not CII. Some Peppol Access Points transparently convert CII ↔ UBL at the network edge, but the on-wire format inside Peppol is UBL. If you're sending via Peppol, generate UBL; if you're going through a French PA outside Peppol, generate Factur-X.

What's the difference between Factur-X and e-Invoicing?

E-invoicing is the umbrella term — any structured, machine-readable invoice format. Factur-X is one specific format within e-invoicing. Others include XRechnung (Germany), UBL (Peppol, Netherlands), FatturaPA (Italy), and KSeF FA(3) (Poland). All of them can be "e-invoices"; only Factur-X uses the hybrid PDF/A-3 + CII XML approach.

How do I validate a Factur-X file?

Four layers: PDF/A-3 (veraPDF), XML Schema (any XSD validator), EN 16931 Schematron (KoSIT or FNFE-MPE reference implementation), and country CIUS Schematron (CIUS-FR for France, XRechnung for German public sector). Public web validators cover all four but with a rate-limited, interactive interface. See how to validate e-invoices via API for pipeline-grade options.

What is a Factur-X XML example?

The minimum viable EN 16931 body is above. For a full working file with attached PDF, the FNFE-MPE reference implementation on GitHub carries current example files for every profile. Do not reuse example files from before January 2026 — Factur-X 1.08 introduced small breaking changes in the XMP block.

Does Factur-X work with SAP?

Yes. SAP S/4HANA supports Factur-X natively via the Document and Reporting Compliance (DRC) framework from release 2023 onwards. For older SAP releases, third-party add-ons (SEEBURGER, Basware, Comarch) provide Factur-X emission on top of standard SAP output management. The XML mapping is the same either way — SAP just needs the right output type configured.

Is Factur-X free to use?

Yes. Both the Factur-X specification and the underlying UN/CEFACT CII schema are freely available. The FNFE-MPE and FeRD publish the full technical documentation without licensing fees. Commercial libraries and validators exist, but the format itself is open.

Further Reading

Internal references:

External references:

  • FNFE-MPE Factur-X specification (fnfe-mpe.org)
  • FeRD ZUGFeRD documentation (ferd-net.de)
  • UN/CEFACT Cross Industry Invoice schema
  • KoSIT XRechnung validator (xeinkauf.de)

Invoice Navigator is a compliance safety layer for EU e-invoicing pipelines. If you build Factur-X in an ERP context and want per-invoice validation with automatic fixes for the top rounding, VAT-category, and CIUS-FR failures, see how the fixer works.

Check Your Compliance Status

Find out exactly what your business needs to do for e-invoicing compliance.

Use Obligation Finder