De la conformité en 3 jours : Comment un éditeur a intégré la facture électronique sans réécrire son logiciel
Guide technique d'intégration — Janvier 2026
TL;DR — Un éditeur de logiciel de gestion a rendu son application conforme à la réforme de la facturation électronique 2026 en 3 jours de développement, sans toucher à son architecture existante.
Mots-clés : intégration Factur-X, SDK facturation électronique, API e-invoicing Python, conformité 2026, Solution Compatible
Le défi : 400+ règles métier à implémenter
La transition vers la facturation électronique (norme EN 16931 / Factur-X) représente un défi majeur pour les éditeurs de logiciels. Il ne s'agit plus de générer un simple PDF, mais de produire un fichier structuré conforme à des centaines de règles de validation — mentions légales françaises (BR-FR), structure XML CII, calculs de TVA normalisés, conformité PDF/A-3 (archivage longue durée), et communication sécurisée avec les plateformes agréées (PA/PDP)...
Deux options s'offraient à cet éditeur :
- Développer en interne : 3 à 6 mois d'effort, maintenance continue des normes
- Déléguer la complexité : intégrer une API spécialisée
Cet article détaille comment l'intégration de FactPulse a permis de transformer ce projet complexe en un développement Python standard et maintenable.
Étape 1 — Adapter le modèle de données (30 minutes)
La première étape consiste à enrichir le modèle existant avec quelques champs requis par la réglementation française (règles BR-FR).
Seulement 5 champs à ajouter :
- 3 mentions légales obligatoires (frais de recouvrement, pénalités, escompte)
- 2 champs JSON pour le suivi des échanges avec l'API
Snippet d'adaptation (Django models) :
# models.py
class Facture(models.Model):
# ... champs existants (montant_ht, date, etc.) ...
# Mentions légales obligatoires (BR-FR-05)
mention_frais_recouvrement = models.CharField(
max_length=1024, blank=True, default="",
help_text="Mention obligatoire : Indemnité forfaitaire pour frais de recouvrement"
)
mention_penalites_retard = models.CharField(
max_length=1024, blank=True, default="",
help_text="Mention obligatoire : Pénalités en cas de retard de paiement"
)
mention_escompte = models.CharField(
max_length=1024, blank=True, default="",
help_text="Mention obligatoire : Escompte pour paiement anticipé ou son absence"
)
# Stockage des retours API pour le suivi
erreurs_validation_facturx = models.JSONField(
default=list,
help_text="Stocke les messages d'erreur lors de la validation du XML"
)
reponse_plateforme_agreee = models.JSONField(
default=dict,
help_text="Stocke la réponse complète (Flow ID, Tracking ID) lors de la soumission"
)
Étape 2 — Mapper les données métier (1 heure)
C'est ici que la valeur de l'API se révèle. Le SDK FactPulse est un wrapper HTTP minimaliste qui appelle directement les endpoints API. L'API fait le travail lourd : validation, enrichissement automatique depuis le SIRET, génération PDF/A-3, et soumission aux plateformes.
Format simplifié avec auto-enrichissement — Fournissez seulement le SIRET et l'IBAN. L'API récupère automatiquement la raison sociale, l'adresse, le numéro de TVA intracommunautaire.
Snippet d'initialisation de la facture :
# methods_facturx.py
def build_invoice_payload(facture: Facture) -> dict:
"""Transform internal business object into FactPulse API payload."""
return {
"number": facture.numero_facture,
"invoiceDate": facture.date_emission.isoformat(),
"paymentDueDate": facture.date_echeance.isoformat(),
# Format simplifié : SIRET + IBAN suffisent
# L'API enrichit automatiquement (raison sociale, adresse, TVA)
"supplier": {
"siret": facture.fournisseur.siret,
"iban": facture.fournisseur.iban,
"routingAddress": facture.fournisseur.siret, # Adresse électronique
},
"recipient": {
"siret": facture.destinataire.siret,
"routingAddress": facture.destinataire.siret,
},
# Lignes de facture
"lines": _build_invoice_lines(facture),
# Mentions légales obligatoires (BR-FR)
"notes": [
{"subjectCode": "PMT", "content": facture.mention_frais_recouvrement},
{"subjectCode": "PMD", "content": facture.mention_penalites_retard},
{"subjectCode": "AAB", "content": facture.mention_escompte},
],
}
Étape 3 — Détailler les lignes (45 minutes)
Factur-X exige un détail précis de chaque ligne (biens/services). Le mapping est direct : les noms de champs correspondent à l'API.
def _build_invoice_lines(facture):
"""Map internal invoice lines to API format."""
lines = []
for ligne in facture.lignes.all():
lines.append({
"description": ligne.libelle,
"quantity": float(ligne.quantite),
"unitPrice": float(ligne.prix_unitaire),
"vatRate": float(ligne.taux_tva), # e.g., 20.0
})
return lines
Note : Avec
autoEnrich=True(par défaut), l'API calcule automatiquement les totaux HT, TVA et TTC à partir des lignes. Pas besoin de les calculer côté client.
Étape 4 — Générer, valider et soumettre en un seul appel (30 minutes)
L'appel à l'API génère le PDF/A-3 conforme, valide en temps réel toutes les règles métier, et soumet directement à la plateforme. Le SDK gère automatiquement le polling des tâches asynchrones.
import base64
from factpulse_helpers import FactPulseClient, FactPulseError
def generate_and_submit_facturx(facture, pdf_original_bytes):
"""Generate Factur-X PDF and submit to PDP in one call."""
client = FactPulseClient(
email="api@votre-editeur.fr",
password="votre-mot-de-passe",
client_uid="uuid-de-votre-client", # Credentials PDP configurés dans le Dashboard
)
try:
payload = build_invoice_payload(facture)
# Un seul appel : génération + validation + soumission PDP
result = client.post(
"processing/invoices/submit-complete-async",
invoiceData=payload,
sourcePdf=base64.b64encode(pdf_original_bytes).decode(),
profile="EN16931",
destination={"type": "afnor"},
)
# Le PDF Factur-X est dans result["content"] (auto-décodé)
pdf_facturx = result["content"]
# Sauvegarder la preuve de soumission
facture.reponse_plateforme_agreee = {
"success": True,
"flowId": result.get("afnorResult", {}).get("flowId"),
"validation": result.get("validation", {}),
}
facture.erreurs_validation_facturx = []
facture.save()
return pdf_facturx
except FactPulseError as e:
# Stocker les erreurs structurées pour l'affichage UI
facture.erreurs_validation_facturx = e.details or [str(e)]
facture.save()
raise ValueError(f"Facture non conforme : {e}")
Ce qui se passe en coulisses :
- L'API valide les données selon 400+ règles Schematron
- L'API enrichit automatiquement depuis les bases officielles (Chorus Pro, INSEE)
- L'API génère le XML CII conforme EN 16931
- L'API convertit en PDF/A-3 avec XML embarqué
- L'API soumet au PDP et retourne le Flow ID
- Le SDK poll automatiquement jusqu'à complétion (si async)
Bilan : 3 jours au lieu de 3 mois
| Métrique | Sans API | Avec FactPulse |
|---|---|---|
| Temps d'intégration | 3-6 mois | 3 jours |
| Lignes de code | ~5 000 (XML, validation) | ~100 (mapping métier) |
| Maintenance des normes | Continue | Déléguée |
| Risque de rejet plateforme | Élevé | Quasi nul |
Ce que l'équipe a retenu
- Un seul appel API — Génération, validation et soumission en une opération
- Format simplifié — SIRET + IBAN suffisent, l'API enrichit automatiquement
- Validation synchrone — Les erreurs sont détectées immédiatement, pas 48h plus tard par la plateforme
- Traçabilité native — Chaque échange est journalisé (erreurs, accusés de réception, Flow ID)
- Code maintenable — Du Python idiomatique, pas de manipulation XML
Prêt à intégrer ?
FactPulse propose un sandbox gratuit pour tester l'intégration avec vos propres données. Générez vos premières factures Factur-X en quelques minutes.
→ Essayer gratuitement le sandbox | Documentation API (Scalar)
Pour aller plus loin
- Comment devenir une Solution Compatible — Guide complet basé sur les sources officielles
- Solutions Compatibles 2026 : Enjeux et Opportunités — Analyse approfondie de la réforme et de la norme AFNOR XP Z12-013
- Guide PME : Se préparer à 2026 — Guide pratique pour les PME
Article mis à jour le 18 janvier 2026
Sources : DGFiP (impots.gouv.fr), AFNOR (normes XP Z12-012/013/014), FNFE-MPE (factur-x.org)