Facturino / Documentation / Factures

Factures

L'objet invoice représente une facture B2B française. Le dépôt CII est vérifié selon EN 16931 et les règles CIUS-FR locales ; la variante UBL est vérifiée selon EN 16931 uniquement et ne vaut pas attestation CIUS-FR. Le cycle de vie couvre la création en brouillon, la finalisation atomique (avec attribution de numéro), le dépôt via Plateforme Agréée et le suivi des paiements.

Toute facture naît d'une décision fiscale. Demandez d'abord une décision — sous la source facturino (TVA déterminée par Facturino) ou integration (TVA fournie par votre moteur, validée en cohérence) — puis créez la facture avec taxDecisionId et decisionLines. La TVA, les montants et les mentions décidés sont copiés tels quels et figés ; une décision finale adosse exactement une facture.

Les historiques volumineux sont archivés en segments au-delà de 512 Kio pour préserver la capacité d’écriture. Les lectures REST et l’export personnel restituent les entrées archivées ; les anciens identifiants de dépôt restent opposables aux retours tardifs.

Endpoints

MéthodeCheminDescription
POST/v1/invoicesCréer un brouillon
GET/v1/invoicesLister les factures (filtres, pagination)
GET/v1/invoices/:idRécupérer une facture
PATCH/v1/invoices/:idModifier un brouillon (seuls les drafts sont éditables)
DELETE/v1/invoices/:idSupprimer un brouillon (soft-delete)
POST/v1/invoices/:id/bind-tax-decisionAdosser une décision fiscale finale à un brouillon commercial (issu d'un devis converti)
POST/v1/invoices/:id/finalizeFinaliser → attribue le numéro et passe à finalized, ou directement à paid avec un payment facultatif
POST/v1/invoices/:id/sendDéposer via la Plateforme Agréée
POST/v1/invoices/:id/emailEnvoyer par email avec PDF en pièce jointe
POST/v1/invoices/:id/remindEnvoyer une relance de paiement
POST/v1/invoices/:id/cloneDupliquer en brouillon
POST/v1/invoices/:id/cancelAnnuler un brouillon
GET/v1/invoices/:id/pdfPDF lisible
GET/v1/invoices/:id/facturxFactur-X (PDF/A-3 + XML CII)
GET/v1/invoices/:id/xmlXML brut (CII ou UBL via ?format=)
POST/v1/invoices/:id/paymentsEnregistrer un paiement
GET/v1/invoices/:id/paymentsLister les paiements
POST/v1/invoices/:id/payments/:paymentId/cancelAnnuler un paiement (piste d'audit conservée)
POST/v1/invoices/:id/payment-linkCréer un lien de paiement en ligne
GET/v1/invoices/:id/statusStatut courant (poll-friendly)
GET/v1/invoices/:id/eventsHistorique du cycle de vie
GET/v1/invoices/:id/verifyVérifier l'intégrité de la chaîne de hash
GET/v1/invoices/:id/audit-trailPiste d'audit fiable (PAF)

Créer une facture

$ curl -X POST https://facturino.com/api/v1/invoices \
  -H "Authorization: Bearer fac_test_..." \
  -H "Idempotency-Key: invoice-create-order-7842" \
  -H "Content-Type: application/json" \
  -d '{
    "customerId": "cus_8f2k4m9n",
    "taxDecisionId": "taxdec_9k2f7p1m",
    "decisionLines": [
      { "taxLineRef": "sprint-3", "unit": "flat_rate" }
    ],
    "buyer": {
      "companyName": "Durand & Associés",
      "siret": "00012345500008",
      "address": {
        "line1": "10 rue de Rivoli",
        "postalCode": "75001", "city": "Paris", "country": "FR"
      }
    },
    "dates": { "issued": "2026-09-22", "due": "2026-10-22" },
    "payment": {
      "terms": "30 jours net",
      "termsDays": 30,
      "method": "transfer",
      "latePaymentRate": "3 fois le taux légal",
      "collectionFee": "40.00 EUR"
    }
  }'

Réponse — objet invoice complet :

{
  "id": "inv_a1b2c3d4e5f6",
  "object": "invoice",
  "status": "draft",
  "taxSource": "facturino",
  "taxDecisionId": "taxdec_9k2f7p1m",
  "number": null,
  "livemode": false,
  "currency": "eur",
  "customer": {
    "ref": "cus_8f2k4m9n",
    "snapshot": {
      "name": "Durand & Associés",
      "siret": "00012345500008"
    }
  },
  "items": [
    {
      "id": "li_3k9d2",
      "description": "Développement web — Sprint 3",
      "quantity": "1",
      "unit": "flat_rate",
      "unitPrice": 150000,
      "vatRate": 2000,
      "vatCode": "S",
      "taxLineRef": "sprint-3",
      "lineAmount": 150000,
      "vatAmount": 30000,
      "lineTotal": 180000
    }
  ],
  "totals": {
    "totalHT": 150000,
    "totalVAT": 30000,
    "totalTTC": 180000
  },
  "dates": {
    "issued": "2026-04-22",
    "due": "2026-05-22"
  },
  "einvoicing": {
    "paId": null,
    "paStatus": null,
    "paStatusCode": null,
    "paTransactionId": null,
    "paErrorCode": null,
    "rejectionReason": null,
    "refusalReason": null,
    "paIdempotencyKey": null,
    "peppolDeliveryId": null,
    "ereportingId": null,
    "sentAt": null,
    "trackingId": null,
    "submissionArtefact": null
  },
  "files": {},
  "created": "2026-04-22T13:48:10.000Z",
  "updated": "2026-04-22T13:48:10.000Z"
}

Formats d'entrée

  • Montants : entiers en centimes (150000 = 1 500,00 €). Évite les erreurs de précision flottante.
  • Taux TVA : centièmes de pourcent (2000 = 20,00 %) — décidés côté serveur (source facturino) ou fournis par ligne de la décision (source integration), jamais saisis sur la facture.
  • Quantités : chaînes décimales ("1.5") — précision arbitraire.
  • Dates : ISO 8601 sans heure ("2026-04-22").

Codes TVA (EN 16931)

Le champ vatCode indique la catégorie TVA appliquée à la ligne, selon la liste de codes définie par la norme européenne EN 16931. Il est conclu par la décision fiscale — déterminé par Facturino, ou fourni par l'intégration et validé en cohérence — et sert à générer les mentions légales obligatoires sur le PDF et le XML Factur-X.

CodeLibelléUsage typique
SStandard rateTaux normal (20 %, 10 %, 5,5 %, 2,1 %)
ZZero rateTaux zéro (livres, presse spécifique…)
EExemptExonération (formation pro, médical…)
AEReverse chargeAutoliquidation par l'acquéreur (B2B intra-UE, sous-traitance BTP…)
GExportExport hors UE (TVA non applicable)
ICIntracommunautaireLivraison intra-UE entre assujettis
KVAT exempt EUService intracommunautaire (article 196)
OOut of scopeOpération hors champ TVA
VATEX-FR-FRANCHISEFranchise en baseRégime franchise (article 293 B CGI, micro-entrepreneurs)

Précision financière. Les montants sont des entiers en centimes à la fois en entrée et en sortie (150000 = 1 500,00 €) — symétrie entrée/sortie, aucune chaîne décimale dans les réponses. Cela évite toute perte de précision liée aux flottants et permet de réinjecter une valeur lue sans re-conversion. Les montants des deposits et de l'schedule suivent la même convention en centimes.

Acomptes et échéanciers

Deux modalités de règlement s'ajoutent au corps de création (toutes deux optionnelles) :

  • deposits — factures d'acompte (type deposit, code 386) déjà émises au même client. Leur TTC est déduit du montant dû de la facture de solde (BT-113, CGI art. 289). Chaque acompte doit être finalisé ; maximum 20.
  • schedule — échéancier de 2 à 12 versements. La somme des montants (en centimes) doit couvrir le montant dû, les dates sont strictement croissantes et la dernière échéance tombe à la date d'échéance de la facture (BT-9). L'échéancier est rendu en texte libre dans les conditions de paiement (BT-20).

Les deux modalités se règlent contre le montant décidé, dans la transaction de création : le total décidé (amountToCharge) n'est jamais modifié — les acomptes alimentent amountPaid (BT-113) et abaissent amountDue (BT-115), et l'échéancier répartit exactement ce qui reste dû. Un acompte non intégralement réglé est refusé : un acompte émis mais non encaissé n'est pas un prépaiement.

# Facture de solde : on déduit deux acomptes déjà émis (386) et on
# échelonne le solde en 2 versements (le dernier tombe à l'échéance).
{
  "customerId": "cus_8f2k4m9n",
  "taxDecisionId": "taxdec_solde01",
  "decisionLines": [ /* ... */ ],
  "buyer": { /* ... */ },
  "dates": { "issued": "2026-09-22", "due": "2026-11-30" },
  "payment": { /* ... */ },
  "deposits": [
    { "invoiceId": "inv_acompte1" },
    { "invoiceId": "inv_acompte2" }
  ],
  "schedule": [
    { "amount": 600000, "dueDate": "2026-05-31", "label": "1er versement" },
    { "amount": 600000, "dueDate": "2026-06-30" }
  ]
}

Émission en un appel (one-shot)

Le flux granulaire (créer → /finalize/send) reste toujours disponible. Pour émettre en un seul appel, deux champs optionnels à la création :

  • autoFinalize (booléen) — finalise la facture (attribue le numéro) dans le même appel.
  • autoSend — finalise puis émet : email envoie au client, pa dépose sur la Plateforme Agréée connectée (asynchrone, statut sending). Implique autoFinalize.
# One-shot : créer + finaliser + envoyer (email au client ET dépôt PA) en un appel.
{
  "customerId": "cus_8f2k4m9n",
  "taxDecisionId": "taxdec_9k2f7p1m",
  "decisionLines": [ /* ... */ ],
  "buyer": { /* ... */ },
  "dates": { "issued": "2026-09-22", "due": "2026-10-22" },
  "payment": { /* ... */ },
  "autoSend": { "email": true, "pa": true }
}

Pour une récurrence, le refus de finalisation automatique pour identité masquée laisse la facture générée en brouillon, sans numéro. Le propriétaire reçoit la notification existante recurring_failed, avec un lien vers la facture et l’action à effectuer ; ses préférences de notification et d’e-mail s’appliquent. Pour une autre erreur technique, l’avis invite à vérifier la facture : une étape postérieure à sa finalisation peut avoir échoué. L’avis de génération réussie n’est pas envoyé pour ce même échec.

Cycle de vie

Une facture évolue à travers une machine à états déterministe. Les transitions invalides retournent 400 invalid_status_transition (type invalid_request_error).

StatutDescriptionTransitions possibles
draftBrouillon éditablefinalized (irréversible), → suppression
finalizedFinalisée — numéro attribué, immuablesent (manuel) ou sending (PA), → paid (comptant)
sentEnvoyée par e-mail ou remise manuellementpartially_paid, paid
sendingEn cours d’envoi — dépôt à confirmer par la plateformedeposited, rejected
depositedDéposée (fr:200) sur la plateformetransmitted
transmittedÉmise (fr:201) par la plateformeavailable
availableMise à disposition (fr:203) de l'acheteurreceived
receivedPrise en charge (fr:204) par l'acheteurapproved, refused, suspended
approvedApprouvée (fr:205)partially_paid, paid
refusedRefusée (fr:210) par l'acheteur(terminal)
suspendedSuspendue par l'acheteurapproved, refused
rejectedRejetée (fr:213) par la plateforme (code et motif dans einvoicing.rejectionCode et einvoicing.rejectionReason)sending (renvoi direct par send, même numéro)
partially_paidPartiellement payéepaid
paidPayée (fr:212) intégralementsending (dépôt PA d'une facture émise acquittée ; la transmission suit ensuite son cycle, l'encaissement reste acquis)
overdueEn retard — échéance dépasséepaid, partially_paid

Irréversibilité. Une fois finalisée, une facture ne peut plus revenir à draft ni être modifiée. C'est la conséquence directe du caractère opposable de la numérotation. Pour corriger une facture finalisée, émettez un avoir de régularisation.

Finaliser

La finalisation est une opération atomique qui réserve un numéro depuis le compteur de l'entreprise et passe la facture à finalized. Le numéro n'est jamais réutilisé, même si la facture est ensuite annulée ou rejetée (le numéro est brûlé).

$ curl -X POST https://facturino.com/api/v1/invoices/inv_a1b2c3d4e5f6/finalize \
  -H "Authorization: Bearer fac_test_..."

# Réponse — numéro attribué, statut = "finalized"
{
  "id": "inv_a1b2c3d4e5f6",
  "status": "finalized",
  "number": "FAC2026-00042",
  /* ... */
}

Si la finalisation échoue côté Facturino (timeout, erreur transitoire), un retry avec la même Idempotency-Key retourne le numéro déjà attribué — pas de doublon. Voir Idempotence.

Facture déjà encaissée : émise acquittée

Quand le règlement est reçu avant l'émission — paiement en ligne, au comptoir, prélèvement immédiat —, transmettez-le dans le corps facultatif de finalize. La numérotation et l'encaissement sont appliqués dans la même transaction : le PDF et le Factur-X d'origine sont donc rendus sur une facture déjà réglée, avec la mention « PAYÉE » et les balises BT-113 / BT-115 renseignées.

L'objet payment est exactement celui de POST /v1/invoices/:id/payments : mêmes champs, mêmes méthodes, montant en centimes entiers. Le sous-document d'encaissement créé est indistinguable de celui d'un règlement enregistré après coup.

# Facture déjà encaissée : elle est ÉMISE acquittée, en un seul appel
$ curl -X POST https://facturino.com/api/v1/invoices/inv_a1b2c3d4e5f6/finalize \
  -H "Authorization: Bearer fac_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "payment": {
      "amount": 120000,
      "method": "card",
      "reference": "ch_3Kj9aLZ",
      "paidAt": "2026-05-10T12:00:00.000Z"
    }
  }'

# Réponse — numéro attribué ET encaissement appliqué, dans la même transaction
{
  "id": "inv_a1b2c3d4e5f6",
  "status": "paid",
  "number": "FAC2026-00042",
  "totals": { "totalTTC": 120000, "amountPaid": 120000, "amountDue": 0 },
  /* ... */
}

Tout ou rien. Un encaissement refusé — au-delà du reste dû — répond 422 payment_exceeds_amount_due avec error.issues pointant payment.amount, et la finalisation n'a pas lieu : aucun numéro n'est brûlé, la facture reste un brouillon.

L'original est figé à l'émission ; les copies PDF suivent les encaissements ; le Factur-X ne change jamais. Un règlement postérieur à l'émission fait redessiner la copie PDF de présentation, qui affiche alors le solde à jour ; le Factur-X, lui, reste le document d'origine — c'est lui qui porte la valeur probante et qui est haché dans la chaîne d'archivage. Tant que la copie n'est pas redessinée, GET /v1/invoices/:id/pdf répond 202 avec un job plutôt que de servir une copie périmée.

Déposer via une Plateforme Agréée

En mode live avec une PA configurée (voir Choisir sa PA), send dépose la facture sur la PA choisie via son API ou son flux EDI.

$ curl -X POST https://facturino.com/api/v1/invoices/inv_.../send \
  -H "Authorization: Bearer fac_live_..." \
  -H "Idempotency-Key: send-FAC2026-00042"

# Réponse 202 Accepted — dépôt asynchrone via la PA configurée sur l'entreprise
{
  "id": "inv_a1b2c3d4e5f6",
  "object": "invoice",
  "status": "sending"
}

L'opération est asynchrone — la réponse 202 renvoie l'invoice avec status: "sending". Suivez l'avancement via GET /v1/invoices/{id}/status ou les webhooks : les transitions suivantes (deposited, transmitted, available…) y sont émises.

status est une projection de trois axes lisibles séparément sur la facture : documentStatus, transmissionStatus (avec transmissionDetail) et paymentStatus. Pendant le transit (sending, deposited, transmitted…) c'est la transmission qui donne le mot ; ensuite l'encaissement l'emporte. Une facture encaissée avant son dépôt reste donc status: "paid" une fois approuvée, avec transmissionStatus: "approved" ; l'événement invoice.approved est émis même si status ne change pas.

Les octets déposés sont l'original Factur-X archivé tant qu'il satisfait les règles du CIUS-FR. Si un document figé avant un correctif du générateur ne les satisfait plus (par exemple BT-23, règle BR-FR-08), le dépôt envoie un CII régénéré depuis le document tel qu'émis (même numéro, mêmes montants, encaissement à l'émission et non encaissements postérieurs), enregistré sous files.correctedXmlPath et tracé dans lifecycle ; l'original archivé n'est jamais réécrit. Quand aucune régénération ne suffit, send répond document_not_conformant.

Production uniquement. send avec une clé fac_test_ simule le dépôt sans appel réel à la PA — les statuts sont synthétiques. Ne testez pas la facturation réelle avec une clé de test.

Le dépôt vérifie aussi l’identité figée de l’acheteur, y compris sur une facture finalisée avant ce contrôle. Un marqueur de non-diffusion dans le nom ou l’adresse bloque send avec 400 buyer_identity_not_disclosed, avant lecture des fichiers, régénération ou appel de plateforme ; param indique le champ en cause. Corrigez la fiche client puis établissez un avoir total d’annulation avant une facture de remplacement : le renvoi ne répare pas un instantané figé. Ce contrôle s’applique également en mode test.

Lire le suivi et les fichiers

einvoicing et files sont des objets en lecture seule. Un motif ou un artefact peut être absent sur un document ancien. Un identifiant PA peut être complété après un webhook sans changement de statut ni nouvel événement de cycle de vie.

Champ de einvoicingSignification
paId, paTransactionIdIdentifiants de facture et de transaction chez la plateforme.
paStatus, paStatusCodeDernier état et code brut reçus ; accepted à la soumission attend encore la confirmation du dépôt.
paErrorCode, rejectionReasonCode du dernier échec de dépôt (contrôle local ou plateforme) et motif du dernier rejet ou refus de la plateforme.
refusalReasonMotif du refus de l’acheteur, lorsqu’il est renseigné ; consulter aussi rejectionReason.
paIdempotencyKeyClé de dédoublonnage de la soumission.
peppolDeliveryIdIdentifiant de livraison Peppol.
ereportingIdDéclaration e-reporting de transactions associée.
sentAt, trackingIdHorodatage ISO de soumission et identifiant de suivi du flux.
submissionArtefactObjet { kind: "cii", path, generatedAt, correctedRules } : fichier préparé, date ISO et règles corrigées, par exemple BR-FR-08. Sa présence ne prouve pas l’acceptation par la plateforme.
previousSubmissionsTentatives closes sur la plateforme, de la plus ancienne à la plus récente : un dépôt rejeté renvoyé par send ouvre une nouvelle tentative sous le même numéro ; les identifiants, le statut et le motif de l’ancienne y sont conservés, les champs courants ne décrivent que la tentative en cours. Absent sans renvoi.

files.pdfPath désigne la copie de présentation ; files.facturxPath et files.xmlPath désignent l’original. files.correctedXmlPath désigne le CII corrigé préparé pour le dépôt. Ces champs sont optionnels et contiennent des chemins de stockage, pas des URL publiques. Les endpoints ci-dessous servent les formats de la facture ; correctedXmlPath permet de tracer le fichier préparé pour la plateforme.

Télécharger les formats

# PDF lisible — renvoie une URL signée si en cache
$ curl https://facturino.com/api/v1/invoices/inv_.../pdf \
  -H "Authorization: Bearer fac_test_..."

# 200 OK — URL de téléchargement temporaire (à suivre)
{
  "object": "file_url",
  "url": "https://storage.googleapis.com/.../facture.pdf?...",
  "expires_in": 900
}

# Si le fichier n'est pas encore généré → 202 Accepted (génération asynchrone)
{
  "id": "job_3k9d2",
  "object": "job",
  "type": "pdf",
  "status": "pending"
}

# Factur-X (PDF/A-3 avec XML CII intégré) — même contrat file_url / job
$ curl https://facturino.com/api/v1/invoices/inv_.../facturx \
  -H "Authorization: Bearer fac_test_..."

# XML CII brut (BR-FR validé Schematron) — finalized requis (draft → 400)
$ curl https://facturino.com/api/v1/invoices/inv_.../xml?format=cii \
  -H "Authorization: Bearer fac_test_..." \
  -o invoice-cii.xml

# XML UBL 2.1 (?format=ubl)
$ curl https://facturino.com/api/v1/invoices/inv_.../xml?format=ubl \
  -H "Authorization: Bearer fac_test_..." \
  -o invoice-ubl.xml

Les formats sont générés à la finalisation et mis en cache 90 jours dans Cloud Storage. GET /v1/invoices/:id/pdf (ou /facturx) renvoie un objet file_url (URL signée valable expires_in secondes) si le fichier est en cache, sinon un 202 avec un object: "job" à poller le temps de la (re)génération.

Statuts d'un job de rendu

GET /v1/jobs/:id renvoie download_url uniquement quand le rendu est à la fois terminé et encore à jour. Une copie que le document a dépassée n'est jamais servie.

StatutSignification
pending / processingRendu en cours : continuez à poller.
completedRendu disponible : download_url est renseigné.
supersededTerminal, sans livrable. Un encaissement, une annulation ou un remboursement a modifié la facture après la publication de ce rendu. Ce n'est pas une erreur : redemandez GET /v1/invoices/:id/pdf, qui publiera un rendu à jour. Le champ superseded indique la révision visée et la révision courante.
failedLa génération a échoué ; error décrit la cause.

Une même facture et une même révision ne produisent qu'un seul job : deux demandes simultanées reçoivent le même identifiant plutôt que deux rendus du même document. De nouveaux statuts peuvent apparaître : tolérez les valeurs inconnues.

Conformité Factur-X

  • Profil : EN16931 par défaut (BASIC WL ou BASIC sur demande)
  • Variantes XML : CII (UN/CEFACT) ou UBL 2.1 selon le besoin de la PA
  • Validation Schematron : règles EN 16931 appliquées au CII et à l’UBL ; règles CIUS-FR locales appliquées au CII seulement avant retour 200
  • PDF/A-3b : conforme ISO 19005-3 avec XMP fx:DocumentType=INVOICE

Lister et filtrer

$ curl "https://facturino.com/api/v1/invoices?status=overdue&date_from=2026-01-01&sort=created&limit=50&expand=customer" \
  -H "Authorization: Bearer fac_test_..."

Paramètres de filtrage supportés :

Le CII porte le cadre de facturation BT-23 exigé par le CIUS-FR (règle BR-FR-08) : la lettre dit la nature de l'opération (B biens, S services, M mixte, dérivée des lignes décidées), le chiffre le cas (1 dépôt ordinaire, 2 facture émise acquittée, reste dû nul). Il est calculé à l'émission ; le validateur le contrôle avant tout dépôt.

ParamètreTypeDescription
statusstringFiltrer par statut (un seul à la fois)
date_from / date_toISO datePlage de dates (création)
convertedFromstringFactures issues d'un devis donné (quo_xxx)
sortstringChamp de tri (created ou updated, décroissant)
expandstringHydrater des ressources liées, séparées par des virgules (customer, items.product) — apparaissent sous expanded
limitintegerNombre d'éléments par page (défaut 25, max 100)

Annuler un paiement

Un paiement enregistré par erreur peut être annulé. Le paiement est conservé au statut cancelled (la piste d'audit n'est jamais effacée), le solde restant dû est recalculé et le statut de la facture réajusté. L'annulation est refusée si le paiement a déjà été déclaré à l'administration (e-reporting) : il faut alors passer une écriture rectificative.

$ curl -X POST https://facturino.com/api/v1/invoices/inv_.../payments/pay_.../cancel \
  -H "Authorization: Bearer fac_live_..."

# Le paiement passe à "cancelled" (piste d'audit conservée) et le solde est recalculé.
{
  "id": "pay_...",
  "object": "payment",
  "status": "cancelled",
  "invoiceStatus": "partially_paid",
  "amountDue": 60000
}

Piste d'audit fiable (PAF)

Conformément à l'article L.102 B du LPF et au BOI-CF-COM-10-10-30-10, chaque facture finalisée est associée à une chaîne de hash chronologique (SHA-256) reliant chronologiquement les factures successives. GET /v1/invoices/:id/verify permet de vérifier qu'aucune facture n'a été insérée, modifiée ou supprimée a posteriori.

L'export PAF PDF (réservé au plan Pro+) est généré via POST /v1/invoices/:id/audit-trail/pdf et inclut la totalité des événements du cycle de vie, signés et horodatés.

Étapes suivantes

Contrat complet du suivi électronique

Ces champs sont en lecture seule. Un champ optionnel peut être absent d’un document ancien ; la colonne Nullable distingue cette absence d’une valeur null effectivement écrite. Les dates sont des chaînes ISO 8601.

einvoicing

ChampTypeNullableDescription
paIdstringouiIdentifiant de la facture sur la plateforme.
paStatusstringouiDernier état communiqué par la plateforme ; accepted à la soumission signifie fichier accepté, dépôt encore à confirmer.
paStatusCodestringouiCode brut du statut plateforme, par exemple fr:200.
paTransactionIdstringouiIdentifiant de la transaction de soumission.
paErrorCodestringouiCode du dernier échec de dépôt : contrôle local ou réponse de la plateforme.
rejectionReasonstringouiMotif brut de la plateforme ou de l’acheteur, verbatim ; constat local pour la source facturino. Ne contient pas de code ou de note reconstruits. Null si absent.
rejectionCategorystringouiLecture stable parmi onze catégories. Priorité : code local, code DGFiP, code HTTP ; seul le pré-contrôle annuaire Super PDP dispose d’un repli textuel. REJ_ADR = addressing_error, REJ_SEMAN = semantic_error, REJ_SYNT/REJ_XSD = format_invalid, REJ_DOUBLON = duplicate, AUTRE = other (explication dans rejectionNote). Le statut fr:213 seul ne classe pas en sémantique. Null au renvoi. Valeurs : buyer_not_in_directory, addressing_error, other, format_invalid, semantic_error, duplicate, platform_auth, platform_unavailable, refused_by_buyer, suspended, unknown.
refusalReasonstringouiMotif de refus de l’acheteur, lorsqu’il est fourni dans ce champ.
paIdempotencyKeystringouiClé de dédoublonnage de la soumission.
peppolDeliveryIdstringouiIdentifiant de livraison Peppol.
ereportingIdstringouiDéclaration e-reporting de transactions associée.
sentAtstringouiHorodatage de soumission à la plateforme.
trackingIdstringouiIdentifiant de suivi du flux plateforme.
submissionArtefactobjectouiCII préparé pour la soumission après correction des règles CIUS-FR connues ; l’original archivé reste intact. Sa présence ne confirme pas l’acceptation par la plateforme.
previousSubmissionsarray[]nonTentatives closes de ce document sur la plateforme, de la plus ancienne à la plus récente : un dépôt rejeté renvoyé sous le même numéro ouvre une nouvelle tentative, dont les identifiants courants figurent ci-dessus. Absent tant qu’aucun renvoi n’a eu lieu.
rejectionCodestringouiCode normalisé du motif DGFiP (REJ_ADR, REJ_SEMAN, REJ_SYNT, REJ_XSD, REJ_DOUBLON, AUTRE), HTTP plateforme (SUPER_PDP_400…) ou local (buyer_not_in_directory). Null si aucun code de motif n’est fourni ; les codes de statut fr:* restent dans paStatusCode. Remis à null au renvoi.
rejectionSourcestringouiAuteur du verdict enregistré par le producteur : platform (fr:213, réponse HTTP), buyer (fr:210, fr:207, fr:208), facturino (contrôle avant dépôt). Null après un renvoi ou pour un document ancien sans source enregistrée. Jamais déduit du motif. Valeurs : platform, buyer, facturino.
rejectionNotestringouiNotes jointes par la plateforme ou l’acheteur, verbatim, concaténées par un retour à la ligne. Remises à null au renvoi.
routingIdentifierstringouiElectronic reception address carried in the submitted CII (BT-49), including its scheme. When the directory returns a different active address, the CII is regenerated for the same submission and idempotency key; legal identifiers and the archived original remain unchanged.
senderRoutingIdentifierstringnonAdresse électronique du vendeur résolue pour BT-34 du CII soumis, en lecture seule ; absente sans résolution spécifique.
buyerReachableAtstringouiLast daily check that found an active buyer reception address after a buyer_not_in_directory rejection. Cleared on resend; never triggers an automatic deposit.
directoryCheckedAtstringouiLast daily directory consultation, including absent or indeterminate answers. Cleared on resend.
ereportingPaymentIdstringouiIdentifiant de la déclaration d’encaissement e-reporting liée à cette facture.

einvoicing.submissionArtefact

ChampTypeNullableDescription
kindstringnonChamp en lecture seule ; peut être absent des documents historiques. Valeurs : cii.
pathstringnonChemin de stockage du CII préparé.
generatedAtstringnonChamp en lecture seule ; peut être absent des documents historiques.
sellerRoutingIdentifierstringnonAdresse vendeur employée pour BT-34 de cet artefact, en lecture seule ; absente sans correction de cette adresse.
correctedRulesarray[]nonChamp en lecture seule ; peut être absent des documents historiques.
routingIdentifierstringnonActive directory address carried by this regenerated CII (BT-49), including its scheme.

einvoicing.previousSubmissions[]

ChampTypeNullableDescription
paIdstringouiChamp en lecture seule ; peut être absent des documents historiques.
paTransactionIdstringouiChamp en lecture seule ; peut être absent des documents historiques.
paIdempotencyKeystringouiChamp en lecture seule ; peut être absent des documents historiques.
paStatusstringouiChamp en lecture seule ; peut être absent des documents historiques.
paStatusCodestringouiChamp en lecture seule ; peut être absent des documents historiques.
paErrorCodestringouiChamp en lecture seule ; peut être absent des documents historiques.
rejectionReasonstringouiChamp en lecture seule ; peut être absent des documents historiques.
rejectionCategorystringouiLecture du rejet de cette tentative close. Valeurs : buyer_not_in_directory, addressing_error, other, format_invalid, semantic_error, duplicate, platform_auth, platform_unavailable, refused_by_buyer, suspended, unknown.
sentAtstringouiChamp en lecture seule ; peut être absent des documents historiques.
closedAtstringnonOuverture de la tentative suivante.
rejectionCodestringouiValeur archivée de einvoicing.rejectionCode pour cette tentative close.
rejectionSourcestringouiValeur archivée de einvoicing.rejectionSource pour cette tentative close. Valeurs : platform, buyer, facturino.
rejectionNotestringouiValeur archivée de einvoicing.rejectionNote pour cette tentative close.

Le renvoi conserve le numéro de facture, ouvre une nouvelle tentative, archive le verdict de la précédente et remet les champs de rejet et les dates d’annuaire à null. L’adresse de routage courante décrit les octets déposés ; sa présence ne prouve pas leur acceptation.

Les tentatives closes archivent les identifiants de dépôt, les champs de rejet et sentAt / closedAt. Les écritures actuelles n’y recopient pas l’adresse de routage, l’artefact ou les dates de revérification d’annuaire ; ces informations se lisent uniquement sur la tentative courante lorsqu’elles y sont présentes.

Exemple : facture rejetée pour incohérence d’adresse

{
  "id": "inv_00090",
  "object": "invoice",
  "number": "FAC2026-00090",
  "status": "rejected",
  "documentStatus": "finalized",
  "transmissionStatus": "rejected",
  "transmissionDetail": null,
  "paymentStatus": "unpaid",
  "type": "standard",
  "currency": "eur",
  "customer": {
    "ref": "cus_example",
    "snapshot": {
      "name": "INTEK CENTER",
      "address": {
        "line1": "1 rue Exemple",
        "postalCode": "75001",
        "city": "Paris",
        "country": "FR"
      }
    }
  },
  "items": [],
  "totals": {
    "totalHT": 990,
    "totalTVA": 198,
    "totalTTC": 1188,
    "amountPaid": 0,
    "amountDue": 1188
  },
  "einvoicing": {
    "paId": "dep_current",
    "paStatus": "rejected",
    "paStatusCode": "fr:213",
    "paTransactionId": null,
    "paErrorCode": null,
    "rejectionCode": "REJ_ADR",
    "rejectionSource": "platform",
    "rejectionReason": "REJ_ADR — Directory line matricule_plateforme (0037) does not match expected matricule (0022)",
    "rejectionNote": null,
    "rejectionCategory": "addressing_error",
    "refusalReason": null,
    "paIdempotencyKey": "submission_same_attempt",
    "peppolDeliveryId": null,
    "ereportingId": null,
    "ereportingPaymentId": null,
    "sentAt": "2026-09-07T12:36:00.000Z",
    "trackingId": null,
    "routingIdentifier": "0225:73282932000074",
    "buyerReachableAt": null,
    "directoryCheckedAt": null,
    "submissionArtefact": {
      "kind": "cii",
      "path": "invoices/inv_00090/submission.xml",
      "generatedAt": "2026-09-07T12:35:00.000Z",
      "correctedRules": [],
      "routingIdentifier": "0225:73282932000074"
    },
    "previousSubmissions": [
      {
        "paId": "dep_previous",
        "paTransactionId": null,
        "paIdempotencyKey": "submission_previous",
        "paStatus": "rejected",
        "paStatusCode": "fr:213",
        "paErrorCode": null,
        "rejectionReason": "AUTRE — Ce motif nécessite une explication en note de CDV.",
        "rejectionCode": "AUTRE",
        "rejectionSource": "platform",
        "rejectionNote": "L’adresse de réception doit être confirmée.",
        "rejectionCategory": "other",
        "sentAt": "2026-09-07T08:00:00.000Z",
        "closedAt": "2026-09-07T12:35:00.000Z"
      }
    ]
  },
  "livemode": true,
  "created": "2026-09-07T12:00:00.000Z",
  "updated": "2026-09-07T12:36:00.000Z"
}

Payment.fr212

ChampTypeNullableDescription
statestringnonChamp en lecture seule ; peut être absent des documents historiques. Valeurs : pending, awaiting_deposit, sent, blocked, reconciliation_required, failed.
sentAtstringouiChamp en lecture seule ; peut être absent des documents historiques.
lastErrorCodestringouiChamp en lecture seule ; peut être absent des documents historiques.
lastErrorReasonstringnonMots de la plateforme quand elle a refusé le statut (`lastErrorCode` `pa_lifecycle_rejected`). Absent sinon.
updatedAtstringnonChamp en lecture seule ; peut être absent des documents historiques.

fr212 est absent ou null quand aucune transmission « Encaissée » n’est due. awaiting_deposit attend un dépôt accepté, sans reprise par le cron ; blocked conserve le refus définitif dans lastErrorReason. Une erreur de transport ou une réponse 5xx relève de reconciliation_required.

Customer.warnings et TaxDecision.warnings contiennent les avertissements BuyerNatureWarning : code, message anglais et param. Ils ne bloquent pas la création. Sur les avoirs, relatedInvoiceNumber expose le numéro figé de la facture corrigée.

Les paiements exposent recorded_by : api pour une clé API, app pour un compte connecté, system pour une automatisation. Les montants restent en centimes. Les noms internes du stockage ne sont pas des champs de paiement publics.

Suivi des obligations

einvoicing.obligation, ereportingBlock.obligation, Payment.fr212.obligation et Payment.reportingFollowUp sont des projections en lecture seule, facultatives sur les documents historiques et nullables. Elles portent state (pending, processing, waiting, reconciling, attention_required, completed), reasonCode, reasonSource (platform, buyer, facturino ou null), owner (facturino, customer ou null), action et nextAttemptAt (ISO 8601 ou null).

action vaut submit, follow_status, retry, reconcile, watch_directory, investigate, correct_source, review_buyer_refusal, connect_platform ou null. connect_platform signifie qu’aucune plateforme ne peut porter l’obligation tant que le client n’en a pas connecté ou reconfiguré une ; Facturino reprend ensuite automatiquement. investigate désigne un incident technique traité par Facturino, sans action du client. Une date indique la prochaine tentative ou vérification prévue ; null n’est pas une instruction de relance pour l’intégrateur. Les verrous de traitement et les faits de transport privés ne sont jamais exposés. Le motif original reste dans rejectionReason ou paRejectionReason, séparément de paRejectionCode et des messages de suivi.

Le statut comptable payé ne confirme ni le dépôt, ni l’acceptation, ni l’envoi d’Encaissée. Le serveur assure les reprises techniquement sûres après la demande initiale ; un refus métier de l’acheteur ne permet aucun redépôt automatique.