Flowie
Compliance · 🇫🇷 France

The French e-invoicing lifecycle — interactive reference

Every invoice exchanged under the French reform carries a cycle de vie — a sequence of statuses fixed by AFNOR XP Z12-012 (CDAR data element MDT-105): 14 codes, 200–213. Four are obligatoires (200, 210, 212, 213 — always transmitted to the DGFiP concentrator), five are recommandés (203, 204, 205, 206, 211), and the remaining five coded statuses are libres (201, 202, 207, 208, 209 — optional between platforms). Anything outside the referential is a custom status that never leaves your own tooling. This page is the full referential: who emits each status, in which phase, the allowed transitions — and the exact API call that emits or observes it with Flowie (Plateforme Agréée n° 0040).

Interactive explorer

Filter by tier, click any status for its full definition and the code to add, or press play to watch an invoice travel the network — each step logs the webhook Flowie fires.

Mandatory (obligatoire) Recommended (recommandé) Free (libre, coded) Happy terminal Transition Possible when intermediate statuses are skipped
Click a status in the diagram — or play a scenario — to see its definition, its transitions, and the exact API call that emits it.

The three tiers — obligatoire, recommandé, libre

The official referential (the « Transmission » column of the DGFiP external specifications, kept by AFNOR XP Z12-012) classifies the 14 coded statuses in three tiers — and everything outside the referential forms a fourth, uncoded family:

TierStatusesWhat it meansTransmitted?
Obligatoire (mandatory) 200 Déposée, 210 Refusée, 212 Encaissée, 213 Rejetée Must be emitted whenever the corresponding event occurs. 200 opens every lifecycle; 212 carries the collected amount (MEN) that feeds the VAT-on-collection (CA3) pre-fill; 210/213 cancel the invoice and require a coded motif. Yes — always, including to the PPF concentrator (within the 24-hour reporting window).
Recommandé 203 Mise à disposition, 204 Prise en charge, 205 Approuvée, 206 Approuvée partiellement, 211 Paiement transmis Officially recommended “pour assurer le bon déroulé des échanges”. Optional — but they are what gives your counterparty (and your own AR/AP team) real-time visibility. A serious integration emits them. Between platforms, when emitted.
Libre (coded) 201 Émise, 202 Reçue, 207 En litige, 208 Suspendue, 209 Complétée Part of the referential — coded, interoperable, defined semantics — but entirely at each platform’s / party’s discretion. Not every platform supports receiving them. Between platforms, when emitted & supported.
Custom (uncoded) unbounded Internal workflow states like bon à payer or exportée en compta. No MDT-105 code, no CDAR — see modelling them with tags. Never.

207 En litige is the one contested cell: the v2.3 dossier’s transmission table reads libre, while several industry readings (and some trainings) class it recommandé. Treat it as optional either way; we track every annex revision and will update this page if the classification moves.

The 2024 PPF pivot changed what “mandatory” binds
Since the October 2024 pivot (PPF reduced to annuaire + data concentrator), the operative rule is: the 4 obligatoires are always produced and always reach the DGFiP; the other 10 coded statuses are optional between platforms — a platform must not fail an invoice because a recommended status never arrived. The three-tier vocabulary survives in the AFNOR annexes and in practice; both framings are shown here.
Mandatory ≠ emitted by you
“Mandatory” binds the platform (the PA), not your integration, for 200 and 213 — Flowie emits those automatically. Your integration is on the hook for the business decisions only: 210 Refusée when the buyer refuses, 212 Encaissée when the supplier is paid. The cheat-sheet below says exactly which side emits what.

The 14 statuses of the referential (MDT-105)

The referential splits in two phases, carried in the CDAR’s MDT-77 type code: Transmission statuses (305 — produced automatically by the platforms as the invoice moves) and Traitement statuses (23 — business decisions produced by the buyer or the supplier).

CodeStatut (FR)EnglishTierPhaseEmitted byMeaning
200DéposéeDepositedMandatoryTransmissionSeller’s PAThe sending platform attests the invoice is received, checked & compliant — start of every lifecycle. Invoice data reaches the PPF within 24 h of this timestamp.
201Émise par la plateformeIssued by platformLibreTransmissionSeller’s PAThe seller’s PA confirms it transmitted the invoice to the recipient’s PA.
202Reçue par la plateformeReceived by platformLibreTransmissionBuyer’s PAThe recipient’s PA confirms receipt from the sender’s PA (not yet visible to the buyer).
203Mise à dispositionMade availableRecommendedTransmissionBuyer’s PAThe invoice is available to the buyer on their platform.
204Prise en chargeAcknowledgedRecommendedTraitementBuyerThe buyer acknowledges the invoice and starts processing it.
205ApprouvéeApprovedRecommendedTraitementBuyerThe buyer accepts the invoice in full.
206Approuvée partiellementPartially approvedRecommendedTraitementBuyerThe buyer accepts the invoice only in part — carries the approved / non-approved amount blocks (MAP/MNA); usually followed by a credit note.
207En litigeIn disputeLibreTraitementBuyerThe buyer disputes all or part of the invoice without refusing it outright. Motif required. Resolves to approval or refusal.
208SuspendueSuspendedLibreTraitementBuyerProcessing is suspended pending supporting documents from the supplier. Motif required.
209ComplétéeCompletedLibreTraitementSupplierThe supplier delivered the awaited material — resolves 208. Complementary data travels in the status message (MDG-43, code MAJ); the invoice itself is not re-sent.
210RefuséeRefusedMandatoryTraitementBuyerDeliberate business refusal of a valid invoice. Terminal — cancels the invoice; coded motif from the restricted list required.
211Paiement transmisPayment sentRecommendedTraitementBuyerThe buyer confirms the payment was sent (or the supplier confirms a refund). Amount blocks MPA (paid) / RAP (remainder).
212EncaisséeCollectedMandatoryTraitementSupplierThe supplier confirms funds received (partial or full). Must carry the collected amount (MDT-207 = MEN, rule BR-FR-CDV-14) — this is the e-reporting payment-data vehicle behind the VAT (CA3) pre-fill for services. Terminal.
213RejetéeRejectedMandatoryTransmissionEither PATechnical rejection by a platform control (format, SIRET, duplicate…). Terminal — the invoice was never validly exchanged. The norm splits it into rejetée à l’émission and rejetée en réception; coded motif required.
Two frequent third-party errors
“The buyer emits Encaissée” — no: 211 is the buyer saying payment sent; 212 Encaissée is emitted by the supplier (both map to UNTDID 1373 code 47 Paid, which is why they get conflated). And “there is a code 214 Visée”Visée / Mise en paiement belong to the legacy Chorus Pro B2G flow; the B2B referential stops at 213.

For the crucial difference between 210 Refusée (business refusal by the buyer) and 213 Rejetée (technical rejection by a platform), plus 208 Suspendue (on hold) and their coded motifs (MDT-113/MDT-114) — see the dedicated Refusal, rejection & on-hold reference (or the summary on the France overview).

Status → Flowie API cheat-sheet

One table to bookmark. Automatic means Flowie emits the status for you — you only observe it (webhook lifecycle.updated, or GET /v1/documents/{id}/lifecycle). Everything else is one call to POST /v1/documents/{id}/lifecycle.

CodeStatutYour sideWhat you do
200DéposéeSupplierAutomatic — emitted when your POST /v1/documents/send passes controls.
201Émise par la plateformeSupplierAutomatic — observe via webhook document.sent.
202Reçue par la plateformeSupplierAutomatic — observe via webhook document.delivered.
203Mise à dispositionBuyerAutomatic — your inbound webhook document.received fires; the invoice is in your queue.
204Prise en chargeBuyerPOST …/lifecycle {"status":"under_review"}
205ApprouvéeBuyerPOST …/lifecycle {"status":"approved"}
206Approuvée partiellementBuyerPOST …/lifecycle {"status":"approved", "remainingAmount": …} — the remaining amount signals a partial approval.
207En litigeBuyerPOST …/lifecycle {"status":"disputed", "reason": "…"}
208SuspendueBuyerPOST …/lifecycle {"status":"disputed", "reasonCode":"suspended", "reason":"…"} — the suspended reason code makes Flowie emit 208 instead of 207.
209ComplétéeSupplierAttach the requested material: POST …/actions {"action":"link","relatedDocumentId":"…"} (or add-note) on a suspended invoice — Flowie emits 209.
210RefuséeBuyerPOST …/lifecycle {"status":"rejected", "reasonCode":"…", "reason":"…"} — reason is forwarded verbatim as MDT-113/MDT-114.
211Paiement transmisBuyerPOST …/lifecycle {"status":"paid", "paymentDate":"…"} — from the buyer org, this emits 211.
212EncaisséeSupplierPOST …/lifecycle {"status":"paid", "paymentDate":"…", "paymentAmount": …} — from the supplier org, this emits 212. Partial collection: use "partially_paid" + remainingAmount.
213RejetéeSupplierAutomatic — a platform control failed. Observe webhook document.failed (or compliance.reported.failed), fix, and re-send.
Same call, two codes — 211 vs 212
The norm distinguishes who states that money moved: the buyer saying “payment sent” is 211; the supplier saying “funds received” is 212 (the mandatory one, since it drives VAT on encaissements). With Flowie you make the same {"status":"paid"} call from either side — the party role on the document decides which code is transmitted.

Skipping statuses — what a minimal legal flow looks like

Because only 4 of the 14 statuses are mandatory, a perfectly legal lifecycle can be as short as 200 → 212 (deposited, then collected) — or 200 → 210 / 200 → 213 when things go wrong. The recommended statuses are not checkpoints: an invoice does not have to pass through 204 to be approved, and a buyer may refuse (210) without ever emitting 207 En litige first. Use the Mandatory filter in the explorer above to see the minimal graph.

Two consequences for your integration:

Canonical scenarios

The five playable scenarios in the explorer, in prose — these are the flows to test before go-live:

ScenarioStatus sequenceOutcome
Happy path200 → 201 → 202 → 203 → 204 → 205 → 211 → 212Invoice approved and paid; VAT pre-fill fed by 212.
Dispute resolved200 … 204 → 207 → 205 → 211 → 212Buyer contests (207), parties settle, approval and payment proceed.
Suspension200 … 204 → 208 → 209 → 205 → 211 → 212Buyer requests supporting documents (208); supplier completes (209); flow resumes.
Refusal200 … 203 → 204 → 210Business refusal by the buyer. Invoice cancelled; supplier must issue a corrective invoice (and an avoir if it was already accepted).
Platform reject200 → 201 → 213Technical rejection (format, SIRET, duplicate…). The invoice never legally existed on the network; fix and re-send.

How statuses travel — the CDAR message

Between platforms, a lifecycle status is not a bare number: it travels as a CDAR (Cross Domain Acknowledgement and Response) message — the UN/CEFACT CrossDomainAcknowledgementAndResponse document, which France pins to the D22B XSD and constrains with the BR-FR-CDV Schematron rules. It is the only lifecycle syntax in the French socle minimal — the UBL ApplicationResponse familiar from Peppol is not an accepted syntax for the French CDV flux. The fields that matter:

FieldContentExample
MDT-77TypeCode — the phase: 305 = transmission (platform-generated), 23 = traitement (business decision)23
MDT-105ProcessConditionCode — the status code from the 200–213 referential (+ its label in MDT-106)210
MDT-88StatusCode — optional generic UNTDID 1373 equivalent, for international coherence (see mapping below)50
MDT-113ReasonCode — coded motif from the restricted vocabulary of the XP Z12-012 annex (rule BR-FR-CDV-CL-09). Required for 210/213 (and expected for 206/207/208).(see the official « Tableau des motifs de STATUTS » annex)
MDT-114Reason — optional free text"Prix unitaire ligne 3 non conforme au devis"
MDG-43 / MDT-207Characteristic blocks qualifying amounts & data: MEN collected (mandatory on 212), MPA/RAP paid & remainder (211), MAP/MNA approved & non-approved (206), MAJ replacement data (209)MEN = 2359.50
MDT-87 + MDG-35 + MDG-40Invoice identification: number + issue date + seller party (SIREN) — one CDAR references one invoice, one statusFA-2027-0042

Flowie builds, signs and routes CDAR messages for you in both directions: your POST …/lifecycle becomes an outbound CDAR; inbound CDARs from the buyer’s platform become lifecycle.updated webhooks with reasonCode/reason passed through verbatim — we never invent or re-map a motif (the motif code lists circulating on vendor blogs are largely fabricated; trust only the AFNOR annex).

International mapping — UNTDID 1373 & Peppol

Each French code has a generic UNTDID 1373 equivalent (BR-FR-CDV-CL-05), carried in MDT-88:

FR→ UNTDID 1373FR→ UNTDID 1373
200 Déposée10In preparation207 En litige46Litigious
201 Émise51Issued208 Suspendue39Suspended
202 Reçue43Received209 Complétée37Complete
203 Mise à disposition48Available210 Refusée50Rejected
204 Prise en charge45In process211 Paiement transmis47Paid
205 Approuvée1Accepted212 Encaissée47Paid
206 Approuvée part.49Cond. accepted213 Rejetée8Rejected (tech.)

Peppol is a different layer. Peppol status flows use UBL ApplicationResponse twice — the Message Level Response (validation outcome) and the Invoice Response (buyer decision, 7-code UNCL4343 subset: AB IP UQ CA RE AP PD). There is no official normative table mapping the French 2xx codes to UNCL4343 as of mid-2026; the informal overlaps (205≈AP, 206≈CA, 210≈RE, 211/212≈PD…) break down for the transmission phase, where 200/213 correspond to Peppol’s MLR / transport-receipt layer rather than to an Invoice Response. When you exchange cross-border through Flowie we translate at the edge and always keep the French codes authoritative for the DGFiP leg.

Custom statuses — your workflow, off the wire

Beyond the five coded libre statuses (201, 202, 207, 208, 209 — which do travel between platforms when supported), anything outside 200–213 is a custom status: useful, unregulated, and strictly local. Typical examples and how to model them with Flowie without polluting the regulated lifecycle:

Libre statusTypical meaningModel it as
En validation interneWaiting on an internal approverA tag: POST …/actions {"action":"tag","tag":"workflow/validation-interne"}
Bon à payerCleared for payment by APA tag + optionally assign to the payer
Exportée en comptabilitéPushed to the ledgerA tag, set by your ERP sync after GET …/structured
Relance envoyéeDunning reminder sentAn add-note action with the reminder reference
Mise en paiement / MandatéeLegacy Chorus Pro B2G statusesTreat as libre in a B2B context — their closest B2B code is 211; see the overview’s warning.

Tags and notes never generate a CDAR and are never reported to the DGFiP — which is exactly the point. If a state should be visible to your counterparty, use the regulated status; if it’s internal process, keep it libre.

Machine-readable referential (JSON Schema)

Everything on this page is also published as data, so your integration (or your AI agent) can consume the referential instead of scraping it:

ArtifactURLWhat it is
Dataset /schemas/fr-lifecycle-statuses.json All 14 statuses — tier, phase, emitter, terminality, motif & amount-block rules (MEN/MPA/MAP…), UNTDID 1373 mapping, canonical transitions, and the exact Flowie call or webhook per status.
JSON Schema /schemas/fr-lifecycle-status.schema.json Draft 2020-12 schema the dataset validates against — use it to type your own copy, generate models, or validate a vendored snapshot in CI.
const { statuses } = await (await fetch(
  "https://docs.get-flowie.com/schemas/fr-lifecycle-statuses.json")).json();

const mandatory = statuses.filter(s => s.tier === "mandatory");
// → 200 Déposée, 210 Refusée, 212 Encaissée, 213 Rejetée

const next = Object.fromEntries(statuses.map(s => [s.code, s.transitionsTo]));
// next[204] → [205, 206, 207, 208, 210]

The dataset carries a semantic version plus the DGFiP / AFNOR spec versions it was verified against (specVersions); we bump it with every annex revision. The tables above and the interactive diagram are generated from the same facts — if you spot a divergence, that's a bug: tell us.

Test the full lifecycle in the sandbox

The sandbox ships a working replica of this state machine. A five-minute session that exercises every mandatory status:

  1. Send an invoice with a flw_test_ key — status 200 is synthesized immediately.
  2. Drive the buyer side: POST …/lifecycle {"status":"under_review"} then {"status":"approved"} (codes 204, 205).
  3. Mark it paid from the supplier org (212) — with simulateCompliance: "accept" on the org, a synthetic compliance.reported webhook fires, exactly like the real PPF acknowledgement.
  4. Now break things: simulateCompliance: "reject_00058" replays a PPF rejection end-to-end (compliance.reported.failed), and an illegal transition (e.g. received → paid) returns 409 invalid_transition with the allowed next states.

Full test matrix — including timeout and flaky simulators for your retry logic — in the integration playbook.

References