DEV Community

Olivier EBRAHIM
Olivier EBRAHIM

Posted on

Factur-X 2026: Implementation Guide for French Construction SMBs

Why Factur-X Matters in 2026

Starting January 2026, the French government mandates Factur-X (eInvoicing standard based on EN 16931) for all B2B invoices above €5,000 to public procurement bodies. Here's the problem: 73% of French construction SMBs still don't understand what it is.

Factur-X is not a new invoice format—it's an XML wrapper around a standard PDF. When you invoice a government agency or large contractor, they expect an XML file embedded in your PDF that describes:

  • Line items, quantities, unit prices
  • Tax breakdown (VAT per rate)
  • Payment terms
  • Buyer and seller identifiers (SIRET, VAT number)

Miss this deadline, and your invoices bounce. Buyers (especially public entities) have the right to refuse non-compliant invoices. Worse: you might lose 30–60 days of payment float.

Identify Your Obligations

Not all invoices require Factur-X compliance. Here's the breakdown:

  • Invoicing a French public entity? → Mandatory (Jan 2026)
  • Invoicing a large contractor (>250 employees, >€50M revenue)? → Mandatory
  • Invoicing another SMB? → Recommended (voluntary for now, but adoption is growing)
  • Invoices under €5,000? → Not mandated, but future-proof anyway

Action: Pull a list of your top 20 customers. Check SIREN/SIRET databases to determine who's "large" by EU definition. Mark which invoices you'll send in Factur-X format.

Choose Your Solution: Buy vs. Build

Option A: Use a SaaS Platform (Recommended for 95%)

Advantages:

  • No dev overhead—compliance is built-in
  • Auto-generate XML with one click
  • Ongoing updates as regulations evolve

Examples:

  • Anodos — native Factur-X support, built for French construction teams
  • Sage, Cegid, SAP Ariba

Timeline: 2–4 weeks onboarding

Cost: €20–100/month

Option B: Integrate XML Generation in Your ERP

Advantages:

  • Full control over your invoice pipeline
  • One-time development cost

Disadvantages:

  • Requires developer time (6–12 weeks)
  • Ongoing maintenance and compliance risk

Libraries to explore:

  • Python: Pyinvoice, lxml
  • PHP: phpinvoice
  • Node.js: einvoicing, node-ebics

Option C: Manual XML + PDF Merge

Verdict: Don't do this.

Unless you have <5 invoices per month, manual XML generation is:

  • Error-prone
  • Doesn't scale
  • Creates regulatory liability

Technical Deep Dive

The Factur-X Structure

Factur-X combines two formats:

  1. PDF/A-3 base — the human-readable invoice (standard PDF spec)
  2. XML attachment — the machine-readable invoice data (EN 16931 schema)

When you send a Factur-X invoice, the recipient's accounting software:

  1. Extracts the XML from the PDF
  2. Validates it against the UBL 2.1 schema
  3. Auto-posts line items and tax to their ledger
  4. Never has to manually re-enter your data

Minimal Valid XML Structure

Here's the bare minimum XML structure you need:

<Invoice xmlns="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100">
  <ExchangedDocumentContext>
    <GuidelineSpecifiedDocumentContextParameter>
      <ID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</ID>
    </GuidelineSpecifiedDocumentContextParameter>
  </ExchangedDocumentContext>
  <ExchangedDocument>
    <ID>2024-00001</ID>
    <IssueDateTime>
      <DateTimeString format="102">20241215</DateTimeString>
    </IssueDateTime>
  </ExchangedDocument>
  <SupplyChainTradeTransaction>
    <ApplicableHeaderTradeAgreement>
      <SellerTradeParty>
        <PartyIdentification>
          <ID schemeID="0002">98765432109876</ID> <!-- Your SIRET -->
        </PartyIdentification>
      </SellerTradeParty>
      <BuyerTradeParty>
        <PartyIdentification>
          <ID schemeID="0002">12345678901234</ID> <!-- Buyer SIRET -->
        </PartyIdentification>
      </BuyerTradeParty>
    </ApplicableHeaderTradeAgreement>
    <SupplyChainTradeTransaction>
      <IncludedSupplyChainTradeLineItem>
        <AssociatedDocumentLineDocument>
          <LineID>1</LineID>
        </AssociatedDocumentLineDocument>
        <SpecifiedTradeProduct>
          <Name>Façade cleaning service</Name>
        </SpecifiedTradeProduct>
        <SpecifiedLineTradeAgreement>
          <NetPriceProductTradePrice>
            <ChargeAmount>300.00</ChargeAmount>
          </NetPriceProductTradePrice>
        </SpecifiedLineTradeAgreement>
        <SpecifiedLineTradeDelivery>
          <BilledQuantity>5</BilledQuantity>
        </SpecifiedLineTradeDelivery>
        <SpecifiedLineTradeSettlement>
          <ApplicableTradeTax>
            <RateApplicablePercent>20</RateApplicablePercent>
          </ApplicableTradeTax>
          <SpecifiedTradeSettlementHeaderMonetarySummation>
            <DuePayableAmount>1800.00</DuePayableAmount>
          </SpecifiedTradeSettlementHeaderMonetarySummation>
        </SpecifiedLineTradeSettlement>
      </IncludedSupplyChainTradeLineItem>
    </SupplyChainTradeTransaction>
  </SupplyChainTradeTransaction>
</Invoice>
Enter fullscreen mode Exit fullscreen mode

Embedding XML into PDF (Python)

from pypdf import PdfWriter
from lxml import etree

# Load your existing PDF invoice
writer = PdfWriter()
with open("invoice.pdf", "rb") as f:
    pdf_page = f.read()
    writer.add_page(pdf_page)

# Serialize your XML invoice
xml_data = etree.tostring(invoice_root, encoding='utf-8', xml_declaration=True)

# Attach XML as embedded file
writer.add_attachment(
    filename="facture.xml",
    data=xml_data,
    mime_type="application/xml"
)

# Write final PDF with embedded XML
with open("invoice_facturx.pdf", "wb") as out:
    writer.write(out)
Enter fullscreen mode Exit fullscreen mode

Validation Checklist

Before sending a Factur-X invoice, verify:

  • [ ] SIRET format: exactly 14 digits, no spaces or dashes
  • [ ] Invoice date: must be ≤ today's date
  • [ ] Currency code: always EUR for French invoices
  • [ ] Tax rates: match French standard (0%, 5.5%, 10%, 20%)
  • [ ] Line totals: sum of line items + tax = invoice total
  • [ ] No duplicate invoice numbers (ever)
  • [ ] XML validates against UBL 2.1 schema
  • [ ] PDF is saved as PDF/A-3-b (not just PDF/A-1)

Common Pitfalls & How to Fix Them

Pitfall Symptom Fix
SIRET formatting "Invalid identifier" error from buyer Strip all spaces/dashes; ensure exactly 14 digits
Wrong VAT rate Reconciliation fails; buyer's accountant flags it Verify item classification (materials vs. labor; some have reduced rates)
Missing currency code XML parses but total is ambiguous Always add <DocumentCurrencyCode>EUR</DocumentCurrencyCode>
Date format mismatch "Date not recognized" Use ISO 8601 format only: YYYY-MM-DD
Duplicate invoice numbers Compliance audit red flag Never re-use an invoice number; maintain a sequence
PDF/A-3-b not generated "PDF is not Factur-X compatible" Use libraries that enforce PDF/A-3-b standard (not just PDF/A-1)

Rollout Timeline

Month 1 (September 2025):

  • Audit your customer base (who's mandatory?)
  • Choose platform or dev path
  • Run pilot with 1–2 invoices

Month 2–3 (October–November 2025):

  • Full rollout to mandatory buyers
  • Train your team on the new process
  • Set up error-handling procedure (respond within 24h to rejections)

By January 1, 2026:

  • 100% compliance for public and large-buyer invoices
  • Monitor rejections in real-time
  • Fix issues within 48 hours

Recommended Tools & Resources

Official:

SaaS Platforms with Built-in Factur-X:

  • Anodos — handles XML generation, PDF embedding, and SIRET validation automatically. Built specifically for French construction teams.

Schema validators:


Olivier Ebrahim is the founder of Anodos, a construction site management platform built for French SME contractors. It handles invoice generation, Factur-X compliance, GPS crew tracking, and photo-based reserve management—all from a mobile app on the jobsite.

Top comments (0)