Retour au blog
Développeurs 12 min de lecture

Architecture d'intégration idéale : 5 scénarios

Une intégration de facturation électronique se juge sur l'ordre des opérations, pas sur le nombre d'endpoints appelés. La TVA et le montant à encaisser doivent être arrêtés avant qu'un centime soit prélevé ; la facture doit naître dans l'état où elle est vraiment, réglée ou non ; la transmission à la Plateforme Agréée et le e-reporting suivent, sans que votre code ait à en décider. Cet article décrit l'architecture qui respecte cet ordre, puis la déroule sur cinq scénarios courants avec les appels API dans l'ordre exact.

Architecture d'intégration : votre application appelle l'API Facturino et reçoit ses webhooks ; Facturino prend la décision fiscale, émet la facture avec son original Factur-X, tient le grand livre d'encaissement, dépose la facture sur votre Plateforme Agréée qui la route par l'annuaire vers la plateforme du client, et déclare les obligations de e-reporting à la DGFiP
Votre application encaisse comme elle veut ; Facturino décide, émet, transmet et déclare.

Trois principes qui structurent tout le reste

1. La décision fiscale précède l'encaissement

POST /v1/tax-decisions reçoit l'opération commerciale, client, lignes, date d'effet, mode de prix, et renvoie une décision immuable : la TVA ligne par ligne, le montant exact à encaisser (amountToCharge), le canal de facturation (invoiceChannel) et les obligations de e-reporting. Votre code ne recalcule jamais la TVA. Une clé d'idempotence métier est obligatoire sur cette ressource : la même clé avec le même corps renvoie la même décision, la même clé avec un corps différent est refusée.

2. La facture naît dans son vrai état

POST /v1/invoices crée un brouillon adossé à la décision (taxDecisionId et decisionLines) ; POST /v1/invoices/{id}/finalize attribue le numéro et fige l'original Factur-X. Si l'encaissement est déjà connu, la finalisation le porte dans son corps payment : numérotation et encaissement sont appliqués dans la même transaction, et l'original est rendu sur une facture réglée. Si l'encaissement viendra plus tard, POST /v1/invoices/{id}/payments l'enregistrera, et la copie PDF de présentation suivra.

3. Trois axes de statut, indépendants

Une facture porte trois statuts qui ne se mélangent pas : documentStatus (brouillon, finalisée…), transmissionStatus (dépôt, transmission, réception, approbation ou refus par la plateforme du client, ou not_applicable hors canal e-invoicing) et paymentStatus (impayée, partiellement payée, payée). Une facture réglée peut encore être en cours de transmission ; une facture approuvée peut être impayée. Vos écrans et vos règles métier lisent l'axe qui les concerne.

Quatre étapes en chevrons : décider avec POST /v1/tax-decisions, encaisser par le moyen de son choix avec l'identifiant de décision en référence, vérifier en relisant la décision que le montant reçu est le montant décidé, puis émettre acquittée par la finalisation avec un corps payment ; résultat : une seule transaction, original Factur-X réglé, paymentStatus paid, dates.paidAt
La séquence de référence : décider, encaisser, vérifier, émettre acquittée.

Scénario 1 : abonnement SaaS payé avant la facture

Le cas le plus fréquent en ligne : le client règle au moment de la commande, la facture est produite ensuite. Le montant débité doit être celui de la décision, et la facture doit sortir « PAYÉE » dès l'émission.

  1. Décider. POST /v1/tax-decisions avec la ligne d'abonnement, la catégorie de service et la date d'effet. La décision renvoie amountToCharge.
  2. Encaisser. Prélevez exactement ce montant, par votre prestataire ou par virement, en plaçant l'identifiant de décision dans la référence du paiement.
  3. Vérifier. GET /v1/tax-decisions/{id} : la décision est finale, non expirée, et le montant reçu correspond.
  4. Créer puis émettre acquittée. POST /v1/invoices adossée à la décision, puis POST /v1/invoices/{id}/finalize avec { payment: { amount, method, reference, paidAt } }.
  5. Transmettre. POST /v1/invoices/{id}/send seulement si invoiceChannel vaut einvoicing ; hors de ce canal, l'obligation éventuelle passe par le e-reporting, sans action de votre part.
const decision = await facturino.taxDecisions.create({
  customerId: customer.id,
  effectiveAt: '2026-09-15',
  currency: 'eur',
  priceMode: 'tax_exclusive',
  lines: [{ reference: 'abo-pro', description: 'Abonnement Pro',
            category: 'electronically_supplied_services',
            rateCategory: 'standard', unitAmount: 2900, quantity: '1' }],
}, { idempotencyKey: `order-${order.id}` });

// … encaissement de decision.amountToCharge, référence = decision.id …

const draft = await facturino.invoices.create({
  customerId: customer.id,
  taxDecisionId: decision.id,
  decisionLines: [{ taxLineRef: 'abo-pro', unit: 'month' }],
}, { idempotencyKey: `invoice-${order.id}` });

const invoice = await facturino.invoices.finalize(draft.id, {
  payment: { amount: decision.amountToCharge, method: 'card',
             reference: decision.id, paidAt: '2026-09-15' },
}, { idempotencyKey: `finalize-${order.id}` });
// invoice.paymentStatus === 'paid', invoice.dates.paidAt === '2026-09-15'

Scénario 2 : prestation avec acompte, puis solde

Un acompte n'est déductible du solde que s'il a été encaissé : une facture d'acompte simplement émise a été facturée, pas payée. L'ordre est donc le point.

  1. Décider l'acompte avec une ligne de catégorie deposit qui nomme la prestation principale qu'elle précède.
  2. Émettre l'acompte acquitté : brouillon de type deposit (facture 386), puis finalisation avec le paiement intégral du montant décidé. L'acompte n'existe jamais impayé.
  3. Décider puis émettre le solde en déduisant l'acompte réglé (BT-113) et, si besoin, un échéancier ; le serveur valide la déduction et l'échéancier contre le montant restant dû.
  4. Encaisser le solde à l'échéance : POST /v1/invoices/{id}/payments fait passer paymentStatus à paid et pose dates.paidAt.

Scénario 3 : facture à échéance, encaissement postérieur

Le client paie à trente jours. La facture est émise impayée, transmise, puis réglée plus tard. Ici, ce sont les webhooks qui portent l'intégration.

  1. Décider, créer, finaliser sans corps : la facture est émise « À RÉGLER », son original Factur-X est figé à cet état, ce qui est exact.
  2. Transmettre sur le canal décidé ; suivez invoice.deposited, invoice.transmitted, invoice.received, invoice.approved ou invoice.refused.
  3. Encaisser quand le virement arrive : POST /v1/invoices/{id}/payments. Vous recevez payment.created puis invoice.paid ou invoice.partially_paid ; invoice.overdue signale un retard.
  4. Servir le document à jour : après un encaissement, GET /v1/invoices/{id}/pdf répond 202 avec un job de rendu tant que la copie n'est pas redessinée, puis 200 avec l'URL. Le Factur-X, lui, ne change jamais.

Les webhooks sont livrés au moins une fois : dédupliquez par identifiant d'événement, et traitez payment.created comme le déclencheur de vos écritures comptables, jamais la réponse HTTP d'un appel.

Scénario 4 : vente à un particulier dans l'Union européenne

Un service vendu à un particulier établi dans un autre État membre relève de la TVA du pays de consommation au-delà du seuil annuel, ou du régime OSS si vous y avez opté. La décision fiscale règle la question, à condition de lui donner les preuves de localisation.

  1. Décider avec les preuves : nature du client (particulier), pays déclaré, code postal, et les indices de localisation disponibles (adresse de facturation, pays de l'adresse IP, pays de la banque). Une preuve résolue au niveau du pays est acceptée sans code postal.
  2. Lire la décision : la TVA appliquée, euB2cDestination, et la part du seuil annuel consommée par l'opération dans le registre GET /v1/eu-threshold-ledgers/{year}.
  3. Encaisser et émettre acquittée comme au scénario 1. Si le registre de l'année est en revue, la décision est refusée avec une raison explicite plutôt que de sous-estimer le seuil.

Scénario 5 : recevoir les factures de vos fournisseurs

La réception est obligatoire pour toutes les entreprises depuis le 1er septembre 2026. Avec une Plateforme Agréée connectée, les factures reçues arrivent dans Facturino sans développement de votre part ; votre intégration décide ensuite.

  1. Recevoir : invoice.incoming.received vous notifie ; GET /v1/received-invoices/{id} donne le document, son Factur-X et son historique.
  2. Décider du sort : POST /v1/received-invoices/{id}/approve, /refuse ou /suspend. Les statuts du cycle de vie remontent à la plateforme de l'émetteur.
  3. Enregistrer le règlement : POST /v1/received-invoices/{id}/record-payment quand vous avez payé, pour un e-reporting des paiements exact quand il vous incombe.

Ce que cette architecture évite

Erreur fréquente Ce qui la remplace
Recalculer la TVA dans l'application, puis découvrir un écart à la facture Une décision fiscale prise avant l'encaissement, immuable, rejouable par clé d'idempotence
Finaliser puis enregistrer le paiement une seconde plus tard, et rendre un original « À RÉGLER » sur une facture payée La finalisation avec payment, une seule transaction
Déduire un acompte facturé mais non encaissé L'acompte émis acquitté, puis déduit comme prépayé
Appeler send sur toute facture Le canal décidé : send seulement si invoiceChannel vaut einvoicing
Considérer un webhook comme livré une seule fois Déduplication par identifiant d'événement

Pour aller plus loin

Les cinq scénarios sont implémentés, dans le même ordre, dans les démos publiques Node.js, Go, Python, PHP et HTTP sans SDK, avec une trame partagée qui les décrit étape par étape. La référence des ressources citées est dans la documentation des factures, celle des décisions fiscales et celle des webhooks. L'article suivant détaille le premier scénario : émettre acquittée une facture encaissée d'avance.

Facturino : l'API qui respecte l'ordre

Décision fiscale immuable, facture émise dans son vrai état, transmission par la Plateforme Agréée de votre choix, e-reporting déclaré sans code de votre part. Le démarrage rapide vous fait émettre une première facture en sandbox en quelques minutes, sans carte bancaire.

Prêt à passer à la facturation électronique ?

Créez votre compte Facturino gratuitement et commencez à émettre des factures conformes en quelques minutes.