Aller au contenu
Log in

DGFiP e-Invoicing et e-Reporting

Guide pour intégrer l'API de B2Brouter et te conformer à la RFE depuis ton propre système.

À partir de septembre 2026, toutes les entreprises françaises doivent faire transiter leurs factures et leurs données de TVA par une plateforme certifiée. B2Brouter simplifie cela : tu envoies tes données de facture via un appel REST API, et B2Brouter gère l’enregistrement au PPF, la génération de documents (UBL/CII/Factur-X), le routage vers tes clients, et le rapport fiscal à la DGFiP, le tout via une seule intégration.

B2Brouter est une Plateforme Agréée (PA) certifiée pour la réforme française de facturation électronique DGFiP. Connecte-toi via REST API et B2Brouter gère l’ensemble de la conformité pour toi :

Ce que B2Brouter fait pour toiDétails
Enregistrement PPFPublie ton SIREN/SIRET dans l’Annuaire automatiquement lors de l’activation
Flux 1 : facturation électronique B2BGénère UBL/CII/Factur-X, transmet au PPF, route vers la plateforme du destinataire
Flux 6 : cycle de vie de la factureGère les messages de statut CDAR (Déposée, Reçue, Approuvée, Refusée, Encaissée)
Flux 10 : e-ReportingAgrège les transactions B2C et B2B transfrontalières (intra-UE et extra-UE) en Ledgers envoyés au PPF à la fréquence définie par le vat_regime de ton Tax Report Setting
Réception Peppol 0225Reçoit les factures depuis n’importe quelle plateforme française ou connectée à Peppol
Génération de documentsTu envoies les données de facture en JSON, B2Brouter génère le document UBL/CII/Factur-X conforme et le transmet au PPF. Aucune génération XML requise de ton côté
Formats d’entréeJSON REST API, Factur-X PDF/A-3 (avec XML CII intégré), UBL 2.1 XML, CII XML
Archivage légalTous les documents transmis (factures, rapports fiscaux, messages CDAR) sont conservés par B2Brouter pendant la période légale de conservation de 10 ans. Aucune configuration de stockage supplémentaire requise de ton côté

Le chemin jusqu’à ta première facture : créer ton compte → activer la DGFiP → créer un contact → envoyer ta première facture.


Contexte réglementaire : La réforme française de facturation électronique impose que toutes les entreprises françaises utilisent une Plateforme Agréée (PA) certifiée ou le PPF (Portail Public de Facturation) de l’État pour transmettre les factures et déclarer les données de TVA à la DGFiP, à partir de septembre 2026. En tant que PA certifiée, B2Brouter gère entièrement la connexion au PPF pour toi : pas de SFTP, pas de certificats électroniques, pas d’intégration directe au PPF requise.

Il existe deux cas d’usage principaux pour intégrer B2Brouter à la facturation électronique française :

eDocExchange : Pour les entreprises ou groupes d’entreprises qui intègrent leur logiciel de gestion (ERP, plateforme comptable) directement avec B2Brouter. Le processus d’onboarding (création du compte, configuration des Tax Report Settings) s’effectue généralement une fois par entreprise via l’interface web. Les opérations quotidiennes (émission de factures, suivi de leur cycle de vie) se font via l’API. Pour ajouter d’autres comptes d’entreprise à ton groupe d’intégration, suis le même assistant d’onboarding depuis le même compte utilisateur B2Brouter ; aucun appel API distinct n’est requis.

eDocSync : Pour les éditeurs de logiciels et fournisseurs d’ERP qui souhaitent offrir la conformité DGFiP à leurs propres clients depuis leur produit. C’est le modèle marque blanche / intégré de B2Brouter : B2Brouter opère entièrement en arrière-plan, les clients finaux interagissent exclusivement avec l’interface de l’éditeur et ignorent l’existence de B2Brouter. L’éditeur du logiciel est responsable de la création des comptes, de la soumission des factures et du suivi du cycle de vie via l’API B2Brouter. Les clients finaux n’ont besoin ni d’identifiant B2Brouter ni d’abonnement.

Pour eDocSync, le volume de provisionnement de comptes détermine le bon plan :

  • Peu d’entreprises (modèle revendeur) : ajoute chaque entreprise cliente comme compte dans ton groupe d’intégration B2Brouter via l’interface web, en suivant l’assistant d’onboarding standard. Cela fonctionne bien pour des dizaines d’entreprises et partage une seule clé API.
  • 100+ entreprises : contacte notre équipe commerciale ou ouvre un ticket de support pour discuter d’un plan eDocSync dédié avec provisionnement en masse (tarification au volume pour les éditeurs).

Dans les deux cas, toutes les fonctionnalités de conformité spécifiques à la France (enregistrement à l’Annuaire, transmission Flux 1/6/10, cycle de vie CDAR) fonctionnent de manière identique.

B2Brouter est elle-même une Plateforme Agréée : tu t’intègres avec B2Brouter ; ce n’est ni un relais ni un connecteur vers une autre PA. Si ton SIREN est actuellement enregistré auprès d’une autre PA, activer le Tax Report Setting sur le compte SIREN échoue : il te faut un code de migration (voir Changer de PA). Pour n’intégrer qu’un seul établissement tout en conservant cet enregistrement existant, consulte le scénario 2 dans Structure du compte. Tu ne peux pas utiliser B2Brouter comme simple passerelle pour soumettre des factures sous la certification d’une autre PA.

Routage vers des destinataires sur d’autres PA : quand ton destinataire est enregistré auprès d’une autre PA, B2Brouter route la facture via le modèle Peppol standard à quatre coins (C2 → C3) : le point d’accès Peppol de B2Brouter (C2) recherche l’adresse Peppol du destinataire dans l’Annuaire et livre le document au point d’accès de l’acheteur (C3), quelle que soit la PA qu’il utilise. Aucune configuration supplémentaire n’est requise de ton côté.


Environnements de test : utilise le sandbox pour les premiers tests API et la validation des payloads. En sandbox, les écritures à l’Annuaire de la DGFiP sont simulées : activer un Tax Report Setting n’enregistre rien au PPF, tu n’as donc pas besoin d’identifiants enregistrés au PPF. Le SIREN et le SIRET doivent néanmoins passer leur clé de contrôle, car le sandbox tourne dans l’environnement de production. Seul staging accepte n’importe quel numéro à 9 ou 14 chiffres. Pour des tests de bout en bout complets avec l’environnement DGFiP QAS (qualification), utilise l’environnement staging de B2Brouter comme décrit ci-dessous.

Première fois avec l’API ? Commence par l’introduction à l’API : environnements, clé d’API et première requête.

EnvironnementApplication B2BrouterAPI B2BrouterPortail Chorus Pro
Productionapp.b2brouter.nethttps://api.b2brouter.netchorus-pro.gouv.fr
Staging (test)app-staging.b2brouter.nethttps://api-staging.b2brouter.netqualif.chorus-pro.gouv.fr

Ne mélange pas les environnements. La production utilise de vrais numéros SIREN/SIRET et se connecte à l’Annuaire de production de la DGFiP. Le staging utilise des identifiants de test fictifs et se connecte à l’environnement DGFiP QAS (qualification). Les clés API, comptes et contacts ne sont pas partagés entre environnements.

Inscris-toi sur app.b2brouter.net pour démarrer une intégration en production. Quand tu actives le Tax Report Setting DGFiP, le SIREN/SIRET de ton entreprise est publié dans l’Annuaire PPF réel, le rendant identifiable par toute plateforme de l’écosystème français de facturation électronique.

Cette option est conçue pour les vraies factures B2B à partir de septembre 2026. En attendant, la DGFiP purgera les enregistrements de la période QAS avant l’entrée en vigueur de la réforme, donc les factures que tu envoies pendant ton pilote ne créeront aucune obligation de conformité. C’est le bon point de départ si tu as déjà choisi B2Brouter et veux tester l’intégration complète avec les vraies données de ton entreprise.

Option B : Staging (recommandé pour l’évaluation)

Section intitulée « Option B : Staging (recommandé pour l’évaluation) »

Inscris-toi sur app-staging.b2brouter.net pour utiliser l’environnement de test de B2Brouter, connecté à l’environnement QAS (qualification) de la DGFiP.

C’est la meilleure option si :

  • Tu évalues plusieurs plateformes avant de t’engager
  • Ton SIREN/SIRET est déjà publié dans l’Annuaire auprès d’une autre PA et tu ne veux pas encore changer de PA
  • Tu préfères ne pas associer l’identifiant de ton entreprise à une activité de test

L’environnement staging est auto-provisionné : une fois que tu as des identifiants de test (voir ci-dessous), tu peux démarrer des tests de bout en bout en moins de 24 heures.

Validation des SIRET en staging : dans l’environnement staging, tout numéro valide à 14 chiffres est accepté comme SIRET sans validation de clé de contrôle. Les identifiants fictifs du CSV Chorus Pro QAS sont préenregistrés dans l’annuaire DGFiP QAS et fonctionnent de bout en bout. En production, le format et la clé de contrôle du SIRET sont validés.

Important : la DGFiP n’autorise pas les numéros SIREN ou SIRET réels dans son environnement QAS. Tu dois utiliser des identifiants de test fictifs. Tu peux les obtenir toi-même via le portail Chorus Pro QAS (gratuit, 5 minutes) ou demander un jeu préassigné en ouvrant un ticket de support dans l’application staging.

Un compte par SIREN : B2Brouter crée un compte par SIREN (la clé du numéro de TVA est dérivée du SIREN). Si tu fournis un SIRET, le SIREN en est extrait. Deux SIRET différents de la même entreprise (même SIREN) résoudront vers le même compte. Si ton entreprise opère depuis plusieurs établissements (SIRET différents), ceux-ci sont modélisés comme des unités organisationnelles au sein du même compte B2Brouter, pas comme des comptes séparés. Contacte le Support si tu as besoin de configurer une facturation multi-établissements. Garde cela à l’esprit lors de la sélection des lignes du CSV : choisis des SIRET avec des SIREN distincts (9 premiers chiffres) pour chaque entreprise indépendante que tu dois tester.

Obtenir des identifiants de test via Chorus Pro QAS

Section intitulée « Obtenir des identifiants de test via Chorus Pro QAS »

Le portail Chorus Pro QAS te permet de générer un « Matelas de données » (jeu de données), un fichier CSV contenant des identifiants SIREN/SIRET fictifs préenregistrés dans l’environnement de test de la DGFiP. Suis ces étapes :

  1. Va sur qualif.chorus-pro.gouv.fr → onglet Entreprise → Créer mon compte.
    • Tu peux utiliser une adresse e-mail temporaire (par exemple temp-mail.io).
    • Utilise n’importe quel nom ; ce compte sert uniquement à obtenir des identifiants de test.
  2. Vérifie ta boîte de réception pour l’e-mail « Initialisation de mot de passe Chorus Pro » et définis ton mot de passe (lien valide 60 minutes).
  3. Connecte-toi → va dans Domaines → Matelas de données → clique sur Générer un matelas de données et confirme.
  4. Va dans Consultation du matelas de données. Attends que les deux statuts affichent « Disponible » :
    • Statut pour Chorus Pro : Disponible
    • Statut pour l’annuaire de facturation PPF : Disponible
    • La génération prend généralement quelques minutes. Actualise la page pour vérifier.
  5. Clique sur « Générer et télécharger le fichier CSV du matelas structures et utilisateurs » pour télécharger tes identifiants de test.

Le CSV contient plusieurs numéros SIREN/SIRET fictifs dans des lignes étiquetées « Privé » et « Public ». Utilise uniquement les lignes de la section « Privé » (secteur privé) pour tes comptes de test. Les entités du secteur public (SIREN 'Public') sont rejetées par l’annuaire DGFiP QAS : tenter d’activer l’e-Reporting sur un compte du secteur public renvoie une erreur HTTP 422 (« La création d’une ligne annuaire n’est pas possible pour une entité associée à un SIREN ‘Public’ »). C’est le comportement attendu : les entités publiques utilisent directement Chorus Pro, pas une PA.

Utilise un SIREN du secteur privé pour ton compte émetteur et un autre pour ton contact de test.

Une fois que tu as tes identifiants de test :

  1. Inscris-toi sur app-staging.b2brouter.net et active ton compte.
  2. Crée le compte de ton entreprise en utilisant un SIREN du CSV (voir Créer le compte de ton entreprise).
  3. Souscris à un plan eDocExchange (les abonnements staging sont simulés, aucun frais).
  4. Active les paramètres de rapport fiscal DGFiP (voir Activer le Tax Report Setting).
    • ⚠️ L’enregistrement de ton entreprise à l’Annuaire n’est pas immédiat : la publication part avec l’envoi nocturne et est active le lendemain matin, aussi bien en staging qu’en production. C’est le fonctionnement de l’infrastructure DGFiP, pas un délai de B2Brouter. D’ici là, tu ne pourras pas envoyer de factures.
  5. Le lendemain : crée un contact de test en utilisant un second SIREN du CSV (voir Créer un contact).
  6. Envoie ta première facture (voir Émettre des factures).

L’authentification utilise une clé API statique passée dans l’en-tête HTTP X-B2B-API-Key. Il n’y a pas de flux OAuth2 : génère ta clé API dans l’interface B2Brouter sous Paramètres → Clés API. Garde-la confidentielle et ne l’inclus jamais dans du code côté client. Définis aussi X-B2B-API-Version dans chaque requête.

URL de base : tous les exemples ci-dessous utilisent https://api-staging.b2brouter.net. Pour la production, remplace par https://api.b2brouter.net.


Structure du compte : parent et unités organisationnelles

Section intitulée « Structure du compte : parent et unités organisationnelles »

En France, chaque entreprise a un SIREN à 9 chiffres qui l’identifie comme entité légale, et chaque établissement ou service a un SIRET à 14 chiffres dérivé de ce SIREN. B2Brouter suit la même hiérarchie, avec un compte parent et, sous lui, une unité organisationnelle (UO) pour chaque établissement ou service. Les factures sont émises depuis le compte parent ou depuis une UO spécifique, selon l’établissement émetteur.

Pays couverts par ce guide. Les règles de compte de ce guide (parent et UO, identifiants, Tax Report Setting) s’appliquent aux entreprises établies dans le territoire de TVA français : la France (fr) et les DROM Guadeloupe (gp), Martinique (mq) et La Réunion (re). Pour un émetteur établi dans un autre territoire d’outre-mer (Guyane, Mayotte, Polynésie française, Nouvelle-Calédonie, Saint-Pierre-et-Miquelon…), ce guide n’établit pas la configuration du compte : contacte le support avant de créer le compte.

Le compte parent est toujours un SIREN. Tout SIRET, Code Routage ou Suffix (voir Identifiants et schémas) est toujours modélisé comme une UO sous ce parent, jamais comme un compte indépendant : c’est ce qui garde cohérents les identifiants publiés du parent et de ses UO.

Si tu crées un compte avec un SIRET, B2Brouter ne le rejette pas : il dérive le SIREN des 9 premiers chiffres, crée le compte parent s’il n’existe pas encore et y rattache le SIRET comme UO. Ce que l’appel te renvoie, c’est l’UO. Convertir un parent existant en SIRET avec un PUT renvoie bien 422 parameter_matriu_must_be_siren.

Chaque UO a son propre Tax Report Setting. Une UO ne déclare jamais à travers le compte parent : si elle n’a pas son propre Tax Report Setting activé, elle ne déclare pas. Cela dit, quand tu crées une UO sous un parent qui a déjà la DGFiP active, B2Brouter lui clone un Tax Report Setting propre pour qu’elle commence à déclarer sans étapes supplémentaires. Si tu ne veux pas qu’elle déclare, désactive-le (enabled: false) une fois créée. Consulte Scénarios et cas pour choisir ta configuration.

La règle d’or vaut aussi pour les contacts. Les contacts français (clients et fournisseurs) suivent la même hiérarchie et les mêmes cin_scheme : le contact parent est toujours le SIREN, et tout SIRET, Code Routage ou Suffix est une UO. Le système accepte techniquement un contact parent avec un identifiant autre que le SIREN, mais cela casse les UO que tu ajouteras ensuite pour le même client. Pour les créer, voir Créer un contact.

Dans B2Brouter, les comptes, les unités organisationnelles et les contacts français sont définis par un identifiant principal (cin_scheme + cin_value). Les UO avec SIRET qui ont plusieurs services internes y ajoutent un sous-identifiant (routing_codes.cin1_scheme + routing_codes.cin1_value) pour adresser un service spécifique. Ce sont deux choses différentes : le Suffix est un cin_scheme principal, tandis que le Code Routage va toujours dans le sous-identifiant et jamais comme cin_scheme principal.

Identifiant principal du compte, de l’UO ou du contact (cin_scheme + cin_value) :

cin_schemecin_valueCe que cela représenteExemple
0002 (2)SIREN, 9 chiffres + LuhnEntité légale842917361
0009 (9)SIRET, 14 chiffres (SIREN + 5 chiffres), avec deux contrôles Luhn : l’un sur les 14 chiffres, l’autre sur le SIREN initialÉtablissement84291736100011
8040Suffix, alphanumérique [A-Za-z0-9_\-\/]+UO sans SIRET propreSUF01, ADMIN

La validation du SIREN et du SIRET est uniquement arithmétique : B2Brouter ne consulte ni le répertoire Sirene ni aucun autre registre. Un numéro inventé qui passe le contrôle est accepté, et il peut coïncider avec celui d’une entreprise réelle. Pour construire une paire de test :

  1. Choisis 8 chiffres et ajoute la clé de contrôle Luhn : tu obtiens le SIREN.
  2. Ajoute 4 chiffres d’établissement et la clé de contrôle Luhn calculée sur ces 13 chiffres : tu obtiens le SIRET.

Tous les SIREN et SIRET de cette page passent les deux contrôles, par exemple 842917361 et 84291736100011.

Sous-identifiant ou routing code (routing_codes.cin1_scheme + routing_codes.cin1_value) :

routing_codes.cin1_schemerouting_codes.cin1_valueCe que cela représenteExemple
0224 (224)Code Routage, alphanumérique [A-Za-z0-9_\-\/]+ (minimum 1 caractère)Service au sein d’un SIRETCOMPTA, SERV01, A123

Sur le réseau Peppol, en revanche, le participant français est toujours identifié par le schéma 0225 (FRCTC Electronic Address), le code réservé aux adresses électroniques françaises. Sa valeur est toujours une composition publiée à l’Annuaire, jamais un identifiant seul : un SIRET sans le SIREN devant n’est pas publiable. Les schemes 0224 et 8040 ne sont pas des schémas Peppol : ils servent uniquement à composer cette valeur.

Identifiant du participant Peppol (pin_scheme + pin_value) :

pin_schemepin_valueCe que cela représente
0225SIRENEntité entière (parent)
0225SIREN_SIRETÉtablissement
0225SIREN_SIRET_<CR>Service au sein d’un établissement
0225SIREN_<SUFFIX>UO sans SIRET propre

Chaque composition correspond à un ou deux des cas du Tableau des cas. Pour voir les champs API qui la produisent, consulte Ajouter les établissements comme unités organisationnelles.


B2Brouter couvre trois scénarios de configuration. Celui qui te correspond dépend de ce que tu veux faire depuis B2Brouter. Si tu ne sais pas si ton SIREN est déjà enregistré auprès d’une autre PA, vérifie-le à l’Annuaire avec la recherche dans l’annuaire.

Veux-tu que le SIREN déclare depuis B2Brouter ?

RéponseScénarioCe que tu dois faire
OuiScénario 1.
Toute l’entreprise déclare
Active le Tax Report Setting sur le compte parent SIREN. Les établissements, services et unités internes sont modélisés avec les cas 1, 2 et 3. Si le SIREN est déjà enregistré auprès d’une autre PA, tu dois d’abord le migrer vers B2Brouter avec un code de migration (voir Migrer depuis une autre PA ou vers une autre).
Non, je veux déclarer un établissement précis depuis B2BrouterScénario 2.
Un seul établissement déclare
Crée l’établissement comme UO avec le SIRET et active le Tax Report Setting uniquement sur cette UO, pas sur le compte parent SIREN. L’enregistrement du SIREN auprès de l’autre PA n’est pas modifié. Cas 4 et 5.
Non, je veux uniquement émettre depuis B2BrouterScénario 3.
Émets depuis B2Brouter, reçois chez ta PA
⚠️ Disponible uniquement sur une UO de Suffix : crée-la sous le SIREN et active son Tax Report Setting avec issue_only: true. La réception reste chez l’autre PA. Cas 6, voir Modes du Tax Report Setting.
CasUnité organisationnelle (UO)Tax Report SettingAdressage Annuaire (pin_value)Quand en as-tu besoin
1. Établissement
Scénario 1
SIRETParent :ON
UO :ON1
SIREN_SIRETTu as des établissements et ils déclarent tous depuis l’entreprise.
2. Service
Scénario 1
SIRET + Code RoutageParent :ON
UO :ON1
SIREN_SIRET_<CR>Tu veux adresser un département précis au sein d’un établissement.
3. Suffix
Scénario 1
SuffixParent :ON
UO :ON1
SIREN_<SUFFIX>Tu as une unité sans SIRET propre qui doit recevoir et déclarer avec sa propre adresse.
4. Établissement-only
Scénario 2
SIRETParent :OFF
UO :ON
SIREN_SIRETLe SIREN est déjà enregistré auprès d’une autre PA et tu n’amènes qu’un établissement chez B2Brouter.
5. Établissement-only + Service
Scénario 2
SIRET + Code RoutageParent :OFF
UO :ON
SIREN_SIRET_<CR>Comme le cas 4, mais en adressant un département au sein de cet établissement.
6. Issue-only
Scénario 3
Suffix avec issue_only2Parent :OFF
UO :ON
SIREN_<SUFFIX>Tu veux émettre depuis B2Brouter tout en gardant la réception chez ta PA actuelle.

1 Quand tu crées une UO sous un parent qui a déjà la DGFiP active, B2Brouter lui clone un Tax Report Setting propre. Voir La règle d’or.

2 Une UO de Suffix publie un transport 0225 et reçoit des factures comme n’importe quelle autre adresse (cas 3). Ce qui lui retire la réception, c’est le flag issue_only de son Tax Report Setting, qui n’est accepté que sur une UO de Suffix (voir Modes du Tax Report Setting).


Cette section explique comment créer le compte parent avec le SIREN et comment y ajouter les unités organisationnelles. Le modèle sous-jacent est dans Structure du compte.

Crée le compte avec POST /accounts. S’il existe déjà, récupère son id avec GET /accounts et saute la création.

ChampValeurFinalité
country"fr"Active les validations et le routage FR
cin_scheme"0002"SIREN, l’entité légale. Le parent est toujours un SIREN : voir La règle d’or pour ce qui se passe si tu envoies un SIRET
cin_valueSIREN à 9 chiffresIdentifiant de l’entreprise, validé par Luhn
tin_scheme9957Code ISO 6523 de l’identifiant fiscal français
tin_valueFR{kk}{siren}Numéro de TVA qui apparaît dans l’UBL. Tu n’as pas à calculer la clé kk

Exemple de requête :

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"account": {
"country": "fr",
"name": "Exemplar SAS",
"address": "10 Rue Imaginaire",
"city": "Paris",
"postalcode": "75001",
"province": "Île-de-France",
"email": "john.doe@example.com",
"tin_value": "FR22842917361",
"tin_scheme": 9957,
"cin_scheme": "0002",
"cin_value": "842917361",
"rounding_method": "half_up"
}
}'

Exemple de réponse :

{
"account": {
"id": 83428,
"name": "Exemplar SAS",
"tin_value": "FR22842917361",
"tin_scheme": 9957,
"cin_scheme": "0002",
"cin_value": "842917361",
"address": "10 Rue Imaginaire",
"city": "Paris",
"postalcode": "75001",
"province": "Île-de-France",
"country": "fr",
"currency": "EUR",
"email": "john.doe@example.com",
"rounding_method": "half_up",
"created_at": "2026-06-10T09:54:38.000Z",
"updated_at": "2026-06-10T09:54:38.000Z"
}
}

Ajouter les établissements comme unités organisationnelles (facultatif)

Section intitulée « Ajouter les établissements comme unités organisationnelles (facultatif) »

Si la structure de ton entreprise nécessite des UO (voir le tableau des cas), crée chaque UO avec POST /accounts en ajoutant parent_id (l’id du compte parent créé précédemment).

Si le compte parent a déjà le Tax Report Setting DGFiP actif, la nouvelle UO en reçoit une copie propre et commence à déclarer aussitôt. Si tu ne veux pas qu’elle déclare, désactive son Tax Report Setting (enabled: false) une fois créée (voir La règle d’or).

  • Une UO ne peut pas porter tin_value ni tin_scheme : elle les hérite du parent et ils ne doivent pas être répétés.
  • Une UO ne peut pas être le parent d’une autre UO : il n’y a qu’un seul niveau de profondeur.
ChampValeurFinalité
parent_idId du compte parentRattache l’UO au parent SIREN : c’est ce qui en fait une UO
cin_scheme et cin_valueSelon le type d’UOIdentifiant propre de l’UO ; voir Champs de création et résultat à l’Annuaire. Un SIRET commence toujours par les 9 chiffres du SIREN parent, par définition de l’INSEE : si le parent est 842917361, les SIRET valides ont la forme 842917361XXXXX
country"fr"Active les validations et le routage FR
email, address, city, postalcode, provinceCoordonnées et adresse de l’UOObligatoires sur n’importe quel compte, y compris les UO

Sans ces champs, la création renvoie HTTP 422 ("Region/Province/Country can't be blank").

Type d’UOChamps à envoyer à POST /accountsRésultat à l’Annuaire
Établissement
(cas 1 et 4)
parent_id (parent SIREN) + cin_scheme="0009" + cin_value=<SIRET>SIREN_SIRET
Service
(cas 2 et 5)
parent_id (parent SIREN) + cin_scheme="0009" + cin_value=<SIRET> + routing_codes.cin1_scheme="224" + routing_codes.cin1_value=<CR>SIREN_SIRET_<CR>
Suffix
(cas 3 et 6)
parent_id (parent SIREN) + cin_scheme="8040" + cin_value=<SUFFIX>SIREN_<SUFFIX>

Les cas 4, 5 et 6 : le payload ne les distingue pas de leurs équivalents. Ce qui change, c’est où le Tax Report Setting est activé et, au cas 6, le flag issue_only. Voir Scénarios et cas.

Cas 1 et 2 : UO de type Établissement avec Service facultatif
Section intitulée « Cas 1 et 2 : UO de type Établissement avec Service facultatif »

Pour un établissement sans Code Routage (cas 1), omets le bloc routing_codes.

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"account": {
"name": "Exemplar SAS, Succursale Paris",
"parent_id": {PARENT_ACCOUNT_ID},
"cin_scheme": "0009",
"cin_value": "84291736100011",
"routing_codes": { "cin1_scheme": "224", "cin1_value": "COMPTA" },
"country": "fr",
"email": "succursale-paris@example.com",
"address": "1 Rue de la Paix",
"city": "Paris",
"postalcode": "75001",
"province": "Île-de-France"
}
}'

Le payload du cas 6 (Issue-only) est identique à celui du cas 3 : ce qui les sépare n’est pas le POST /accounts mais le Tax Report Setting que tu actives ensuite, avec issue_only: true. Ce flag n’est accepté que sur une UO avec cin_scheme="8040". Voir Modes du Tax Report Setting.

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"account": {
"name": "Exemplar SAS, Unité Administrative",
"parent_id": {PARENT_ACCOUNT_ID},
"cin_scheme": "8040",
"cin_value": "SUF01",
"country": "fr",
"email": "admin-unit@example.com",
"address": "1 Rue de la Paix",
"city": "Paris",
"postalcode": "75001",
"province": "Île-de-France"
}
}'

C’est l’étape clé de l’onboarding. Quand tu crées un Tax Report Setting avec code: "dgfip", B2Brouter automatiquement :

  1. Enregistre ton entreprise dans l’Annuaire du PPF : ton identifiant devient identifiable par toute plateforme de l’écosystème français de facturation électronique.
  2. Crée un transport Peppol 0225 (FRCTC Electronic Address) : ton entreprise est habilitée à recevoir des factures électroniques depuis toute plateforme connectée à Peppol en France.
    ⚠️ Si le compte sur lequel tu actives dispose déjà d’un transport Peppol, il sera remplacé par le nouveau transport 0225 lors de l’activation.

Identifiant déjà enregistré auprès d’une autre PA : Si le SIREN sur lequel tu actives était précédemment enregistré auprès d’une autre PA, B2Brouter fermera l’entrée Annuaire existante et en ouvrira une nouvelle. Si tu as besoin de conserver cet enregistrement existant, n’active pas sur le SIREN ; active plutôt sur une UO SIRET (voir « Où activer » ci-dessous). Mets à jour toute intégration existante qui référence l’ancien identifiant de transport.

Où activer le Tax Report Setting : {ACCOUNT_ID} peut être le parent SIREN, une UO SIRET, ou les deux. Chaque compte (parent ou UO) qui a son propre Tax Report Setting est publié dans l’Annuaire sous sa propre adresse. Pour les comptes dans le territoire de TVA français (FR, et les DROM GP/MQ/RE), il n’y a pas d’héritage entre UO et parent (voir La règle d’or) : sans son propre Tax Report Setting, l’UO ne déclare pas, et avec un Tax Report Setting propre désactivé, elle ne déclare pas non plus. Trois configurations :

  1. Tax Report Setting uniquement sur le SIREN : l’entreprise est publiée comme SIREN (cas standard, Scénario 1). Les nouvelles UO créées sous ce parent reçoivent automatiquement leur propre Tax Report Setting cloné à la création (voir la note ci-dessous), donc elles déclarent normalement aussi.
  2. Tax Report Setting sur le SIREN et sur une ou plusieurs UO SIRET : l’entreprise est publiée à la fois comme SIREN et comme chaque SIREN_SIRET (une adresse Annuaire par compte activé). Tous les Tax Report Setting DGFiP actifs sous le même SIREN doivent partager le même vat_regime : en activer un avec une valeur différente renvoie 422 dgfip_vat_regime_taken_per_siren.
  3. Tax Report Setting uniquement sur une UO SIRET, pas sur le SIREN : seul cet établissement est publié (SIREN_SIRET) ; le SIREN lui-même ne l’est pas (Scénario 2). Utilise cela quand le SIREN est déjà enregistré auprès d’une autre PA et que tu veux conserver cet enregistrement.

Voir Structure du compte pour le modèle complet.

Si tu crées une UO alors que le parent est déjà actif : B2Brouter crée automatiquement son propre Tax Report Setting DGFiP (avec start_date demain), afin qu’elle commence à déclarer sans étape supplémentaire. Si le parent n’a pas la DGFiP active à ce moment, l’UO est créée sans aucun Tax Report Setting ; quand tu actives le parent plus tard, l’UO reçoit le sien. L’UO ne regarde jamais le paramètre du parent pour décider si elle doit déclarer.

Le start_date détermine quand le rapport fiscal commence. À partir de cette date, les factures que tu émets génèreront des rapports fiscaux et seront transmises au PPF.

Exemple de requête :

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_settings \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"tax_report_setting": {
"code": "dgfip",
"start_date": "2026-10-01",
"type_operation": "services",
"vat_regime": "reel_normal_mensuel",
"naf_code": "62",
"enterprise_size": "eti",
"email": "jane.doe@example.com"
}
}'

Exemple de réponse :

{
"tax_report_setting": {
"code": "dgfip",
"start_date": "2026-10-01",
"auto_generate": true,
"auto_send": true,
"enabled": true,
"type_operation": "services",
"vat_regime": "reel_normal_mensuel",
"naf_code": "62",
"enterprise_size": "eti",
"email": "jane.doe@example.com",
"locked": false,
"created_at": "2026-06-10T10:15:22.000Z",
"updated_at": "2026-06-10T10:15:22.000Z"
}
}
ChampTypeObligatoireDescription
codestringOuiDoit être "dgfip".
start_datedateNonQuand le rapport fiscal commence. Doit être demain ou plus tard : la date du jour est refusée avec 422. Par défaut, demain si omis.
type_operationstringOuiType d’opération par défaut pour cette entreprise : "services", "goods" ou "mixed". Détermine le code de procédure DGFiP (S1/B1, etc.) utilisé dans les rapports fiscaux. Choisis "mixed" si ton entreprise vend à la fois des biens et des services. Sur une facture mixte, le rapport fiscal Flux 1 est émis sous le code de procédure services (S1/S2/S4/S7) et ne déclare que les ventilations de services ; la DGFiP n’a pas de cadre « M » dédié pour le Flux 1 (voir Codes de procédure). Ce paramètre peut être mis à jour après l’activation.
naf_codestringNonFacultatif ; validé seulement s’il est renseigné. Le code NAF/APE de l’entreprise (Nomenclature d’Activités Française). C’est le code section à 2 chiffres attribué par l’INSEE qui identifie l’activité économique principale de l’entreprise (par exemple "62" pour les services informatiques et logiciels, "47" pour le commerce de détail, "86" pour la santé). La DGFiP utilise ce code pour la classification du rapport fiscal. Tu trouveras ton code NAF sur le Kbis de ton entreprise ou sur sirene.fr.
enterprise_sizestringNonFacultatif ; validé seulement s’il est renseigné. La catégorie de taille de l’entreprise telle que définie par l’INSEE. Valeurs autorisées : "micro" (Microentreprise — < 10 salariés, CA ≤ 2 M€), "pme" (PME — 10 à 249 salariés, CA ≤ 50 M€), "eti" (ETI — 250 à 4 999 salariés, CA ≤ 1,5 Md€), ou "ge" (Grande Entreprise — 5 000+ salariés ou CA > 1,5 Md€).
vat_regimestringOui, sauf si annuaire_only=trueLe régime de TVA de l’entreprise. Détermine la fréquence de transmission du Flux 10 (e-Reporting). Sans vat_regime valide, aucune facture déclarable ne peut être transmise : la requête renvoie HTTP 422. Voir le tableau des régimes.
reason_vat_exemptstringNonCode de motif d’exonération de TVA par défaut pour cette entreprise. Par défaut "VATEX-FR-FRANCHISE" (franchise en base de TVA). Définis ce champ si ton entreprise opère sous un régime d’exonération de TVA spécifique. Voir Lignes exonérées de TVA et Franchise en base de TVA pour la liste complète des codes acceptés.
emailstringNonE-mail de contact pour les notifications fiscales.
auto_generatebooleanNonToujours true pour la DGFiP (obligation légale). Ne peut pas être modifié.
auto_sendbooleanNonTransmet automatiquement les rapports fiscaux au PPF. Par défaut true.
enabledbooleanNonIndique si le paramètre est actif. Par défaut true. L’enregistrement à l’Annuaire n’a lieu que si true.
annuaire_onlybooleanNonQuand true, le compte n’est enregistré à l’Annuaire du PPF que pour la réception. Aucun rapport fiscal Flux 1 n’est généré et aucun message CDAR n’est envoyé, et vat_regime n’est pas obligatoire. Par défaut false. Voir Modes du Tax Report Setting.
issue_onlybooleanNonQuand true, B2Brouter émet tes factures et rapports fiscaux tandis que la réception reste chez ta PA actuelle. Accepté uniquement sur une UO Suffix (cin_scheme="8040") : sur tout autre compte, la requête renvoie 422 dgfip_issue_only_suffix_uo_only. Par défaut false. Voir issue_only.
peppol_email_fallbackbooleanNonEnvoie la facture par e-mail au format Factur-X quand le destinataire français est enregistré à l’Annuaire mais confirmé absent de Peppol. Par défaut false : sans cela, l’envoi est bloqué. Voir Émettre des factures.
RégimeDescription
reel_normal_mensuelPar décade (jours 1-10, 11-20, 21-fin de mois) pour les transactions ; mensuel pour les paiements.
reel_normal_trimestrielMensuel.
simplifieMensuel. Date limite d’envoi : le 26 du mois suivant. Régime aboli au 01/01/2027 ; traité comme reel_normal_trimestriel ensuite.
franchise_en_baseBimestriel (bimestres calendaires : jan-fév, mar-avr, mai-juin, juil-août, sep-oct, nov-déc). Date limite d’envoi : le 26 du mois suivant.

Si l’enregistrement à l’Annuaire échoue (SIREN/SIRET invalide, ou panne temporaire du service DGFiP), la création du Tax Report Setting est annulée et une erreur est renvoyée. Corrige le problème et réessaie.

Tax Report Settings - API Reference

Si tu as suivi les étapes précédentes, tu as déjà le mode complet et tu n’as pas besoin de lire la suite de cette section. Les deux autres modes sont des déviations pour des situations précises.

ModeOù vit le Tax Report SettingAnnuaireRéception Peppol 0225Rapports fiscauxRéponses (CDAR)
Complet (par défaut)Parent ou UOouiouiouienvoyées et reçues
annuaire_onlyParent ou UOouiouinonaucune envoyée
issue_onlyUO de Suffix uniquementouinon (reste chez la PA actuelle)ouireçues si tu actives cdar sur le transport

Le transport Peppol en émission seule n’est pas un mode du Tax Report Setting : c’est le véhicule d’émission qui accompagne issue_only et tu le crées à part.

Quand en as-tu besoin : ton entreprise n’est pas encore tenue d’émettre, mais tu veux figurer à l’Annuaire pour que tes fournisseurs puissent t’envoyer des factures.

Il enregistre l’entreprise à l’Annuaire et crée le transport 0225 pour la réception, mais ne génère aucun rapport fiscal et n’envoie aucun message CDAR. Le champ vat_regime n’est pas obligatoire dans ce mode.

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/tax_report_settings \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"tax_report_setting": {
"code": "dgfip",
"start_date": "2026-10-01",
"annuaire_only": true,
"email": "jane.doe@example.com"
}
}'

Quand tu veux émettre, mets à jour le Tax Report Setting en mode complet avec un PATCH.

issue_only : émettre depuis B2Brouter en gardant la réception où elle est

Section intitulée « issue_only : émettre depuis B2Brouter en gardant la réception où elle est »

Quand en as-tu besoin : tu veux émettre depuis une UO de Suffix chez B2Brouter tout en gardant la réception chez la PA qui détient déjà ton SIREN. Si tu préfères le récupérer, voir Changer de PA.

Ce flag n’est accepté que sur une UO de Suffix (cin_scheme="8040") sous le parent SIREN. L’activer sur le parent renvoie 422 dgfip_issue_only_suffix_uo_only.

À l’activation, B2Brouter publie ta ligne à l’Annuaire du PPF (l’annuaire de l’administration française qui achemine le Flux 1) avec l’adressage SIREN_<SUFFIX>, mais ne crée aucun transport Peppol. La ligne que l’autre PA publie pour ton SIREN reste intacte : ce que tu publies, tu le publies sous SIREN_<SUFFIX>, qui est un identifiant différent.

Tu dois créer le transport toi-même pour l’UO de Suffix, avec l’identifiant composé et avec cdar comme seul type de document activé. Sans transport, le premier envoi échoue avec 422 "To use Peppol Network you need to configure this connection to your account".

Trois champs sont critiques :

  • reception: true publie le Suffix au SML. C’est nécessaire, car les CDAR arrivent par Peppol et sans publication ils ne te trouveraient pas.
  • cdar: true, et aucun autre type de document. C’est ce qui rend le mode issue-only : tu reçois les réponses des factures que tu émets, mais pas les factures, qui doivent continuer d’arriver chez ta PA actuelle.
  • pin_value doit être la composition {SIREN du parent}_<SUFFIX> avec pin_scheme: 225, le même adressage que B2Brouter a déjà publié sur la ligne de l’Annuaire.
Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{UO_ACCOUNT_ID}/transports \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"transport": {
"code": "peppol",
"enabled": true,
"reception": true,
"cdar": true,
"pin_scheme": 225,
"pin_value": "842917361_SUF01"
}
}'

Il reste un transport qui émet et qui ne reçoit que les CDAR. L’enregistrement que l’autre PA détient pour ton SIREN n’est pas touché et continue de recevoir les factures de tes fournisseurs.

Si tu veux plus tard recevoir également via B2Brouter, désactive issue_only.


Le changement implique deux enregistrements distincts qui se comportent différemment :

  • L’Annuaire est toujours mis à jour par la PA entrante, pas par la sortante.
  • L’enregistrement Peppol est celui qui peut bloquer le changement : un identifiant ne peut être actif qu’auprès d’un seul prestataire à la fois. Tant que l’enregistrement n’est pas déplacé ou radié, l’activation de la PA entrante échoue avec 422.

Il y a trois façons de le débloquer :

  • Avec un code de migration, le chemin automatique et recommandé, car il n’interrompt pas le service. Il est toujours émis par la PA qui publie l’identifiant à ce moment-là, et utilisé par la PA entrante lors de l’activation. Chez B2Brouter, tu peux en demander un en partant (voir Quitter B2Brouter) et en apporter un en arrivant (voir Venir chez B2Brouter).
  • Avec une radiation Peppol : la PA sortante dépublie l’identifiant de Peppol. Cela le libère et la PA entrante peut activer, mais cela te laisse sans service jusqu’à ce qu’il soit republié. Voir Dépublier, radier et migrer.
  • Manuellement, quand la PA sortante ne propose aucune des deux : contacte la PA entrante, et c’est elle qui réclame le changement à la sortante. Toutes les PA françaises sont tenues de proposer ce chemin, donc ne pas avoir de code ne te bloque pas (voir Venir chez B2Brouter).

Trois opérations que l’on appelle souvent de la même façon et qui ont des effets différents :

OpérationEffetToujours enregistré au SML ?
Dépublier de l’annuaire PeppolRetire l’entrée du catalogue consultableOui : continue d’émettre et de recevoir
Dépublier de PeppolSupprime l’enregistrement du participant au SMLNon : c’est la radiation qui libère l’identifiant
Migrer avec un codeTransfère l’enregistrement à la nouvelle PA sans radiationOui, sans interruption

Seule la deuxième libère l’identifiant. Tant que l’enregistrement au SML existe, activer le Tax Report Setting sur cet identifiant continuera d’échouer avec 422, même si l’autre PA a dépublié l’entrée de l’annuaire. C’est la confusion la plus fréquente : si elle t’assure qu’elle t’a déjà dépublié et que l’activation continue d’échouer, demande-lui de confirmer qu’elle a supprimé l’enregistrement au SML et pas seulement l’entrée de l’annuaire.

La vérification effectuée par B2Brouter à l’activation est une requête DNS en direct contre le SML, pas une requête sur une base de données à nous. Il n’y a donc aucun délai garanti après une radiation, car la propagation dépend du SML et du DNS, mais tu peux relancer l’activation quand tu veux et tu obtiendras l’état réel à ce moment-là. Le code de migration évite tout cela, puisqu’il ne passe par aucune radiation.

Activer le Tax Report Setting sur un identifiant publié par un autre prestataire échoue avec 422. Répète le même appel en y ajoutant le code que ce prestataire t’a donné :

  • POST /tax_report_settings avec peppol_migration_code. C’est la voie principale pour la France : l’identifiant est déplacé dans le cadre de la même activation.
  • POST /transports ou PUT /transports/{code} avec migration_code, si tu crées directement le transport.

Ces deux champs sont write-only et n’apparaissent dans aucun GET. Si le code ne convient pas, l’appel échoue avec migration_code_malformed, migration_code_not_applicable ou migration_code_rejected, ce dernier avec le motif réel du SML. Aucun état partiel ne subsiste : si la migration échoue, le transport n’est pas créé.

Si l’autre PA ne te propose ni code ni radiation, ouvre un ticket de support et nous lançons la procédure manuelle pour réclamer ta portabilité.

POST /accounts/{ACCOUNT_ID}/transports/peppol/migration_code renvoie le code à remettre au nouveau prestataire. Il est idempotent : répéter l’appel renvoie le même code jusqu’à ce que tu l’annules avec DELETE sur le même chemin, et un POST ultérieur en génère un nouveau.

Il renvoie 409 not_published_by_b2brouter si le transport est en émission seule, puisque l’identifiant n’est alors pas publié par nous.

Le champ en lecture seule migration_pending des GET de transports indique si un code a été émis et pas encore annulé. Le code lui-même n’est jamais exposé dans un GET.


Un contact B2B français a besoin d’identifiants de routage (comment la facture atteint le destinataire) et d’une identification fiscale (comment le destinataire apparaît dans le XML UBL).

ChampValeurObjectif
cin_scheme"0002" (SIREN, par défaut) ou "0009" (SIRET, pour adresser un établissement spécifique)ID de l’organisation : utilisé pour rechercher le destinataire dans l’Annuaire
cin_valueSIREN ou SIRETID de l’organisation : l’identifiant enregistré dans l’Annuaire
tin_scheme9957ID fiscal : code ISO 6523 pour l’identifiant fiscal français
tin_valueFR{kk}{siren} (par exemple "FR22842917361")ID fiscal : numéro de TVA français dans le XML UBL
pin_scheme"0225"EAS Peppol du participant FR (FRCTC Electronic Address) — requis pour les contacts français
pin_valueComposition Annuaire du destinataireIdentifiant Peppol du contact ; suit la même composition que le parent à l’Annuaire (SIREN, SIREN_SIRET, SIREN_SIRET_<CR> ou SIREN_<SUFFIX> — voir Niveaux d’identifiants)
country"fr"Requis pour la logique de routage DGFiP
currency"EUR"Devise par défaut pour les factures de ce contact
transport_type_code"peppol"Recommandé : assure la livraison via le réseau Peppol
document_type_code"xml.ubl.invoice.frcius.v1"Recommandé : format de facture UBL France CIUS

Transport et type de document : pour les contacts français enregistrés à l’Annuaire, nous recommandons de définir explicitement transport_type_code: "peppol" et document_type_code: "xml.ubl.invoice.frcius.v1". Sans pin_value, la création renvoie HTTP 422 (« Peppol Endpoint ID can’t be blank »). Tu peux vérifier qu’un contact est enregistré à l’Annuaire avant de le créer en utilisant la recherche dans l’annuaire ou l’annuaire officiel Peppol.

Contacts en Belgique, en Allemagne et dans d’autres pays de l’UE : pour les factures B2B vers des entreprises non françaises, utilise leur schéma d’identifiant national (par exemple "0208" pour le KBO/BCE belge, "0190" pour le Leitweg-ID allemand, "0184" pour le KVK néerlandais) et le code country approprié. Si le destinataire a un point d’accès Peppol actif, B2Brouter route la facture via le Peppol BIS 3.0 standard : aucune configuration n’est nécessaire. Pour les transactions avec tout contact non "fr", l’e-Reporting transfrontalier Flux 10 est généré automatiquement.

Exemple de requête :

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/contacts \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"contact": {
"name": "Client Exemple SARL",
"address": "25 Avenue de la République",
"city": "Lyon",
"postalcode": "69001",
"country": "fr",
"currency": "EUR",
"language": "fr",
"cin_scheme": "0002",
"cin_value": "987654324",
"tin_scheme": 9957,
"tin_value": "FR14987654324",
"pin_scheme": "0225",
"pin_value": "987654324",
"transport_type_code": "peppol",
"document_type_code": "xml.ubl.invoice.frcius.v1"
}
}'

POST Contact - API Reference

Adresser un établissement spécifique : si le client a plusieurs établissements et que tu dois en identifier un en particulier, utilise cin_scheme: "0009" avec le SIRET à 14 chiffres et définis pin_value sur la composition SIREN_SIRET (par exemple 987654324_98765432400019) au lieu du simple SIREN.

Contacts multi-niveaux : si ton client a plusieurs établissements ou services nécessitant des identifiants séparés, crée d’abord le contact parent au niveau SIREN puis ajoute des UO avec parent_id. Voir Structure du compte pour la règle d’or et les structures applicables.

Alternative : contact en ligne sur la facture (sans le module contacts)

Section intitulée « Alternative : contact en ligne sur la facture (sans le module contacts) »

Au lieu de créer un contact séparément et de le référencer avec contact_id, tu peux envoyer un objet contact en ligne directement à l’intérieur de POST /accounts/{ACCOUNT_ID}/invoices, avec toutes les données du destinataire :

{
"invoice": {
"type": "IssuedInvoice",
"contact": {
"name": "Client Exemple SARL",
"country": "fr",
"currency": "EUR",
"language": "fr",
"cin_scheme": "0009",
"cin_value": "98765432400019",
"tin_scheme": 9957,
"tin_value": "FR14987654324",
"pin_scheme": "0225",
"pin_value": "987654324_98765432400019",
"transport_type_code": "peppol",
"document_type_code": "xml.ubl.invoice.frcius.v1"
}
}
}

⚠️ Avertissement important : passe toujours les identifiants corrects (tin / cin / pin) avec la bonne composition FR (parent SIREN + UO), pour éviter de casser la cohérence parent↔UO (voir La règle d’or). À partir de la version d’API 2026-04-20, le système rejette (422) un contact en ligne non simplifié qui ne fournit ni tin_value ni cin_value. currency et language sont obligatoires sur tout contact ; sans eux, la création échoue dans tous les cas. Le contact en ligne accepte également routing_codes.cin1_scheme / routing_codes.cin1_value pour identifier un service au sein d’un SIRET (Cas 2), avec les mêmes valeurs ("224" et le Code Routage) que pour un contact créé via le module contacts.

Facultatif : vérifier le routage du destinataire (recherche dans l’annuaire)

Section intitulée « Facultatif : vérifier le routage du destinataire (recherche dans l’annuaire) »

B2Brouter route les factures automatiquement. Pour inspecter comment un destinataire sera routé avant l’envoi, par exemple pour confirmer qu’il est enregistré à l’Annuaire, utilise la recherche dans l’annuaire (Flux 11) :

Fenêtre de terminal
curl --request GET \
--url https://api-staging.b2brouter.net/directory/fr/0009/98765432400019 \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}'

Réponse résolue : exemple :

{
"external_company": {
"country": "fr",
"cin_scheme": "0009",
"cin_value": "98765432400019",
"information_flags": ["FR_ASSUJETTI_ACTIVE"],
"source": ["peppol", "annuaire"]
}
}

Champs spécifiques à la France :

ChampValeursSignification
information_flagsFR_ASSUJETTI_ACTIVELe destinataire est enregistré et actif à l’Annuaire du PPF
information_flagsFR_ASSUJETTI_INACTIVELe destinataire a un enregistrement obsolète ou aucune PA assignée
information_flagsFR_ASSUJETTI_UNKNOWNLe PPF n’a pas d’information concluante (par exemple 404)
sourcetableau de "peppol", "annuaire"Sources consultées. Si les deux apparaissent, B2Brouter a trouvé le destinataire dans les deux annuaires

Cette recherche est informative : B2Brouter résout déjà le routage automatiquement lors de la création d’une facture (voir Vérification dans l’Annuaire et génération du rapport fiscal). Utilise-la pour inspecter avant l’envoi ou pour afficher le statut du destinataire dans ton interface. Elle ne garantit pas le routage réellement utilisé à l’envoi : si le destinataire s’avère introuvable sur Peppol, l’envoi est bloqué par défaut, ou bascule vers l’e-mail si le compte a activé le fallback Peppol → e-mail. Voir la note ci-dessous.

GET Lookup Directory - API Reference

Vérification dans l’Annuaire et génération du rapport fiscal

Section intitulée « Vérification dans l’Annuaire et génération du rapport fiscal »

B2Brouter vérifie automatiquement si les contacts français (country: "fr") sont enregistrés à l’Annuaire de la DGFiP. Cette vérification détermine le flux de rapport fiscal :

  • Contact enregistré à l’Annuaire (in_dgfip_annuaire: true ou pas encore vérifié) : la facture génère un rapport fiscal Flux 1 (facturation électronique B2B domestique).
  • Contact NON enregistré à l’Annuaire (in_dgfip_annuaire: false) : la facture ne génère pas de rapport fiscal. Cela évite des soumissions Flux 1 invalides pour des destinataires vers lesquels le PPF ne peut pas router.
  • Contact pas encore vérifié (in_dgfip_annuaire: nil) : B2Brouter est permissif : la facture est traitée normalement et génère un rapport fiscal. La vérification a lieu en arrière-plan de manière asynchrone.

Si tu crées un contact français et envoies immédiatement une facture, la vérification à l’Annuaire peut ne pas encore être terminée. C’est voulu : B2Brouter ne bloque pas la création de facture pendant que la vérification est en attente. Si le contact s’avère non enregistré, les futures factures vers ce contact ne généreront pas de rapport fiscal Flux 1 tant qu’il ne s’enregistre pas auprès d’une PA.

La vérification à l’Annuaire ne s’applique qu’aux contacts domestiques français (country: "fr"). Les contacts non français suivent toujours le chemin d’e-Reporting Flux 10, quel que soit leur statut Annuaire.

Important : les deux entreprises doivent être dans l’Annuaire DGFiP : pour un envoi FR → FR avec un rapport fiscal Flux 1, à la fois l’émetteur et le destinataire doivent être enregistrés à l’Annuaire DGFiP. Si l’un des deux ne l’est pas, le rapport fiscal ne peut pas se compléter et la facture est envoyée sans déclaration fiscale.

Comment vérifier l’enregistrement à l’Annuaire DGFiP :

⚠️ Le site annuaire-entreprises.data.gouv.fr sert aux données fiscales générales ; il ne garantit pas l’enregistrement à l’Annuaire DGFiP : ce sont des bases de données différentes.

À partir de septembre 2026, ce comportement permissif cessera de s’appliquer : les déclarations fiscales échoueront simplement si l’identifiant n’est pas listé comme activable DGFiP, même si le SIREN/SIRET est valide.


Une fois ton entreprise onboardée et le Tax Report Setting DGFiP activé, la création de factures fonctionne via l’API de facturation standard, POST /accounts/{ACCOUNT_ID}/invoices. B2Brouter gère automatiquement toutes les exigences spécifiques à la France : génération du rapport fiscal, formatage UBL/CII/Factur-X et transmission au PPF via le Flux 1.

Utilise send_after_import: true pour créer et transmettre en une seule étape. Mets-le à false si tu veux d’abord créer la facture et la revoir avant l’envoi ; dans ce cas, la facture reste à l’état new jusqu’à ce que tu déclenches la transmission via un appel séparé ou via l’interface B2Brouter.

Date de la facture
Pour les comptes avec un Tax Report Setting DGFiP actif, la date de la facture ne peut pas être une date future. Une date future renvoie HTTP 422 (« Only invoices with today’s date are allowed »). Les dates dans les exemples ci-dessous sont indicatives ; remplace-les par la date du jour lors de tes tests.

Numéro de facture
⚠️ Garde le number de la facture à 20 caractères ou moins. La création ne le valide pas et un numéro plus long est créé sans erreur, mais le PPF applique une limite de 20 caractères et rejette le dépôt a posteriori avec REJ_SEMAN. Dans un ledger de Flux 10, le rejet emporte tout le lot de la période.

Facturation séquentielle
L’API traite une facture par requête. Pour des scénarios en masse ou par lot, parcours ta liste de factures et appelle l’endpoint pour chaque document. L’API prend en charge les requêtes concurrentes : tu peux paralléliser plusieurs POST sans attendre chaque réponse avant de démarrer la suivante.

Le cas le plus courant : une facture B2B française domestique avec TVA standard (20 %).

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/invoices \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"send_after_import": true,
"invoice": {
"type": "IssuedInvoice",
"contact_id": 1313228381,
"number": "FA-2026-0048",
"date": "2026-09-15",
"due_date": "2026-10-15",
"currency": "EUR",
"payment_method": 4,
"bank_account_id": {YOUR_BANK_ACCOUNT_ID},
"remittance_information": "FA-2026-0048 — Exemplar SAS, SAS au capital de 50 000 EUR, RCS Paris 123 456 789",
"payment_method_text": "Virement bancaire",
"payment_terms": "Net 30 jours à compter de la date de facture. Pénalité de retard : 12% annuel.",
"invoice_lines_attributes": [
{
"quantity": 10.0,
"description": "Consulting services — architecture review",
"price": 150.0,
"unit": 9,
"taxes_attributes": [
{ "name": "TVA", "percent": 20.0, "category": "S" }
]
},
{
"quantity": 5.0,
"description": "Training sessions — API integration",
"price": 200.0,
"unit": 9,
"taxes_attributes": [
{ "name": "TVA", "percent": 20.0, "category": "S" }
]
}
]
}
}'

Le tableau tax_report_ids dans la réponse contient l’ID du rapport fiscal généré. Utilise-le pour suivre le cycle de vie de la soumission (voir Vérifier le statut d’un rapport fiscal).

POST Invoice - API Reference

Informations de paiement (champs natifs obligatoires)

Section intitulée « Informations de paiement (champs natifs obligatoires) »

Trois champs de paiement sont obligatoires pour les factures électroniques B2B françaises (IssuedInvoice). Fournis-les comme champs API directs :

ChampChamp DGFiPDescriptionObligatoire
remittance_informationPMDRéférence de paiement et mentions légales (immatriculation de l’entreprise, capital social, RCS)Oui : B2B domestique et transfrontalier
payment_method_textPMTDescription textuelle du mode de paiementOui : B2B domestique et transfrontalier
payment_termsAABDate d’échéance, pénalités de retard, conditions d’escompteOui : B2B domestique et transfrontalier
bank_account_id—Id du compte bancaire associé à ton entreprise B2Brouter. Requis quand payment_method est un virement bancaire (code 4)Oui, pour les paiements par virement

Si un champ obligatoire manque, la requête renvoie HTTP 422 avec des messages d’erreur explicites pour chaque champ absent. Ce ne sont pas des erreurs silencieuses : la facture n’est jamais créée. Corrige les champs manquants et resoumets.

Compte bancaire : crée d’abord le compte bancaire associé à ton entreprise (depuis l’interface web ou via API), et référence son id dans la facture avec bank_account_id. Le compte bancaire contient l’IBAN et le BIC et en est la source canonique — ne les passe pas en texte libre dans payment_method_text.

Factures B2C (IssuedSimplifiedInvoice) : ces champs ne sont pas requis.

Import depuis d’autres formats (UBL, CII, Factur-X) : pour ces intégrations, utilise le champ extra_info avec des balises structurées :

#PMD# FA-2026-0048 — Exemplar SAS, RCS Paris 123 456 789
#PMT# Credit Transfer, IBAN FR00 0000 0000 0000 0000 0000 000, BIC XXXXFRPP
#AAB# Net 30 jours. Pénalité de retard : 12% annuel.

B2Brouter extrait ces balises et les fait correspondre automatiquement aux champs natifs correspondants.

Quand une ligne a category: "E" (exonérée de TVA), tu dois aussi fournir un comment avec le code d’exonération VATEX-FR-CGI261-* applicable (DGFiP BT-121) :

⚠️ Blocage silencieux : si comment est omis sur une ligne de catégorie E, la facture est créée (HTTP 200) mais jamais transmise au PPF. La réponse contiendra un tableau errors non vide ; vérifie-le même sur les réponses réussies.

Codes d’exonération de TVA DGFiP (BT-121)

CodeRéférence légaleCatégorie fiscaleDescription
VATEX-FR-FRANCHISEArt. 293 B CGIZ (taux zéro)Franchise en base de TVA
VATEX-FR-CNWVAT—E (exonéré)Avoir net de taxe — avoir sans TVA (le fournisseur renonce à l’ajustement de TVA). Avoirs uniquement (261/381/396, règle G6.21)
VATEX-FR-AE—E (exonéré)Autoliquidation
VATEX-FR-CGI261-1Art. 261-1° CGIE (exonéré)Soins et services médicaux
VATEX-FR-CGI261-2Art. 261-2° CGIE (exonéré)Services paramédicaux
VATEX-FR-CGI261-3Art. 261-3° CGIE (exonéré)Enseignement scolaire, universitaire et formation professionnelle
VATEX-EU-F / -I / -J—E (exonéré)Régime de la marge (margin scheme)

Codes d’exonération au niveau UE : en plus des codes nationaux VATEX-FR-* ci-dessus, la DGFiP accepte aussi la liste de codes VATEX-EU-* (extensions UNCL5305 / EN16931). Le régime de la marge utilise VATEX-EU-F, VATEX-EU-I ou VATEX-EU-J sur une ligne de catégorie E. Fournis le code applicable dans le comment de la ligne.

Les entreprises opérant sous le régime de la franchise en base de TVA sont à taux zéro (catégorie fiscale Z), pas exonérées (catégorie E). Pour les factures en franchise, définis percent: 0.0 et category: "E" avec comment: "VATEX-FR-FRANCHISE" sur chaque ligne de taxe : B2Brouter transcode automatiquement la catégorie en Z :

{
"taxes_attributes": [
{
"name": "TVA",
"percent": 0.0,
"category": "E",
"comment": "VATEX-FR-FRANCHISE"
}
]
}

Certaines opérations sont hors du champ de la TVA et doivent porter la catégorie fiscale O avec percent: 0.0, pas la catégorie E (exonéré) ou Z (taux zéro). Deux cas courants :

  • Détaxe (opérations hors champ de la TVA) : la ligne ne porte aucune TVA.
  • Débours (frais remboursables avancés pour le compte du client) : répercutés sans TVA.
{
"taxes_attributes": [
{ "name": "TVA", "percent": 0.0, "category": "O" }
]
}

Le rapport fiscal Flux 1 synthétise automatiquement le TaxSubtotal de catégorie O correspondant. La catégorie NS est aussi acceptée et transcodée en O.

À partir de la version d’API 2026-04-20, référence la facture originale avec invoice_references pour émettre un avoir :

"invoice_references": [
{
"reference_type": "amend",
"number": "FA-2026-0048",
"date": "2026-09-15",
"reason": "Annule et remplace",
"correction_method": "01"
}
]

B2Brouter génère un UBL CreditNote avec le code type 381 et inclut la référence de facturation.

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/invoices \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"send_after_import": true,
"invoice": {
"type": "IssuedInvoice",
"contact_id": 1313228381,
"number": "NC-2026-001",
"date": "2026-09-25",
"due_date": "2026-10-25",
"is_credit_note": true,
"invoice_references": [
{
"reference_type": "amend",
"number": "FA-2026-0048",
"date": "2026-09-15",
"reason": "Annule et remplace",
"correction_method": "01"
}
],
"currency": "EUR",
"payment_method": 4,
"bank_account_id": {YOUR_BANK_ACCOUNT_ID},
"remittance_information": "NC-2026-001 — annule et remplace FA-2026-0048. Exemplar SAS",
"payment_method_text": "Virement bancaire",
"payment_terms": "Remboursement sous 30 jours.",
"invoice_lines_attributes": [
{
"quantity": -1.0,
"description": "Annulation partielle — Consulting services",
"price": 500.0,
"unit": 9,
"taxes_attributes": [
{ "name": "TVA", "percent": 20.0, "category": "S" }
]
}
]
}
}'

Champs hérités : dans les versions d’API antérieures à 2026-04-20, un avoir était exprimé avec is_amend: true + amended_number + amended_date au lieu de invoice_references. Ces champs restent acceptés dans ces versions pour compatibilité ascendante, mais sont désormais hérités : utilise invoice_references pour les nouvelles intégrations.


Le code de procédure détermine le cadre de flux du PPF. B2Brouter l’assigne automatiquement selon le type_operation du Tax Report Setting et les caractéristiques de la facture.

Code de procédureType d’opérationDescription
S1ServicesFacture standard pour services
B1BiensFacture standard pour biens
M1MixteFacture standard pour opérations mixtes
S2ServicesFacture payée pour services
B2BiensFacture payée pour biens
M2MixteFacture payée pour opérations mixtes
S4ServicesFacture avec acomptes (services)
B4BiensFacture avec acomptes (biens)
M4MixteFacture avec acomptes (mixte)
S7ServicesCorrection d’une facture enregistrée (services)
B7BiensCorrection d’une facture enregistrée (biens)

Pas de cadre « M » dans le Flux 1 : bien que type_operation accepte "mixed", le rapport fiscal Flux 1 ne porte jamais de code de procédure de série M. Une facture mixte résout vers le code services correspondant (S1/S2/S4/S7) et ne déclare que ses ventilations de services. Les lignes M ci-dessus sont listées pour référence mais ne sont pas produites par le Flux 1.

Code de type de documentFormatDescription
xml.ubl.invoice.frcius.v1UBL XMLFacture Peppol France CIUS (Flux 1 / Annuaire)
xml.cii.cross_industry_invoice.frcius.v1CII XMLFacture CII France CIUS
xml.cii.cross_industry_invoice.facturx.fr.all_profiles.v1Factur-X (CII XML)Facture Factur-X France CIUS (tous profils)

Si ton système génère déjà des factures Factur-X ou UBL XML, soumets-les directement en utilisant l’endpoint d’import de documents :

POST /accounts/{id}/invoices/import

Définis Content-Type sur :

  • application/pdf : pour Factur-X (PDF/A-3 avec XML CII intégré)
  • application/xml : pour UBL 2.1 ou CII XML autonome

La France utilise un modèle en Y / à 5 coins, pas un dédouanement (clearance). La facture est transmise au destinataire, qu’un rapport fiscal Flux 1 soit enregistré ou non ; le PPF ne dédouane pas les factures avant qu’elles n’atteignent le destinataire. La Facture et le Rapport fiscal sont des cycles de vie séparés qui ne coïncident qu’à la livraison du Flux 1. Une erreur de rapport fiscal n’annule pas une facture déjà parvenue au destinataire.

ÉtatCDVOrigineDescription
sending—B2Brouter (C1)La facture a été créée et est en file d’attente pour la transmission au PPF
sent200 : DéposéeB2Brouter (C2)La facture a été envoyée au destinataire et au PPF avec succès
registered202 : ReçueDestinataire (C3)Le système du destinataire a reçu la facture
read204 : Prise en chargeDestinataire (C4)Le destinataire a consulté la facture
accepted205 : ApprouvéeDestinataire (C4)Le destinataire a approuvé la facture
accepted1206 : Approuvée partiellementDestinataire (C4)Le destinataire a approuvé partiellement la facture
annotated207 : En litigeDestinataire (C4)Le destinataire a mis la facture en litige
refused210 : RefuséeDestinataire (C4)Le destinataire a rejeté la facture2
paid212 : EncaisséeDestinataire (C4)Le paiement de la facture a été confirmé. Voir État Encaissée : confirmation de paiement.
error—DiversLa validation préalable ou la transmission ont échoué. Le champ errors contient le motif. Voir Comment gérer les factures en erreur.

1 Le CDV 206 fixe le même état que le 205 : accepted. L’état de la facture ne distingue pas une approbation totale d’une approbation partielle. Le montant approuvé par le destinataire est enregistré comme métadonnée de l’événement correspondant, pas comme champ de la facture.
2 Le payload de la facture porte refuse_reason_code avec le motif structuré du rejet.

Avant l’envoi :
Pour qu’une facture puisse être envoyée, elle doit passer la validation du schematron. Si elle échoue, l’envoi renvoie HTTP 422, la facture reste à l’état error et aucun tax report n’est créé. Le message cite le code de la règle en échec, par exemple G1.24 pour un taux de TVA non valide. Le champ errors contient le motif du rejet : modifie la facture avec un PATCH et renvoie-la, ou supprime-la et crées-en une nouvelle. Il n’existe aucun endpoint de réessai : le chemin est corriger puis renvoyer.

Après l’envoi :
DELETE et PATCH renvoient 422 : la facture est dans le cycle de vie du destinataire et la correction se fait avec un avoir. L’exception est le dépôt échoué : tant que tous ses tax reports sont à l’état error ou refused et que la facture n’a pas atteint le destinataire, tu peux encore la corriger avec un PATCH et la renvoyer. DELETE renvoie toujours 422 : une facture avec un tax report, quel que soit son état, ne peut pas être supprimée.

Configure des endpoints de webhook dans l’interface B2Brouter sous Paramètres → Webhooks. Une fois configuré, B2Brouter envoie une requête HTTP POST à ton endpoint chaque fois que la facture atteint un nouvel état.

Invoice Status WebHooks - API Reference

Fenêtre de terminal
curl --request GET \
--url https://api-staging.b2brouter.net/invoices/{INVOICE_ID} \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Accept: application/json'

GET Invoice - API Reference

Une fois qu’une facture atteint l’état sent, la réponse de GET /invoices/{id} inclut un champ download_legal_url. Utilise-le pour télécharger le document de facture transmis :

Fenêtre de terminal
curl --request GET \
--url https://api-staging.b2brouter.net{download_legal_url} \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}'

Comme alternative en une étape, tu peux appeler directement GET /invoices/{id}/as/legal, sans d’abord récupérer download_legal_url depuis le payload de la facture. Il renvoie le document légal archivé tel que stocké et ne génère pas de transaction facturable — voir Télécharger des factures et Transaction : View_as.

Encaissée est le dernier état du cycle CDV d’une facture B2B française, juste après l’approbation du destinataire. Il indique que le paiement a été confirmé (voir la correspondance complète des CDV dans le tableau États de la facture).

B2Brouter propage la confirmation de paiement au PPF via l’un des deux chemins, selon la nature de la facture :

CasCheminMécanisme
Domestique FR → FR (B2Brouter détecte company.country == "fr" et contact.country == "fr")CDAREnvoie un message CDV 212 (changement d’état) sans générer de rapport fiscal supplémentaire
Transfrontalier (B2B intra-UE / extra-UE) ou B2C (IssuedSimplifiedInvoice)Fichier de paiements Flux 10Génère un rapport fiscal dans le Ledger C (paiements) (voir Modèle à trois ledgers)

Quand le paiement est confirmé, marque la facture au PPF avec un appel mark_as :

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/invoices/{INVOICE_ID}/mark_as \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{"state":"paid"}'

Les paiements partiels sont enregistrés avec l’endpoint POST /accounts/{ACCOUNT_ID}/payments, en passant amount et invoice_id. Répète l’appel pour chaque paiement que tu reçois ; une fois que la somme des montants enregistrés couvre le total de la facture, celle-ci passe automatiquement à paid.

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/payments \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'Content-Type: application/json' \
--data '{
"payment": {
"invoice_id": {INVOICE_ID},
"amount": 900.00
}
}'

Nécessite X-B2B-API-Version: 2026-03-02 ou une version ultérieure.

Pour un paiement unique et complet, tu peux aussi appeler directement mark_as avec state: "paid" (voir Marquer une facture comme payée via l’API) ; pas besoin de passer d’abord par POST /accounts/{ACCOUNT_ID}/payments.

Alternativement, gère les paiements depuis l’application web B2Brouter : ouvre la facture → Créer un paiement → saisis le montant payé.

Notes sur les paiements :

  • Tu peux passer full: true au lieu d’amount pour enregistrer la totalité du montant restant dû : B2Brouter calcule le montant en attente au moment de l’exécution de l’appel et ne dépasse jamais le total de la facture. Si tu passes un amount explicite à la place, il n’y a aucun garde-fou contre le surpaiement : il t’appartient de ne pas dépasser le total restant dû.
  • Supprimer un paiement ne rouvre pas la facture : elle reste à l’état paid.
  • Si le paiement a généré un rapport fiscal Flux 10 (facture transfrontalière ou B2C), un PUT/DELETE sur ce paiement renvoie HTTP 422, car la déclaration déjà soumise est verrouillée. Le cas domestique FR-FR (CDV 212, sans rapport fiscal supplémentaire) n’a pas ce verrou.

En tant qu’entreprise française enregistrée à l’Annuaire avec un transport Peppol 0225, tu reçois automatiquement les factures électroniques d’autres plateformes françaises ou connectées à Peppol.

En tant que destinataire, tu réponds avec POST /invoices/{id}/mark_as. La mécanique générale du mark_as, commune à tous les pays, est décrite dans Switch invoice state.

Chaque transition d’état émet le CDV correspondant vers l’émetteur. Les rejets automatiques (213) font exception : ils ne demandent aucun appel, car B2Brouter dérive le code de motif de la DGFiP des erreurs de validation.

ÉtatCDVAppelDescription
read204 : Prise en chargestate: "read"Tu prends la facture en charge
accepted205 : Approuvéestate: "accepted"Tu approuves la facture
accepted206 : Approuvée partiellementstate: "accepted" + amount + amount_code1 + reasonTu approuves partiellement la facture
annotated207 : En litigestate: "annotated" + dispute: true2 + reasonTu mets la facture en litige
refused210 : Refuséestate: "refused" + reason_code3Tu rejettes la facture
paid212 : Encaisséestate: "paid"Tu confirmes le paiement de la facture

Le reason est obligatoire dans les cas 206 et 207 : sans lui, l’appel renvoie 422.

1 Les valeurs d’amount_code sont MAP, MAPTTC, MNA et MNATTC.
2 Sans dispute: true, l’état annotated ne fait que comptabiliser en interne et n’envoie aucun CDV.
3 Le reason_code est facultatif. Voir Codes de rejet.

Exemple de requête d’approbation partielle :

Fenêtre de terminal
curl --request POST \
--url https://api-staging.b2brouter.net/invoices/{INVOICE_ID}/mark_as \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}' \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--data '{
"state": "accepted",
"amount": 250.00,
"amount_code": "MAP",
"reason": "Une ligne ne correspond pas à la commande"
}'

Quand tu rejettes une facture, tu peux ajouter un reason_code avec le motif structuré de la DGFiP : ADR_ERR, REF_CT_ABSENT, CMD_ERR, TX_TVA_ERR, MONTANTTOTAL_ERR, CALCUL_ERR, DOUBLON, NON_CONFORME, DEST_ERR, TRANSAC_INC, EMMET_INC, CONTRAT_TERM et DOUBLE_FACT.

L’API accepte aussi AUTRE, mais la DGFiP ne le permet pas dans un rejet.

La DGFiP refuse un rejet sans commentaire. Si tu n’envoies pas de reason, B2Brouter rédige le commentaire à partir du libellé officiel du reason_code, ou d’un code par défaut si tu n’en envoies pas, et l’historique de la facture affiche « Commentaire sur le rejet généré par le code de motif ». Dans l’application web, le motif est obligatoire.

Exemple de requête :

POST /invoices/{id}/mark_as
{
"state": "refused",
"reason": "Incorrect total amount",
"reason_code": "MONTANTTOTAL_ERR"
}

Exemple de réponse (extrait) :

{
"invoice": {
"id": 12345,
"state": "refused",
"refuse_reason": "Incorrect total amount",
"refuse_reason_code": "MONTANTTOTAL_ERR"
}
}

POST mark_as - API Reference


Le rapport fiscal suit le cycle de vie technique de la soumission au PPF. La génération XML et la transmission au PPF sont toutes deux asynchrones.

Flux 1 : Factures B2B domestiques

ÉtatDescription
newRapport fiscal créé, en file d’attente pour transmission
sentDocument déposé au PPF via SFTP
acknowledgedLe PPF a reçu et validé le fichier (condition CDV 500 : Reçue)
registered✅ Terminal : Facture acceptée et enregistrée par la DGFiP (condition CDV 300)
refused❌ Terminal : Rejetée par la DGFiP (condition CDV 301)
error❌ Terminal : Erreur de transmission ou de traitement PPF

Flux 10 : Factures B2B transfrontalières et B2C (e-Reporting)

ÉtatDescription
newRapport fiscal créé, accumulé pour le lot de ledger quotidien
sentLedger déposé au PPF via SFTP
acknowledgedLe PPF a reçu le ledger (condition CDV 500 : Reçue)
registered✅ Terminal : Ledger accepté et enregistré par la DGFiP (condition CDV 300)
refused❌ Terminal : Rejeté par la DGFiP (condition CDV 301)
error❌ Terminal : Erreur de transmission ou de traitement PPF

Interroge le statut en utilisant l’ID du rapport fiscal depuis tax_report_ids dans la réponse de la facture :

Fenêtre de terminal
curl --request GET \
--url https://api-staging.b2brouter.net/tax_reports/{TAX_REPORT_ID} \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'X-B2B-API-Version: {YOUR_API_VERSION}'

GET Tax Report - API Reference


Le Flux 10 couvre les transactions hors du champ de l’obligation de facturation électronique B2B domestique qui doivent tout de même être déclarées à la DGFiP. B2Brouter gère le Flux 10 automatiquement.

Si tu génères déjà ton propre <Report> F10 et as seulement besoin d’un canal accrédité pour le déposer, consulte plutôt Flux 10 : déposer un fichier généré par ton système.

Ventes à des particuliers non assujettis à la TVA en France. Utilise "type": "IssuedSimplifiedInvoice". Le contact_id et les champs de paiement ne sont pas requis pour les factures B2C.

Transactions transfrontalières (B2B intra-UE et extra-UE)

Section intitulée « Transactions transfrontalières (B2B intra-UE et extra-UE) »

Les ventes à, ou achats auprès d’entreprises établies hors de France doivent être déclarés via le Flux 10. Utilise le type standard IssuedInvoice ou ReceivedInvoice et définis le country de la contrepartie sur la valeur non "fr" pertinente. B2Brouter détecte automatiquement la nature transfrontalière.

Territoires français d’outre-mer (le contact de la facture, pas ton compte) : les départements DROM Guadeloupe (gp), Martinique (mq) et La Réunion (re) sont traités comme France domestique. Les factures vers des contacts qui s’y trouvent génèrent un rapport fiscal Flux 1 et portent IdentificationCode FR, exactement comme la France métropolitaine. Les autres territoires d’outre-mer (Guyane gf, Mayotte yt, Polynésie française pf, Nouvelle-Calédonie nc, TAAF tf, Saint-Pierre-et-Miquelon pm) sont hors du territoire de TVA français et suivent le chemin d’e-Reporting Flux 10. Ce paragraphe concerne la contrepartie de la facture ; pour le compte émetteur, voir Structure du compte.

B2Brouter regroupe les rapports fiscaux Flux 10 en Ledgers envoyés au PPF. La fréquence d’envoi n’est pas toujours quotidienne : elle dépend du vat_regime configuré sur le Tax Report Setting (voir Champs des paramètres de rapport fiscal DGFiP), par décade ou mensuel selon le régime, ou bimestriel pour franchise_en_base. En staging, les ledgers sont déposés quotidiennement pour faciliter les tests ; en production, ils suivent la périodicité réelle du régime. Tu peux identifier les rapports fiscaux Flux 10 par un ledger_id non nul dans la réponse du rapport fiscal.

Chaque ledger est identifié par deux dimensions internes :

  • Rôle DGFiP (SE ou BY) :
    • SE (Seller / émission) : pour les ventes que tu émets.
    • BY (Buyer / réception) : pour les achats intracommunautaires que tu déclares en tant qu’acheteur.
  • Mode (transactions ou payments) :
    • transactions : ledgers de factures (codes de procédure S1 / B1 / M1), type de document xml.ledger.dgfip.transactions.
    • payments : ledgers de paiements (codes de procédure S2 / B2 / M2, la TVA sur services s’accumule à l’encaissement), type de document xml.ledger.dgfip.payments.

La combinaison des rôles et des modes produit jusqu’à 3 ledgers par compte et période de déclaration :

LedgerRôleModeContenu
A : ÉmissionSEtransactionsFactures émises (B2C et B2B transfrontalier)
B : RéceptionBYtransactionsAchats intracommunautaires / extra-UE déclarés en tant qu’acheteur
C : PaiementsSEpaymentsPaiements confirmés de tes factures émises (cas Encaissée transfrontalier / B2C)

La paire (BY, payments) n’existe pas : l’information de paiement pour tes achats est générée par le vendeur de son côté ; tu ne la déclares pas.

Chaque rapport fiscal est lié à un seul ledger_id (il ne peut pas appartenir à plusieurs ledgers à la fois). Le regroupement se fait par compte + période de déclaration + (rôle, mode) sous un verrou pour éviter les doublons.