Mettre à jour une facture brouillon
PATCH/api/v1/invoices/:id
Met à jour une facture brouillon par ID. Seules les factures à l'état de cycle de vie « draft » peuvent être mises à jour.
Il s'agit d'une opération de remplacement complet : tous les enregistrements enfants (parties, lignes, sous-totaux de taxe, moyens de paiement, notes, remises/charges, références de facture) sont effacés et reconstruits à partir du payload fourni.
Avant que la facture ne soit reconstruite, le payload est complété avec les mêmes valeurs par défaut
côté entreprise que POST .../invoices - résolution de party_id par rapport à l'annuaire
de l'entreprise, une valeur par défaut de tiers côté entreprise quand le payload l'omet (sans
jamais écraser une entrée de tiers que l'appelant fournit), des valeurs par défaut
d'item_notes sur sales, et des valeurs par défaut de payment_means (comptes bancaires de
l'entreprise, ou compte du factor de l'acheteur pour un client confidentiellement affacturé)
dans les deux sens. Il s'agit d'un changement de comportement
pour les intégrations existantes : un PATCH qui omet item_notes ou payment_means les reremplit désormais
à partir de l'entreprise au lieu de laisser la facture sans aucun. Les mêmes contrôles
s'appliquent, parmi eux le contrôle de devise ISO 4217 documenté sur POST .../invoices :
currency_code (BT-5), tax_currency_code (BT-6) et chaque tax_subtotals[].currency_code
sont comparés aux listes de codes embarquées de façon sensible à la casse, et une valeur non
listée retourne 422 sans rien écrire. Un BT-5 omis laisse en vigueur la devise existante de la
facture et n'est jamais refusé. Le contrôle de cohérence de la ventilation de TVA documenté
au même endroit s'applique aussi à ce verbe, et il y est jugé sur les totaux EFFECTIFS
plutôt que sur ceux du payload : sur direction: "sales", la somme des
tax_subtotals[].amount_without_taxes est raccordée au total_amount_excluding_taxes et la
somme des tax_subtotals[].vat_amount au total_tax_amount, à la tolérance de 0,01 de la
règle PPF G1.53 près, chaque total étant lu dans le payload quand sa clé est présente et
dans la facture persistée quand elle est omise, et un écart au-delà retourne 422 sans rien
écrire. Ne lire que le payload était faux sur ce verbe : les tax_subtotals envoyés
REMPLACENT ceux du document en bloc, alors qu'un total dont la clé est absente garde sa
valeur persistée ; un PATCH ne portant qu'une nouvelle ventilation laissait donc les totaux
inchangés, sortait du périmètre de la règle, et persistait exactement l'incohérence que le
contrôle existe pour refuser. La conversion en
SIREN aussi : un tiers rempli depuis une fiche d'annuaire dont le SIRET est déclaré sous le
schéma 0009 est écrit avec le SIREN de l'unité légale sous le schéma 0002
(BR-FR-11 / BT-47), tandis qu'un legal_registration_id envoyé explicitement sur l'entrée
n'est jamais converti. Les valeurs par défaut de payment_means
se résolvent par rapport au currency_code existant de la facture quand le payload l'omet, pas en EUR.
Elles sont résolues UNIQUEMENT à partir de l'acheteur du payload : parce que cet endpoint remplace chaque
tiers, omettre parties laisse la facture sans acheteur, et aucun moyen de paiement n'est
émis dans ce cas plutôt que de reporter le compte bancaire de l'acheteur détruit.
Le contrôle de cohérence de l'état déjà payée documenté sur POST .../invoices s'applique
aussi à ce verbe, jugé sur les valeurs EFFECTIVES comme le contrôle de la ventilation de TVA :
invoicing_process_id, profile_id, les totaux, due_date et issue_date sont chacun lus
dans le payload quand la clé est présente et dans la facture persistée quand elle est omise.
Ainsi, un PATCH qui modifie le total d'une facture B2 / S2 / M2 sans redéclarer
prepaid_amount retourne 422, et un PATCH qui ramène la facture dans la famille B1 / S1 /
M1 la sort du périmètre du contrôle.
L'autorisation repose sur l'accès tenant de l'application OAuth à l'espace de travail de la facture.
Request
Responses
- 200
- 401
- 403
- 404
- 422
La facture mise à jour, reconstruite à partir du payload avec les valeurs par défaut côté entreprise réappliquées pour tout parties, item_notes ou payment_means que le payload a omis.
La requête ne comporte aucun jeton d'accès (bearer token) OAuth, ou celui-ci est invalide ou expiré.
La facture n'est pas à l'état de cycle de vie draft et ne peut donc pas être mise à jour.
Aucune facture n'existe avec l'ID donné, ou la facture appartient à un espace de travail auquel l'application du jeton n'a pas accès - les deux cas renvoient cette même réponse afin de ne jamais révéler l'existence d'une ressource dans un autre espace de travail.
Le payload a été refusé. Le corps d'erreur indique error: "unprocessable_entity" avec un code nommant la classe d'erreur et un message la décrivant : operation_failed quand le party_id d'une entrée parties ne se résout pas dans l'annuaire de l'entreprise, ou quand un tiers payer (EXT-FR-FE-BG-02) est envoyé alors que le customization_id effectif de la facture - celui du payload quand la clé est présente, celui persisté quand elle est omise - n'est pas l'une des deux formes EXTENDED-CTC-FR, ou quand un role_code est envoyé sur un rôle autre que payer (EXT-FR-FE-44) ou payee (EXT-FR-FE-26), avec une valeur hors de la liste UN/CEFACT PartyRoleCode D22A, ou sur un payee alors que ce customization_id effectif n'est pas l'une des deux formes EXTENDED-CTC-FR (EXT-FR-FE-26 n'est défini que dans les profils EXTENDED), ou quand un role_code n'est pas du tout une chaîne (un booléen ou un nombre JSON n'est jamais une absence, si bien que sur un payer ou un payee il est refusé comme valeur hors de cette liste et que sur tout autre rôle il est refusé pour le rôle), ou quand un currency_code (BT-5), un tax_currency_code (BT-6) ou un tax_subtotals[].currency_code tombe hors des listes de codes ISO 4217 embarquées - la comparaison est sensible à la casse, le message nomme lequel des trois champs a été refusé, et une valeur qui n'est pas du tout une chaîne est refusée de la même façon plutôt que lue comme une absence, seuls une clé omise, un null explicite ou une chaîne vide ou composée uniquement d'espaces valant absence de valeur, ou quand un payload direction: "sales" porte une ventilation tax_subtotals qui ne se raccorde pas aux totaux du document - la somme des amount_without_taxes face au total_amount_excluding_taxes et la somme des vat_amount face au total_tax_amount, chacune à la tolérance de 0,01 de la règle PPF G1.53 près et chacune hors périmètre quand son total de document ou ses montants de ventilation sont absents (api.invoices.errors.ventilation_not_reconciled), ou quand une facture direction: "sales" dont l'invoicing_process_id ou le profile_id EFFECTIF déclare l'état déjà payée (B2 / S2 / M2) ne porte pas un prepaid_amount effectif égal au tax_inclusive_amount, un payable_amount à 0, aucun payable_rounding_amount autre que 0 et une due_date antérieure ou égale à issue_date (règle flux 2 BR-FR-CO-09, EN 16931 BR-CO-16), ou quand une telle facture désigne une facture d'acompte par document_id dans invoice_references (XP Z12-014 CU-21), api.invoices.errors.already_paid_* dans les deux cas ; invalid_argument quand le payload porte lifecycle_state - un changement d'état sur une facture existante est précisément l'objet de PATCH /api/v1/invoices/{id}/transition.