Guide d'intégration · Node.js

Générer un Factur-X en Node.js

L'écosystème JavaScript n'a pas d'équivalent mûr aux bibliothèques Factur-X du monde Python ou Java : produire un PDF/A-3 embarquant un XML CII valide, puis le passer au Schematron, suppose en pratique de sortir de Node. Voici la voie courte, en fetch natif, sans dépendance.

Pourquoi c'est plus dur qu'il n'y paraît en JS

Trois obstacles, dans cet ordre :

D'où le choix courant : produire la facture ailleurs, et ne garder côté Node que l'appel réseau.

Générer une facture

Node ≥ 18 : fetch est natif, aucun paquet à installer.

import { writeFileSync } from "node:fs";

const API = "https://confactura.fr";
const KEY = "df_live_…";     // POST /v1/signup pour en obtenir une (gratuit)

const invoice = {
  number: "2026-0042",
  issue_date: "2026-09-01",
  due_date: "2026-09-30",
  seller: {
    name: "Ma Société",
    address_line: "1 rue X",
    postcode: "75001",
    city: "Paris",
    siren: "123456789",
    vat_id: "FR32123456789",
    electronic_address: "[email protected]",
  },
  buyer: {
    name: "Client SARL",
    address_line: "2 av. Y",
    postcode: "69001",
    city: "Lyon",
    electronic_address: "[email protected]",
  },
  lines: [{ description: "Presta dev", quantity: 5, unit_price: "450.00" }],
};

const res = await fetch(`${API}/v1/invoices/facturx`, {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": KEY },
  body: JSON.stringify(invoice),
});

if (res.status === 422) {
  // Facture non conforme : rapport détaillé, aucun PDF produit.
  const { errors } = await res.json();
  console.error("règles en échec :", errors);
} else if (!res.ok) {
  throw new Error(`Confactura ${res.status}: ${await res.text()}`);
} else {
  const pdf = Buffer.from(await res.arrayBuffer());
  writeFileSync("facture-2026-0042.pdf", pdf);   // PDF/A-3b, XML CII embarqué
}

Attention au piège du res.text()

La réponse est un flux binaire. La lire avec text() puis la réécrire produit un PDF corrompu de façon silencieuse — il s'ouvrira peut-être, mais la pièce jointe XML sera illisible. Utilisez arrayBuffer(), et vérifiez le résultat sur le validateur plutôt que dans un lecteur PDF.

Les champs que la réforme française rend obligatoires

Le profil EN 16931 seul ne suffit pas : le Schematron CTC français ajoute ses propres règles. Trois oublis expliquent la quasi-totalité des 422 au premier essai.

Les mentions légales 2026 — frais de recouvrement, pénalités de retard, escompte, catégorie d'opération — sont ajoutées côté serveur : voir BR-FR-05.

Valider un PDF depuis vos tests

/v1/validate est gratuit, anonyme et ne consomme aucun quota — donc appelable à chaque exécution de la suite de tests.

import { readFileSync } from "node:fs";

const form = new FormData();
form.append("file", new Blob([readFileSync("facture-2026-0042.pdf")],
                             { type: "application/pdf" }), "facture.pdf");

const report = await (await fetch(`${API}/v1/validate`, {
  method: "POST", body: form,
})).json();

console.log(report.valid, report.errors);

Et le XML seul ?

POST /v1/invoices/xml renvoie le CII sans le PDF — utile si vous conservez votre propre mise en page, ou si votre Plateforme Agréée attend du XML brut. Même corps de requête, mêmes validations.

Essayer maintenant

20 documents par mois gratuits, sans carte bancaire. La clé API est créée en une requête.

Obtenir ma clé API Valider un PDF existant