Factur-X 2026 Implementation Cheatsheet for French Construction SaaS
Factur-X 2026 is no longer optional for French B2B invoicing. If you're building construction software (logiciel BTP), your invoice engine must emit valid Factur-X XML alongside PDF by January 2026. This cheatsheet cuts through the spec bloat and gives you the exact implementation path.
What is Factur-X 2026?
Factur-X = e-invoice standard (French "invoice" = "facture", hence the name). It's:
- Mandatory for all B2B invoices in France starting Jan 2026
- An XML file embedded inside the PDF or sent separately
- Validates seller SIRET, buyer SIRET, VAT IDs, line items, payment terms
- Machine-readable (no OCR needed by accountant software)
- Compliant with EU Directive 2014/55/EU (cross-border standard)
If you don't support Factur-X: large clients (Décathlon, SNCF, etc.) will reject your invoices. SME construction teams will face penalties.
The Implementation Pipeline
Step 1: Choose Your Library (Don't Reinvent XML)
Node.js / JavaScript:
npm install --save factur-x-js
# or
npm install --save invoice-x
Python:
pip install factur-x
# (official French standard library)
PHP:
composer require denys-duchenko/facturx-generator
Rule: Use a validated library, not hand-rolled XML. The spec is 100+ pages; libraries handle edge cases (namespace prefixes, character encoding, SIRET checksums).
Step 2: Gather Required Data
Before generating an invoice, ensure you have:
{
"seller": {
"name": "SARL Building Masters",
"siret": "12345678901234", // 14 digits, validated
"siren": "123456789", // 9 digits (first 9 of SIRET)
"address": "123 Rue de la Paix, 75002 Paris",
"vatId": "FR12345678901" // VAT ID (optional but recommended)
},
"buyer": {
"name": "Acme Corp",
"siret": "98765432101234", // SIRET or just VAT ID
"vatId": "FR98765432101"
},
"invoice": {
"number": "INV-2026-001",
"issueDate": "2026-01-15",
"dueDate": "2026-02-15",
"currency": "EUR",
"paymentTerms": "Net 30"
},
"lineItems": [
{
"description": "Placo pose chambre étage 2",
"quantity": 8,
"unit": "hours",
"unitPrice": 65.00,
"vatRate": 0.20, // 20% is standard for construction labor
"total": 624.00
}
],
"totalExcludingVat": 624.00,
"totalVat": 124.80,
"totalIncludingVat": 748.80,
"paymentMethod": "SEPA",
"bankAccount": {
"iban": "FR1420041010050500013M02606",
"bic": "PCHQFRPP"
}
}
Step 3: Generate the Factur-X XML
import { generateFacturX } from 'factur-x-js';
const invoice = {
// ... data from Step 2
};
const facturXXml = await generateFacturX(invoice, {
format: 'BASIC', // or 'EXTENDED' (BASIC is sufficient for SMEs)
languageId: 'fr'
});
console.log(facturXXml); // Valid XML string, ready to embed
Format choice:
- BASIC: Covers 90% of construction invoices (seller, buyer, line items, totals)
- EXTENDED: Adds purchase order references, delivery notes, project codes
- For SME BTP, start with BASIC. Upgrade to EXTENDED only if clients demand it.
Step 4: Embed XML in PDF or Send Separately
Option A: Embed in PDF (Recommended)
Use a library that embeds Factur-X XML as PDF attachment:
import PDFDocument from 'pdfkit';
import fs from 'fs';
const pdfDoc = new PDFDocument();
const pdfStream = fs.createWriteStream('invoice.pdf');
pdfDoc.pipe(pdfStream);
pdfDoc.fontSize(12).text('Invoice INV-2026-001');
pdfDoc.text(`Total: €${invoice.totalIncludingVat}`);
pdfDoc.end();
// Then attach Factur-X XML to the PDF
// (library-specific; pdfkit doesn't support this natively, use pdf-lib or similar)
Better approach: Use php-invoice-x (PHP) or Factur-X-Lib (Python) which handle PDF + XML embedding directly.
Option B: Send XML Separately
Some workflows require the XML as a separate file:
POST /api/v1/invoices/send
{
"invoiceId": "INV-2026-001",
"recipientEmail": "buyer@acme.com",
"attachments": [
{
"filename": "INV-2026-001.pdf",
"mimeType": "application/pdf"
},
{
"filename": "INV-2026-001.xml",
"mimeType": "application/xml",
"content": "<facturx>...</facturx>"
}
]
}
Large clients often prefer XML separately for automation.
Step 5: Validate & Test
Before shipping to production:
# Command-line validation (Linux/macOS)
java -jar facturx-validator.jar invoice.pdf
# Online validator
# https://www.codelint.net/facturation/facturx/
Common errors:
- ❌ SIRET format invalid (must be 14 digits, numeric only)
- ❌ VAT ID mismatch (France = "FR" + 11 digits)
- ❌ Line item VAT rate missing
- ❌ Currency not EUR
- ❌ Date format (must be YYYY-MM-DD)
Fix these before production. A single invalid invoice breaks downstream accounting software.
Step 6: Archive & Audit Trail
Store the Factur-X XML alongside the PDF:
{
"invoiceId": "INV-2026-001",
"pdfUrl": "s3://bucket/INV-2026-001.pdf",
"facturXUrl": "s3://bucket/INV-2026-001.xml",
"generatedAt": "2026-01-15T10:30:45Z",
"validatedAt": "2026-01-15T10:30:50Z",
"sentAt": "2026-01-15T10:31:00Z"
}
French tax authorities can audit XML files. Keep them immutable.
Integration Checklist
- [ ] SIRET/SIREN database lookup (validate seller/buyer existence)
- [ ] VAT ID format validation (REGEX or library)
- [ ] Line item VAT rates (20% labor, 10% materials, 5.5% social housing, 2.1% books/medicine)
- [ ] PDF + XML generation tested with validator
- [ ] Unit tests for edge cases (SIRET with zeros, multi-currency conversion if applicable)
- [ ] Error handling: invalid SIRET → user-friendly message ("Validate SIRET on societe.com first")
- [ ] Audit log: every invoice generation logged with operator ID + timestamp
- [ ] Backup: nightly export of all Factur-X XMLs to cold storage
- [ ] Deadline: January 2026 (but deploy by October 2025 to let clients test)
Common Pitfalls (Based on Real Deployments)
| Pitfall | What Happens | How to Avoid |
|---|---|---|
| Hard-code VAT rates | Labor = 20%, materials = 10% (French rule). Hard-code wrong. | Use a lookup table, let accountant verify quarterly |
| SIRET validation via regex only | Fake SIRETs pass validation. Buyers reject invoice. | Validate against INSEE database (free API exists) |
| PDF without XML | Compliant with 2024, not 2026. Late discovery. | Generate both, embed early, test in staging |
| No timezone on timestamps | Auditor can't reconcile invoice time with payment time. | Always use ISO 8601 with UTC (+00:00) |
| XML encoding utf-8 vs latin1 | Accents (Côte, Île) break parsing. | Force UTF-8; validate before embedding |
Real-World Example: Anodos Invoice Flow
At Anodos, we handle 500+ invoices/month for French construction SMEs. Our flow:
- Foreman creates estimate → AI voice-to-quote → generates line items
- Site manager converts to invoice (one-click)
- Backend:
- Validates seller/buyer SIRET (5ms lookup)
- Calculates VAT (20% for labor, 10% for materials, per French rules)
- Generates Factur-X XML (using factur-x library)
- Embeds XML in PDF (using pdf-lib)
- Stores both in S3
- Email sent with PDF + XML (optional separate file)
- Accountant receives machine-readable invoice (no re-keying)
Result: Zero rejected invoices (since adoption in May 2025), 60% faster accounting reconciliation.
Resources
- Official Factur-X Spec: https://www.factur-x.gouv.fr/
- INSEE SIRET Validator: https://www.insee.fr/
- Online Validator: https://www.codelint.net/facturation/facturx/
- Python Library (recommended): https://github.com/factur-x/factur-x-python
Conclusion
Factur-X 2026 is mandatory in 9 months (January 2026). For construction SaaS:
- Use a validated library (don't reinvent).
- Validate SIRET + VAT early.
- Test with French accountant software before launch.
- Plan for Q4 2025 deployment so clients can test before the deadline.
Your invoices will be machine-readable, audit-proof, and compliant. Accountants will love you. Anodos did it—so can you.
Olivier Ebrahim
Founder, Anodos — Real-time job site management for French construction SMEs
Top comments (0)