Factures
L'objet invoice représente une facture B2B française conforme à la norme EN16931 et au profil 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.
Endpoints
| Méthode | Chemin | Description |
|---|---|---|
| POST | /v1/invoices | Créer un brouillon |
| GET | /v1/invoices | Lister les factures (filtres, pagination) |
| GET | /v1/invoices/:id | Récupérer une facture |
| PATCH | /v1/invoices/:id | Modifier un brouillon (seuls les drafts sont éditables) |
| DELETE | /v1/invoices/:id | Supprimer un brouillon (soft-delete) |
| POST | /v1/invoices/:id/finalize | Finaliser → attribue le numéro et passe à finalized |
| POST | /v1/invoices/:id/send | Déposer via la Plateforme Agréée |
| POST | /v1/invoices/:id/email | Envoyer par email avec PDF en pièce jointe |
| POST | /v1/invoices/:id/remind | Envoyer une relance de paiement |
| POST | /v1/invoices/:id/clone | Dupliquer en brouillon |
| POST | /v1/invoices/:id/cancel | Annuler un brouillon |
| GET | /v1/invoices/:id/pdf | PDF lisible |
| GET | /v1/invoices/:id/facturx | Factur-X (PDF/A-3 + XML CII) |
| GET | /v1/invoices/:id/xml | XML brut (CII ou UBL via ?format=) |
| POST | /v1/invoices/:id/payments | Enregistrer un paiement |
| GET | /v1/invoices/:id/payments | Lister les paiements |
| POST | /v1/invoices/:id/payments/:paymentId/cancel | Annuler un paiement (piste d'audit conservée) |
| POST | /v1/invoices/:id/payment-link | Créer un lien de paiement Stripe |
| GET | /v1/invoices/:id/status | Statut courant (poll-friendly) |
| GET | /v1/invoices/:id/events | Historique du cycle de vie |
| GET | /v1/invoices/:id/verify | Vérifier l'intégrité de la chaîne de hash |
| GET | /v1/invoices/:id/audit-trail | Piste 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",
"buyer": {
"companyName": "Durand & Associés",
"siret": "73282932000074",
"address": {
"line1": "10 rue de Rivoli",
"postalCode": "75001", "city": "Paris", "country": "FR"
}
},
"lines": [
{
"description": "Développement web — Sprint 3",
"quantity": "1",
"unit": "flat_rate",
"unitPrice": 150000,
"vatRate": 2000,
"vatCode": "S"
}
],
"dates": { "issued": "2026-04-22", "due": "2026-05-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",
"number": null,
"livemode": false,
"currency": "eur",
"customer": {
"ref": "cus_8f2k4m9n",
"snapshot": {
"name": "Durand & Associés",
"siret": "73282932000074"
}
},
"items": [
{
"id": "li_3k9d2",
"description": "Développement web — Sprint 3",
"quantity": "1",
"unit": "flat_rate",
"unitPrice": 150000,
"vatRate": 2000,
"vatCode": "S",
"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,
"paIdempotencyKey": null,
"peppolDeliveryId": null
},
"files": {
"pdfPath": null,
"xmlPath": null
},
"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 %). Permet 2 décimales exactes. - 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 sert
à générer les mentions légales obligatoires sur le PDF et le XML Factur-X.
| Code | Libellé | Usage typique |
|---|---|---|
S | Standard rate | Taux normal (20 %, 10 %, 5,5 %, 2,1 %) |
Z | Zero rate | Taux zéro (livres, presse spécifique…) |
E | Exempt | Exonération (formation pro, médical…) |
AE | Reverse charge | Autoliquidation par l'acquéreur (B2B intra-UE, sous-traitance BTP…) |
G | Export | Export hors UE (TVA non applicable) |
IC | Intracommunautaire | Livraison intra-UE entre assujettis |
K | VAT exempt EU | Service intracommunautaire (article 196) |
O | Out of scope | Opération hors champ TVA |
VATEX-FR-FRANCHISE | Franchise en base | Ré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 (typedeposit, 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).
# 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",
"buyer": { /* ... */ },
"lines": [ /* ... */ ],
"dates": { "issued": "2026-04-22", "due": "2026-06-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 :emailenvoie au client,padépose sur la Plateforme Agréée connectée (asynchrone, statutsending). ImpliqueautoFinalize.
# One-shot : créer + finaliser + envoyer (email au client ET dépôt PA) en un appel.
{
"customerId": "cus_8f2k4m9n",
"buyer": { /* ... */ },
"lines": [ /* ... */ ],
"dates": { "issued": "2026-04-22", "due": "2026-05-22" },
"payment": { /* ... */ },
"autoSend": { "email": true, "pa": true }
} Cycle de vie
Une facture évolue à travers une machine à états déterministe. Les transitions invalides retournent 400 invalid_status_transition (type invalid_request_error).
| Statut | Description | Transitions possibles |
|---|---|---|
draft | Brouillon éditable | → finalized (irréversible), → suppression |
finalized | Numéro attribué, immuable | → sent (manuel) ou sending (PA), → paid (comptant) |
sending | Dépôt en cours via PA | → deposited, rejected |
deposited | Déposée sur la PA | → transmitted |
transmitted | Transmise à la DGFiP | → available |
available | Mise à disposition de l'acheteur | → received |
received | Prise en charge acheteur | → approved, refused, suspended |
approved | Approuvée | → partially_paid, paid |
refused | Refusée par l'acheteur | (terminal) |
suspended | Suspendue par l'acheteur | → approved, refused |
rejected | Rejetée par la PA | → finalized (re-dépôt même numéro) |
partially_paid | Paiement partiel | → paid |
paid | Payée intégralement | (terminal) |
overdue | Échéance dépassée | → paid, 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.
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.
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.
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.
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 BR (Business Rules) EN16931 et BR-FR (CIUS-FR) appliquées 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 :
| Paramètre | Type | Description |
|---|---|---|
status | string | Filtrer par statut (un seul à la fois) |
date_from / date_to | ISO date | Plage de dates (création) |
convertedFrom | string | Factures issues d'un devis donné (quo_xxx) |
sort | string | Champ de tri (created ou updated, décroissant) |
expand | string | Hydrater des ressources liées, séparées par des virgules (customer, items.product) — apparaissent sous expanded |
limit | integer | Nombre 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
- Clients — créer le destinataire avant la facture
- Avoirs — régulariser une facture finalisée
- Webhooks — suivre le cycle de vie sans polling
- Plateformes Agréées — choisir et configurer sa PA
- Référence interactive — endpoint par endpoint