Créer une facture
POST/api/v1/workspaces/:workspace_id/invoices
Crée une nouvelle facture pour l'espace de travail indiqué.
Avant que la facture ne soit construite, le payload est complété avec les valeurs par défaut côté entreprise :
- résolution de
party_id: une entréepartiesportant unparty_id(éventuellementbilling_address_id) est complétée à partir de l'annuaire de l'entreprise (nom, identifiant/schéma d'immatriculation légale, numéro de TVA, identifiant de routage, adresse de facturation, contact par défaut) et reliée en retour afin que leparty_idde la réponse fasse l'aller-retour. La recherche est cantonnée par type STI pour correspondre àdirection:buyersursalesse résout parmi les clients de l'entreprise,sellersurpurchasesparmi ses fournisseurs ;payeeettax_representativese résolvent dans l'ensemble de l'annuaire. Unparty_idsur le rôle propre de l'entreprise (sellersursales,buyersurpurchases) retourne 422 (api.invoices.errors.party_id_not_allowed_for_company_role) - ce tiers est dérivé de la fiche entreprise, pas de l'annuaire.party_idetbilling_address_iddoivent être des entiers positifs ; toute autre valeur retourne 422 (api.invoices.errors.invalid_reference_id) plutôt que d'être convertie. Tout attribut voisin également envoyé sur l'entrée remplace la valeur correspondante de l'annuaire. Unparty_idnon résolvable retourne 422 (api.invoices.errors.party_not_found). Quand la fiche de l'annuaire porte un SIRET déclaré sous le schéma0009, le tiers est rempli avec le SIREN de l'unité légale - les 9 premiers chiffres - sous le schéma0002, car BR-FR-11 lit BT-47 sur le sélecteur0002et exige exactement 9 chiffres dès lors que la facture est une pièce B2B flux 2 ; une valeur laissée sous0009ne remplit pas du tout ce sélecteur et l'assertion est fatale. Seule l'identité que cet endpoint recopie depuis l'annuaire est convertie : unlegal_registration_idenvoyé explicitement sur l'entrée est l'intention déclarée de l'appelant et passe sans modification, et une immatriculation à 14 chiffres ne portant aucun schéma déclaré n'est pas convertie non plus, puisque la forme seule ne prouve pas une identité française. - Valeur par défaut du tiers côté entreprise : quand le payload ne comporte aucune entrée pour le
rôle propre de l'entreprise (
sellersurdirection: sales,buyersurdirection: purchases), une entrée est ajoutée à partir de laCompanyet de son établissement siège. Une entrée de tiers que l'appelant fournit n'est jamais écrasée. - Valeur par défaut de
item_notes: quand la clé est OMISE et quedirectionvautsales, les mentions légales de l'entreprise sont insérées. Les facturespurchasesn'en reçoivent aucune. Envoyer un tableau vide explicite vide la collection et elle n'est jamais reremplie - c'est ainsi qu'un intégrateur retire des notes existantes lors d'un PATCH. - Valeur par défaut de
payment_means: quand la clé est OMISE (un tableau vide explicite vide la collection et elle n'est jamais reremplie), les comptes bancaires de l'entreprise figurant sur la facture sont insérés, dans les deux sens. Sursales, quand l'acheteur se résout à un client de l'annuaire confidentiellement affacturé, le compte du factor de ce client les remplace. Quand un acheteursalesest présent mais ne peut pas être résolu à un client de l'annuaire (envoyé par nom seul, sansparty_idni lien persistant), aucun moyen de paiement n'est inséré - le statut d'affacturage ne peut pas être déterminé, et émettre les comptes propres de l'entreprise pour un client affacturé acheminerait le paiement au mauvais endroit. - Contrôle du profil pour un payeur tiers : une entrée
partiesportantrole: "payer"(le bloc EXT-FR-FE-BG-02) n'est acceptée que lorsquecustomization_idvaut l'une des deux formes EXTENDED-CTC-FR -urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended(Factur-X/CII) ouurn:cen.eu:en16931:2017#conformant#urn.cpro.gouv.fr:1p0:extended-ctc-fr(UBL). Uncustomization_idomis, vide ou EN 16931 simple retourne 422 (api.invoices.errors.payer_requires_extended_profile) et n'écrit rien : les générateurs UBL et CII refusent d'émettre un payeur hors EXTENDED-CTC-FR, si bien qu'en accepter un ici créerait une facture dont tous les exports structurés échouent, ce que l'appelant ne découvrirait qu'au moment du téléchargement. - Acteurs structurés (XP Z12-014) :
buyer_agent(EXT-FR-FE-BG-01),seller_agent(EXT-FR-FE-BG-03),invoicee(EXT-FR-FE-BG-04) etinvoicer(EXT-FR-FE-BG-05) sont renvoyés en lecture sous leur propre clé, renseignés sur les documents reçus ; aucun n'est jamais lu comme le vendeur, l'acheteur ou le payeur. Ils sont acceptés à la création comme à la modification sous l'une des deux formes EXTENDED-CTC-FR decustomization_idseulement, et les exports UBL et CII les émettent alors ; sous tout autrecustomization_id, une entrée retourne 422 (api.invoices.errors.extended_role_requires_extended_profile). Chaque entrée doit porter unname(EXT-FR-FE-03 / -66 / -89 / -112, 1..1), envoyé ou rempli depuisparty_id, sinon 422 (api.invoices.errors.structured_actor_name_required) ; unidentifierdoit être accompagné de sonidentifier_scheme_id(EXT-FR-FE-07 / -70 / -92-1 / -116, 1..1), sinon 422 (api.invoices.errors.structured_actor_identifier_scheme_required) ; unendpoint_iddoit être accompagné de sonendpoint_scheme_id(EXT-FR-FE-13 / -76 / -99 / -122, 1..1), sinon 422 (api.invoices.errors.structured_actor_endpoint_scheme_required) ; unlegal_registration_iddoit être accompagné de sonlegal_registration_scheme_id(EXT-FR-FE-09 / -72 / -95 / -118), sinon 422 (api.invoices.errors.structured_actor_legal_registration_scheme_required) ; une adresse qui renseigne un champ doit porter soncountry_code(EXT-FR-FE-107 / -130, Factur-X EXTENDED), sinon 422 (api.invoices.errors.structured_actor_country_required), et uncountry_codequi n'est pas un code ISO 3166-1 alpha-2 retourne 422 (api.invoices.errors.structured_actor_country_unknown) ;endpoint_scheme_iddoit appartenir à la liste CEF EAS (BR-CL-25),identifier_scheme_idetlegal_registration_scheme_idà la liste ISO 6523 ICD (BR-CL-10 / -11), chacune restreinte aux codes que connaît la table des schémas de Scribee, hors0231(réservé à l'assujetti unique), sinon 422 (api.invoices.errors.structured_actor_scheme_outside_code_list) ; unendpoint_idde plus de 125 caractères retourne 422 (api.invoices.errors.structured_actor_endpoint_too_long, BR-FR-25, bloquante) ; l'un de ces trois schémas envoyé sans sa valeur retourne 422 (api.invoices.errors.structured_actor_value_required), puisqu'il n'est émis que comme attribut de la valeur ; undirectory_routing_identifierretourne 422 (api.invoices.errors.structured_actor_routing_identifier_unsupported) - il n'adresse que le vendeur et l'acheteur, l'adresse électronique d'un acteur est sonendpoint_id, et il n'est pas recopié sur un acteur depuis la fiche de l'annuaire désignée parparty_id; unnameou un schéma qui n'est pas une chaîne compte comme absent ; et une deuxième entrée du même rôle d'acteur retourne 422 (api.invoices.errors.structured_actor_duplicated) ; unbuyer_agentou uninvoiceesansbuyer, ou unseller_agentou uninvoicersansseller, retourne 422 (api.invoices.errors.structured_actor_parent_required), puisque l'UBL imbrique l'acteur dans cette partie - la partie côté entreprise ajoutée par l'API compte. Une facture qui nomme uninvoicern'est déposée que si l'entreprise détient, à la date d'émission, un mandat de facturation tiers facturant actif pour ce tiers (XP Z12-014 cas 19a) ; sinon le dépôt retourne 422 et la facture reste un brouillon. - Contrôle de
role_code:role_codeest accepté sur une entréepayer(EXT-FR-FE-44),payee(EXT-FR-FE-26) et sur un acteur structuré (EXT-FR-FE-04 / -67 / -90 / -113). L'envoyer sur tout autre rôle retourne 422 (api.invoices.errors.role_code_not_allowed_on_role), car la valeur d'aucun autre rôle n'est jamais émise sur le fil. Le code de l'invoiceevaut toujoursIVet celui de l'invoicerII, et toute autre valeur retourne 422 (api.invoices.errors.role_code_mismatch). Sur chaque rôle accepté, la valeur doit provenir de la liste UN/CEFACT PartyRoleCode D22A - l'espace de valeurs UNCL 3035 - et la casse est significative ; toute autre valeur retourne 422 (api.invoices.errors.invalid_role_code).PRest le code du tiers payeur. Sur une entréepayee, le code exige en outre l'une des deux formescustomization_idEXTENDED-CTC-FR : EXT-FR-FE-26 n'est défini que dans les profils EXTENDED et CII-SR-352 / UBL-CR-270 interdisent l'élément en EN 16931 simple, si bien qu'unrole_codede bénéficiaire sous tout autre profil retourne 422 (api.invoices.errors.payee_role_code_requires_extended_profile). Un bénéficiaire SANSrole_coderelève de l'EN 16931 simple (BG-10) et est accepté sous tous les profils. - Contrôle de la devise :
currency_code(BT-5),tax_currency_code(BT-6) et chaquetax_subtotals[].currency_codedoivent porter un code ISO 4217 alpha-3 issu des listes de codes embarquées par Scribee - l'énumération UN/CEFACT ISO3AlphaCurrencyCode réunie à la listeISO4217de Peppol BIS. La comparaison est sensible à la casse, si bien queeurest refusé plutôt que mis en majuscules, et toute valeur hors de ces listes retourne 422 (api.invoices.errors.invalid_currency_code) ; le message nomme lequel des trois champs a été refusé. L'acceptation ici n'est pas une conformité Peppol : PEPPOL-EN16931-CL007 est fatal au regard de sa propre liste, plus étroite, si bien qu'une poignée de codes est acceptée à l'écriture et refusée malgré tout à l'export Peppol. Une valeur omise ou vide n'est jamais refusée - BT-5 retombe surEURà la création, et sur la devise existante de la facture à la mise à jour. - Contrôle de cohérence de la ventilation de TVA (
direction: "sales"uniquement) : lestax_subtotalsdoivent se raccorder aux totaux du document. La somme desamount_without_taxes(BT-116) est comparée autotal_amount_excluding_taxes(BT-109), et la somme desvat_amount(BT-117) autotal_tax_amount(BT-110), chacune à 0,01 près - la tolérance que la règle PPF F1-START-TOTAL-COHERENCE-G1.53 accorde au dépôt. Un écart au-delà retourne 422 aveccode: "operation_failed"(api.invoices.errors.ventilation_not_reconciled) et n'écrit rien ; le message nomme le total, le montant que le document déclare et celui auquel la ventilation s'élève. Chaque moitié est jugée pour elle-même et sort du périmètre quand son total de document est omis ou qu'aucune lignetax_subtotalsn'énonce son montant - un total omis n'est pas un total nul, et c'est ainsi que le schematron le lit lui aussi.direction: "purchases"n'est jamais jugé : un achat enregistré par l'API est le reflet d'une pièce que le tenant a reçue et cette plateforme ne la dépose jamais. Le contrôle existe parce que BT-116 porte la base HORS taxe, si bien qu'un appelant qui le remplissait avec le montant TTC obtenait un 201 ici et un refus PPF quelques heures plus tard. - Contrôle de cohérence de l'état déjà payée (
direction: "sales"uniquement) : une facture ou un avoir qui déclare l'état déjà payée -invoicing_process_idpaid_goods_invoice/paid_services_invoice/paid_goods_and_services_invoice(codesB2/S2/M2, BT-23), ou l'un de ces codes dansprofile_id- doit déclarer lui-même le règlement : unprepaid_amount(BT-113) égal autax_inclusive_amount(BT-112), unpayable_amount(BT-115) à0, aucunpayable_rounding_amount(BT-114) autre que0, et la date de paiement dansdue_date(BT-9), antérieure ou égale àissue_date. Ce sont la règle fatale flux 2 BR-FR-CO-09 et la règle EN 16931 BR-CO-16. Tout autre cas retourne 422 aveccode: "operation_failed"(api.invoices.errors.already_paid_*) et n'écrit rien. L'API ne complète jamais ces totaux et n'en déduit jamais l'état déjà payée : une facture payée peut aussi rester dans la familleB1/S1/M1, que ce contrôle ne juge pas. Déclarer cet état ne crée ni enregistrement de paiement ni statut de cycle de vie. Une facture déjà payée ne peut pas non plus désigner une facture d'acompte pardocument_iddansinvoice_references: elle deviendrait une facture définitive soldant des acomptes, dont la familleB4/S4/M4n'a pas de variante déjà payée (XP Z12-014 CU-21) ; l'appel retourne le même 422 et n'écrit rien.
Request
Responses
- 201
- 401
- 403
- 422
La facture créée, y compris tout champ de tiers, de notes d'article ou de moyens de paiement que l'API a complété à partir des valeurs par défaut de l'annuaire de l'entreprise.
La requête ne comporte aucun jeton d'accès (bearer token) OAuth, ou celui-ci est invalide ou expiré.
L'application OAuth du jeton n'a aucune relation d'accès avec le tenant de l'espace de travail demandé, ou un tel espace de travail n'existe pas.
Le payload a échoué la validation. Le corps d'erreur indique error: "unprocessable_entity" avec un message décrivant l'échec précis - un champ requis vide, un party_id non résolvable, un party_id envoyé pour le rôle propre de l'entreprise, un tiers payer (EXT-FR-FE-BG-02) sur une facture dont le customization_id n'est pas l'une des deux formes EXTENDED-CTC-FR, ou un role_code envoyé sur un rôle autre que payer (EXT-FR-FE-44) ou payee (EXT-FR-FE-26), hors de la liste UN/CEFACT PartyRoleCode D22A, ou sur un payee dont le customization_id 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 envoyé comme une valeur qui 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 code non listé et que sur tout autre rôle il est refusé pour le rôle), ou un currency_code (BT-5), un tax_currency_code (BT-6) ou un tax_subtotals[].currency_code 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 devise - ou, sur un payload direction: "sales", une ventilation tax_subtotals qui ne se raccorde pas aux totaux du document, la somme des amount_without_taxes étant comparée au total_amount_excluding_taxes et la somme des vat_amount 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, refusée avec code: "operation_failed" (api.invoices.errors.ventilation_not_reconciled) - ou, sur un payload direction: "sales" qui déclare l'état déjà payée (invoicing_process_id B2 / S2 / M2 ou leurs clés paid_*, ou l'un de ces codes dans profile_id), un prepaid_amount différent du tax_inclusive_amount, un payable_amount différent de 0, un payable_rounding_amount ni absent ni égal à 0, ou une due_date absente ou postérieure à issue_date (règle flux 2 BR-FR-CO-09, EN 16931 BR-CO-16), ou une entrée invoice_references désignant une facture d'acompte par document_id (XP Z12-014 CU-21), refusés avec code: "operation_failed" (api.invoices.errors.already_paid_*) - ou un payload direction: "sales" visant une entreprise dont l'offre souscrite n'inclut pas la facturation de vente - la même restriction, et le même statut, que ceux signalés par POST /invoices/upload ; l'entreprise elle-même est visible dans l'espace de travail, si bien que ce refus n'est jamais un 404. details est présent et indexé par champ dès lors que le refus nomme des attributs (un échec de validation d'enregistrement, ou un lifecycle_state demandé que le contrôle de dépôt refuse et dont il liste les champs manquants), et absent sinon. Un lifecycle_state: "deposited" demandé emprunte le même contrôle de dépôt que PATCH /invoices/{id}/transition, si bien que ses refus remontent ici aussi - parmi eux une partie qui ne déclare aucun pays, avec details sous la clé seller.address.country_code ou buyer.address.country_code. Seule l'obligation flux 1 porte cette règle de présence ; une vente dont l'acheteur doit une déclaration e-reporting (flux 10) n'est pas refusée pour cela.