DEV Community

Olivier EBRAHIM
Olivier EBRAHIM

Posted on

Factur-X 2026 : implémentation pratique pour les PME du BTP

Factur-X 2026 : implémentation pratique pour les PME du BTP

Introduction : la facture électronique devient obligatoire

Depuis le 1er septembre 2026, la facturation électronique au format Factur-X est devenue obligatoire pour toutes les entreprises du BTP en France. Ce n'est pas un simple changement de format : c'est une refonte de la chaîne de facturation entre les systèmes ERP, les outils comptables, et les portails publics français (Chorus, e-SENS).

Pour les développeurs travaillant sur des solutions BTP, comprendre Factur-X signifie maîtriser la structure XML/UBL, les règles de validation SIREN, les flux de transmission, et surtout : éviter les pièges courants qui bloquent les PME pendant des semaines.

Cet article décortique les 5 erreurs d'implémentation qu'on voit le plus souvent, et propose une checklist d'intégration éprouvée.


1. Le piège de la dualité XML/PDF : Factur-X n'est pas "juste" un PDF

Le malentendu classique :
Les développeurs pensent souvent que Factur-X = PDF avec un fichier XML attaché. C'est techniquement vrai, mais c'est une simplification dangereuse.

❌ MAUVAIS : générer un XML Factur-X, créer un PDF séparé, les coller ensemble
✓ BON     : générer un seul fichier PDF/A-3 qui inclut l'XML en métadonnée
Enter fullscreen mode Exit fullscreen mode

Pourquoi c'est important :

  • Les portails publics français (Chorus) rejettent les fichiers hybrides mal formés. Ils analysent l'XML embarqué, pas juste le PDF visuel.
  • L'archivage légal en France (article L123-1 du Code de commerce) exige la validité structurelle de l'XML, pas seulement la lisibilité du PDF.
  • Les PME qui envoient des PDF+XML "bricolés" se retrouvent avec des retours d'erreur du portail public 3 semaines après.

Solution :
Utilise une librairie spécialisée pour générer directement un PDF/A-3 avec l'XML embarqué en conformité. Côté JavaScript/Node.js, facturx ou zugferd-node sont éprouvés. Côté Python, facturx est la référence.


2. Les champs obligatoires : quelle version de la norme ?

Le piège :
Factur-X a plusieurs niveaux de conformité :

  • Minimum : 17 champs obligatoires (BASIC)
  • Intermédiaire : 60+ champs (EN16931)
  • Complet : 150+ champs (Extended)

Les PME françaises doivent supporter au minimum EN16931 pour que Chorus accepte la facture. Beaucoup de devs commencent avec la version BASIC pour simplifier, puis se retrouvent bloqués au premier envoi vers Chorus.

Checklist des champs à ne pas oublier :

Facture (invoice) :
  ✓ BT-1  : Invoice number (unique, sans espaces ni accents)
  ✓ BT-2  : Invoice issue date (YYYY-MM-DD)
  ✓ BT-9  : Due date (YYYY-MM-DD, optionnel mais recommandé)
  ✓ BT-5  : Invoice type (e.g., "380" pour facture normale)

Seller (émetteur) :
  ✓ BT-27 : Seller legal name
  ✓ BT-29 : Seller trading name (optionnel)
  ✓ BT-33 : Seller VAT number (FR XX XXXXXXXXXX)
  ✓ BT-34 : Seller identification (SIREN, SIRET)

Buyer (acheteur) :
  ✓ BT-44 : Buyer legal name
  ✓ BT-48 : Buyer VAT number (si applicable)
  ✓ BT-49 : Buyer identification (si public sector)

Lignes de facturation :
  ✓ BT-106 : Invoice line amount (net HT)
  ✓ BT-121 : VAT category (standard, zero, exempted, etc.)
  ✓ BT-118 : Unit price (net)

Totaux :
  ✓ BT-109 : Invoice total amount (TTC)
  ✓ BT-110 : Total VAT amount
Enter fullscreen mode Exit fullscreen mode

Conseil pro : Valide ton XML contre le schéma Factur-X 1.0.07 (la version officielle) avec un outil en ligne avant de le passer en production. Un validateur comme XSD Validator peut te sauver des heures.


3. Les erreurs de devises et de TVA

Scénario courant :
Une PME de charpente facture un client en euros. Le champ devise (BT-96) est supposé être EUR. Mais le développeur oublie que certains clients acceptent plusieurs devises, et la migration d'un système legacy peut laisser des USD ou CHF en base.

Danger immédiat :
Chorus rejette tout fichier avec une devise différente de EUR pour les entrées/sorties intracommunautaires. La facture n'arrive jamais à destination.

Règle de TVA qui bloque :

Si vendeur.VAT_country = "FR" ET acheteur.VAT_country = "FR"
  => TVA standard (20%) ET devise DOIT être EUR

Si vendeur.VAT_country = "FR" ET acheteur hors UE
  => TVA = 0% (exonération) MAIS tu dois indiquer la raison
     (BT-120 = "VATEX-G" pour prestation intra-communautaire)

Si devise != EUR MAIS client français
  => ERREUR : Chorus refuse
Enter fullscreen mode Exit fullscreen mode

Implementation check :

if (seller.vatCountry === "FR" && buyer.vatCountry === "FR") {
  if (invoice.currency !== "EUR") {
    throw new Error("Factur-X FR→FR must use EUR currency");
  }
  if (invoice.vatRate !== 20) {
    console.warn("Standard FR VAT is 20%, you have", invoice.vatRate);
  }
}
Enter fullscreen mode Exit fullscreen mode

4. Timestamps et signatures : le piège de l'horodatage

L'erreur classique :
Tu signes numériquement une facture Factur-X avec ton certificat client. Super. Mais tu oublies d'inclure un timestamp tiers (via un service d'horodatage RFC 3161).

Résultat :
6 mois plus tard, ta clé privée a expiré ou a été révoquée. Les auditeurs demandent si la signature était valide au moment de l'émission. Sans timestamp, impossible à prouver. Chorus peut même invalider la facture rétrospectivement.

Règle légale (France 2026) :

  • Les factures haute valeur (> 5 000 €) doivent être signées XAdES (XML Advanced Signature).
  • La signature doit inclure un timestamp d'une autorité de confiance (Thales, Certigna, AC SNCF, etc.).
  • Chorus valide le timestamp au moment de la réception.

Implémentation :
Utilise une librairie comme xades-js (JS) ou python-xades (Python) qui gère les timestamps RFC 3161 automatiquement.

const xadesSignature = await signXml(
  facturXml,
  certificatePrivateKey,
  {
    timestampUrl: "http://timestamp.certigna.fr/services/timestamp",
    profile: "XAdES-EPES" // Enhanced Electronic Signature
  }
);
Enter fullscreen mode Exit fullscreen mode

5. Les routes d'envoi : quand envoyer où ?

La confusion :
Une PME BTP génère une facture Factur-X. Ensuite, elle doit l'envoyer... où exactement ?

  • Via Chorus (portail public français) ? ✓ obligatoire si le client est public sector
  • Via e-SENS (réseau de transmission) ? ✓ si le client est en UE et inscrit
  • Via email direct au client ? ✓ acceptable mais moins sûr
  • Via l'ERP du client ? ✓ si API privée disponible

Règles 2026 :

Acheteur = Administration publique (code APE 84xx)
  => Doit recevoir via Chorus OU e-SENS
  => Format Factur-X obligatoire

Acheteur = Entreprise privée française
  => Peut recevoir par email + Factur-X
  => Peut aussi utiliser e-SENS si inscrit

Acheteur = Entreprise UE (autre pays)
  => e-SENS prioritaire (interopérabilité UE)
  => Factur-X ou format local acceptable
Enter fullscreen mode Exit fullscreen mode

Check avant envoi :

function getTransmissionRoute(buyer) {
  if (buyer.isPublicSector) {
    return { route: "CHORUS", required: true };
  } else if (buyer.country !== "FR") {
    return { route: "eSENS", required: false, fallback: "email" };
  } else {
    return { route: "email", required: false, fallback: "manual" };
  }
}
Enter fullscreen mode Exit fullscreen mode

Intégration chez Anodos : cas réel

Chez Anodos, une solution de gestion de chantier pour PME du BTP, nous avons intégré Factur-X 2026 en avril 2026. Nos apprentissages :

  1. Valider l'XML en temps réel lors de la création de la facture, pas à l'envoi (économise 90% du support utilisateur).
  2. Proposer un PDF+Factur-X hybride : les utilisateurs reçoivent un fichier à la fois lisible et valide légalement.
  3. Automatiser les timestamps : l'utilisateur ne doit jamais gérer certificats ou horloges.
  4. Tester contre le sandbox Chorus avant chaque release (sinon surprises en production).

Le coût d'une intégration sérieuse Factur-X : 200-400 heures dev. Le coût d'une intégration bancale : pénalités + support utilisateur infini.


Checklist finale : avant de passer en prod

  • [ ] XML valide contre le schéma Factur-X 1.0.07
  • [ ] Tous les champs EN16931 remplis (validation stricte en code)
  • [ ] Devise = EUR pour les factures FR→FR
  • [ ] TVA correctement calculée (incluyant les cas exonération/intra-UE)
  • [ ] Signature XAdES-EPES avec timestamp RFC 3161 (si montant > 5 000 €)
  • [ ] Route d'envoi déterminée avant génération (email vs Chorus vs e-SENS)
  • [ ] Test d'envoi réussi vers le sandbox Chorus
  • [ ] Archivage légal des originaux (PDF + XML + signature)
  • [ ] Gestion des erreurs Chorus documentée (quoi faire si 400/401/413)

Ressources


Olivier Ebrahim, fondateur d'Anodos, plateforme de gestion de chantier BTP pour PME avec facturation Factur-X native. Ancien dev fullstack, passionné par les workflows artisans et la régul française.

Top comments (0)