Skip to main content
Version: 1.0.1

CDV / CDAR Lifecycle


Every French invoice carries a lifecycle: a sequence of statuses recording what happened to it after it was sent — delivered, taken in charge, approved, disputed, paid. Each status is transmitted as a CDAR (Compte-rendu d'Anomalie et de Rejet) document, and the resulting chain is the invoice's CDV (Cycle de Vie).

This page covers which statuses exist, who can submit each one, in what order, and what data each requires.


1. Two kinds of status

Automatic — produced by the platform with no action from you:

CodeStatusWhen
200DéposéeThe invoice is deposited
201Émise par la plateformeImmediately after 200
202Reçue de la plateformeThe recipient's platform receives it
203Mise à dispositionIt is made available to the buyer
213RejetéeTechnical rejection — validation failed

Do not submit these. A /cdar/submit call carrying one of them is rejected.

Manual — you submit these when they reflect what happened on your side:

CodeStatusSubmitted by
204Prise en chargeBuyer
205ApprouvéeBuyer
206Approuvée partiellementBuyer
207En litigeBuyer
208SuspendueBuyer
210RefuséeBuyer
211Paiement transmisBuyer
209ComplétéeSeller
212EncaisséeSeller
214ViséeSeller

The role gate is enforced. A seller cannot submit a buyer status, and vice versa — the platform decides your role from the invoice's direction in your own account.

220 (Annulée) is neither: the platform produces it automatically when a corrective document for the invoice is confirmed.


2. Status reference

CodeNameLabel (FR)ObligationTerminalReaches the tax authority
200DEPOSEEDéposéeMandatoryYes
201EMISEÉmise par la plateformeOptional
202RECUEReçue de la plateformeRecommended
203MISE_A_DISPOSITIONMise à dispositionRecommended
204PRISE_EN_CHARGEPrise en chargeRecommended
205APPROUVEEApprouvéeRecommended
206APPROUVEE_PARTIELLEMENTApprouvée partiellementRecommended
207EN_LITIGEEn litigeOptional
208SUSPENDUESuspendueOptional
209COMPLETEEComplétéeOptional
210REFUSEERefuséeMandatoryYesYes
211PAIEMENT_TRANSMISPaiement transmisRecommended
212ENCAISSEEEncaisséeMandatoryYesYes
213REJETEERejetéeMandatoryYesYes
214VISEEViséeOptional
220ANNULEEAnnuléeOptionalYes

"Mandatory" is conditional, not per-invoice. It means: if the underlying business event happens, reporting it is compulsory. Refuse an invoice and 210 must be sent; collect a payment and 212 must be sent. In a normal accepted-and-paid flow the buyer sends no mandatory status at all.

The four mandatory statuses are exactly the four that reach the tax authority. Everything else stays between the two platforms.

Terminal means the lifecycle is closed. Any further /cdar/submit for that invoice is rejected.

Three manual statuses can be sent once only per invoice: 205, 210 and 212. A second attempt is rejected as a duplicate.


3. Transition rules

Transitions are validated. Submitting a status that cannot follow the current one returns an error — the lifecycle does not advance and nothing is transmitted.

You want to submitCurrent status must be one of
204 Prise en charge203
205 Approuvée203, 204, 207, 208
206 Approuvée partiellement203, 204, 207, 208
207 En litige203, 204, 208
208 Suspendue203, 204
209 Complétée203, 204, 205, 206, 207, 208, 211
210 Refusée202, 203, 204, 207, 208
211 Paiement transmis205, 206
212 Encaissée203, 204, 205, 206, 207, 208, 211
214 Visée203, 204, 205, 206, 207, 208, 211

The buyer decision group

205, 206, 207, 208 and 210 are alternative decisions on the same invoice. How they interact is the part most integrations get wrong:

AfterStill available
207 En litige205, 206, 210 — not 208
208 Suspendue205, 206, 207, 210 — all of them
205 Approuvéenone of the five; 211 remains available
206 Approuvée partiellementnone of the five; 211 remains available
210 Refuséenone — terminal

207 and 208 are transitional. A disputed or suspended invoice is meant to be resolved afterwards by approving, partially approving, or refusing it. If your interface locks those options after a dispute, the invoice can never be closed.

205 and 206 are final decisions: after either, the only remaining buyer action is 211.


4. Submitting a status

POST /cdar/submit?statusName={ENUM_NAME}
Content-Type: application/json
R-Auth: {token}

statusName takes the enum name from the reference table, not the numeric code — REFUSEE, not 210.

FieldTypeRequiredNotes
companyIdUUIDYesYour own company
invoiceIdUUIDYesThe invoice in your own account. The buyer's copy and the seller's copy have different ids.
reasonCodestring206, 207, 208, 210Must come from that status's list — see section 5
reasonstring208, 210Free text comment. Mandatory for Suspendue and Refusée — the request is rejected without it. Recommended for 206 and 207.
characteristicsarray208For Suspendue, at least one entry must carry a non-empty currencyId (e.g. "EUR"). Optional for other statuses.
requestedActionCodestring207 only, optionalSee section 6
requestedActionstring207 only, optionalFree text

A reason code on its own is not enough for 208 and 210: the authority validates the free-text comment as well, so a request carrying only reasonCode is rejected before it is sent.

Example — refusal

curl -X POST 'https://{host}/cdar/submit?statusName=REFUSEE' \
-H 'Content-Type: application/json' \
-H 'R-Auth: {token}' \
-d '{
"companyId": "…",
"invoiceId": "…",
"reasonCode": "MONTANTTOTAL_ERR",
"reason": "Net payable does not match the purchase order"
}'

Example — suspend

The only status that requires characteristics.

curl -X POST 'https://{host}/cdar/submit?statusName=SUSPENDUE' \
-H 'Content-Type: application/json' \
-H 'R-Auth: {token}' \
-d '{
"companyId": "…",
"invoiceId": "…",
"reasonCode": "JUSTIF_ABS",
"reason": "Delivery note missing — cannot process until supplied",
"characteristics": [
{ "currencyId": "EUR" }
]
}'

Example — take charge

curl -X POST 'https://{host}/cdar/submit?statusName=PRISE_EN_CHARGE' \
-H 'Content-Type: application/json' \
-H 'R-Auth: {token}' \
-d '{"companyId": "…", "invoiceId": "…"}'

5. Reason codes

A reason code is mandatory for statuses 206, 207, 208 and 210, and the allowed codes are defined per status. The lists are not interchangeable: a code accepted for a dispute may be rejected for a refusal.

This is a change from our earlier documentation, which presented a single shared list for En litige and Refusée. Those two statuses have different lists. See section 8.

206 — Approuvée partiellement · 13 codes

CodeLabel (FR)Meaning
AUTREAutreOther
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong, missing, or already invoiced
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect
PU_ERRPrix unitaires incorrectsUnit price is not the expected one
REM_ERRRemise erronéeDiscount missing or not as expected
QTE_ERRQuantité facturée incorrecteInvoiced quantity is not as expected
ART_ERRArticle facturé incorrectWrong item invoiced
MODPAI_ERRModalités de paiement incorrectesPayment terms incorrect
QUALITE_ERRQualité d'article livré incorrecteA delivered item is defective
LIVR_INCOMPLivraison incomplète / non effectuéeDelivery incomplete or not made

207 — En litige · 26 codes

The widest list. It contains everything valid for 210, plus thirteen more.

CodeLabel (FR)Meaning
AUTREAutreOther
TX_TVA_ERRTaux de TVA erronéVAT rate is wrong
MONTANTTOTAL_ERRMontant total erronéAn invoice total is wrong
CALCUL_ERRErreur de calcul de la factureCalculation error — line totals or rounding
NON_CONFORMEMention légale manquanteA mandatory legal statement is missing
DOUBLONFacture en doublonDuplicate invoice
DOUBLE_FACTDonnées réglementaires F1 en doublonDuplicate regulatory data
DEST_INCDestinataire inconnuRecipient not found in the directory
DEST_ERRErreur de destinataireWrong recipient
EMMET_INCÉmetteur inconnuSender unknown to the recipient
TRANSAC_INCTransaction inconnueNo matching delivery or service
CONTRAT_TERMContrat terminéContract has ended
COORD_BANC_ERRErreur de coordonnées bancairesBank details are wrong
ADR_ERRAdresse de facturation électronique erronéeElectronic invoicing address wrong or missing
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect
PU_ERRPrix unitaires incorrectsUnit price is not the expected one
REM_ERRRemise erronéeDiscount missing or not as expected
QTE_ERRQuantité facturée incorrecteInvoiced quantity is not as expected
ART_ERRArticle facturé incorrectWrong item invoiced
MODPAI_ERRModalités de paiement incorrectesPayment terms incorrect
QUALITE_ERRQualité d'article livré incorrecteA delivered item is defective
LIVR_INCOMPLivraison incomplète / non effectuéeDelivery incomplete or not made

208 — Suspendue · 7 codes

CodeLabel (FR)Meaning
JUSTIF_ABSJustificatif absent ou insuffisantSupporting documents missing or insufficient
COORD_BANC_ERRErreur de coordonnées bancairesBank details are wrong
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
SIRET_ERRSIRET erroné ou absentRecipient SIRET wrong or missing
CODE_ROUTAGE_ERRCode routage absent ou erronéRouting code missing or wrong
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing
REF_ERRRéférence incorrecteA reference is incorrect

210 — Refusée · 13 codes

CodeLabel (FR)Meaning
TX_TVA_ERRTaux de TVA erronéVAT rate is wrong
MONTANTTOTAL_ERRMontant total erronéAn invoice total is wrong
CALCUL_ERRErreur de calcul de la factureCalculation error — line totals or rounding
NON_CONFORMEMention légale manquanteA mandatory legal statement is missing
DOUBLONFacture en doublonDuplicate invoice
DOUBLE_FACTDonnées réglementaires F1 en doublonDuplicate regulatory data
DEST_ERRErreur de destinataireWrong recipient
EMMET_INCÉmetteur inconnuSender unknown to the recipient
TRANSAC_INCTransaction inconnueNo matching delivery or service
CONTRAT_TERMContrat terminéContract has ended
ADR_ERRAdresse de facturation électronique erronéeElectronic invoicing address wrong or missing
CMD_ERRN° de commande/engagement incorrect ou manquantPurchase order number wrong or missing
REF_CT_ABSENTRéférence contractuelle manquanteA contractually required reference is missing

AUTRE is not valid for a refusal. There is no generic "other" option, unlike every other status above.

Also absent from 210 but present in 207: SIRET_ERR, CODE_ROUTAGE_ERR, DEST_INC, COORD_BANC_ERR, REF_ERR, PU_ERR, REM_ERR, QTE_ERR, ART_ERR, MODPAI_ERR, QUALITE_ERR, LIVR_INCOMP, AUTRE.

Building one shared dropdown

Every code valid for 210 is also valid for 207. If your interface offers a single reason list for both statuses, restrict it to the 13 codes of 210 — that set is safe for both. Separate lists are only needed if you want the thirteen extra codes 207 allows.


6. Requested action — 207 only

Optional. Tells the seller what you expect them to do about the dispute.

CodeMeaning
NOANo action required
NINNew invoice required
CNFCredit note required, full
CNPAccepted value — no published label
PINAccepted value — no published label
CNAAccepted value — no published label
OTHAccepted value — no published label

7. Error handling

A rejected submission returns HTTP 400 with a validationErrors[] array. Read that array — it names the rule that failed and, for reason-code errors, lists the codes that would have been accepted.

{
"errorMessage": "Validation failed!",
"errorType": "VALIDATION_FAILED",
"status": 400,
"errorId": "78509ff2-004a-4bd5-905d-05b51fa102ad",
"validationErrors": [
{
"code": "BR-FR-CDV-CL-09_MDT-113_210",
"field": "…/ProcessConditionCode[1]",
"message": "Le code motif de statut (MDT-113) : \"SIRET_ERR\", n'est pas dans la liste des codes autorisés pour le statut REFUSÉE (210) : \"TX_TVA_ERR\", \"MONTANTTOTAL_ERR\", …"
}
]
}

Logging only errorMessage loses the diagnosis. "Validation failed!" on its own tells you nothing.

Rejected before validation

Three checks run locally, before any document is generated. They return 400 with a message naming the missing field rather than a schematron rule id.

ConditionError
reasonCode missing for 206, 207, 208 or 210A comment (reason) is required for status …
reason missing for 208 or 210same message
208 with no characteristics entry carrying a currencyIdCDV-208 Suspendue requires at least one characteristic with a currencyId …

Schematron rules

Rules you are most likely to hit:

RuleCause
BR-FR-CDV-CL-09_MDT-113_<status>The reason code is not in that status's list
BR-FR-CDV-15_MDT-113A reason code is required for this status and none was supplied
BR-FR-CDV-CL-10_MDT-121requestedActionCode is not an accepted value

Other errors:

ErrorCause
Invalid transitionThe status cannot follow the current one — see section 3
Terminal statusThe lifecycle is closed (210, 212, 213 or 220 already recorded)
Duplicate status205, 210 or 212 was already sent for this invoice
Not allowed for your roleYou submitted a status belonging to the other party

A failed submission leaves the lifecycle untouched. The invoice keeps its previous status and nothing is transmitted, so you can correct the payload and retry.


8. Reading the lifecycle

GET /cdar/last-cdv/{companyId}/{invoiceId}

Current status, invoice status, platform and timestamps.

GET /cdar/history/{invoiceId}?companyId={companyId}

Full chain, oldest first. Each entry carries the status, the actor, the direction, and — where applicable — reasonCode and reasonText. reasonText echoes back the reason you sent.


9. Migration notes

Reason codes were not validated in earlier releases; any value passed through. They are now checked against the official per-status lists, so values that previously worked may now be rejected.

Fields that became mandatory:

StatusNow required
208 SuspenduereasonCode, reason, and a characteristics entry with currencyId
210 RefuséereasonCode and reason
206, 207reasonCodereason stays optional

If your integration sends only a reason code for a refusal or a suspension, add the free-text comment. The authority validates the comment, not just the code.

Codes that changed name:

Previously documentedUse instead
MONTANT_ERRMONTANTTOTAL_ERR
FACT_NON_CONFORMENON_CONFORME
ROUTAGE_ERRCODE_ROUTAGE_ERR — and note it is not valid for 210
NON_TRANSMISENo equivalent; removed

Codes that are still valid but not for every status:

CodeValid forNot valid for
SIRET_ERR206, 207, 208210
DEST_INC207210 — use DEST_ERR
AUTRE206, 207210
COORD_BANC_ERR207, 208210

If you map business-facing labels onto these codes, check every label against the list for the status it will be submitted with. A label that works for a dispute may fail for a refusal.

Common mapping for a missing mandatory legal statement: NON_CONFORME — its official label is literally "Mention légale manquante", and it is valid for both 207 and 210.