Facturino / Documentation / Factures

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é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/finalizeFinaliser → attribue le numéro et passe à finalized
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 Stripe
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",
    "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.

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).
# 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 : 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",
  "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).

StatutDescriptionTransitions possibles
draftBrouillon éditablefinalized (irréversible), → suppression
finalizedNuméro attribué, immuablesent (manuel) ou sending (PA), → paid (comptant)
sendingDépôt en cours via PAdeposited, rejected
depositedDéposée sur la PAtransmitted
transmittedTransmise à la DGFiPavailable
availableMise à disposition de l'acheteurreceived
receivedPrise en charge acheteurapproved, refused, suspended
approvedApprouvéepartially_paid, paid
refusedRefusée par l'acheteur(terminal)
suspendedSuspendue par l'acheteurapproved, refused
rejectedRejetée par la PAfinalized (re-dépôt même numéro)
partially_paidPaiement partielpaid
paidPayée intégralement(terminal)
overdueÉ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.

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è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