Suivez ce tutoriel pour créer, finaliser et envoyer une facture électronique conforme Factur-X EN 16931 via l'API REST Facturino. Du client au PDF/A-3 avec XML CII intégré, en 6 étapes.
Compte Facturino
Créez un compte gratuit — aucune carte bancaire requise.
Clé API test
Paramètres → API → Nouvelle clé. Préfixe fac_test_ pour le mode sandbox.
Base URL
https://facturino.com/api/v1/ Authentification
Authorization: Bearer fac_test_... Content-Type
application/json
Commencez par créer un client avec POST /v1/customers.
Le SIRET est validé via l'algorithme de Luhn côté serveur. Si le SIRET est connu de l'API Sirene,
la raison sociale et l'adresse sont auto-complétées.
SIRET validé Luhn — rejeté si invalide (erreur 422)
Auto-complétion Sirene — raison sociale et adresse pré-remplies
Numéro TVA — vérifié via VIES pour les clients intracommunautaires
$ curl -X POST https://facturino.com/api/v1/customers \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-d '{
"name": "Durand & Associés SARL",
"siret": "73282932000074",
"vatNumber": "FR44732829320",
"address": {
"line1": "15 rue de la Paix",
"city": "Paris",
"postalCode": "75002",
"country": "FR"
},
"contacts": [{ "email": "compta@durand-associes.fr" }]
}'
# Réponse
{
"id": "cus_8f2k4m9n",
"name": "Durand & Associés SARL",
"siret": "73282932000074",
"vatNumber": "FR44732829320",
"livemode": false
}
Créez un brouillon avec POST /v1/invoices.
Le brouillon est modifiable à volonté avant la finalisation. Utilisez le header
Idempotency-Key
pour éviter les doublons en cas de retry.
Statut initial : draft — modifiable librement
Idempotency-Key — même clé = même résultat pendant 24h
Pas encore de numéro — attribué à la finalisation uniquement
$ curl -X POST https://facturino.com/api/v1/invoices \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: qs-inv-001" \
-d '{
"customerId": "cus_8f2k4m9n",
"buyer": {
"companyName": "Durand & Associés SARL",
"siret": "73282932000074",
"address": { "line1": "15 rue de la Paix", "postalCode": "75002", "city": "Paris", "country": "FR" }
},
"lines": [
{
"description": "Prestation de conseil",
"quantity": "1", "unit": "flat_rate",
"unitPrice": 150000, "vatRate": 2000, "vatCode": "S"
}
],
"dates": { "issued": "2026-03-25", "due": "2026-04-30" },
"payment": {
"terms": "30 jours net", "termsDays": 30, "method": "transfer",
"latePaymentRate": "3 fois le taux légal", "collectionFee": "40.00 EUR"
},
"notes": "Merci pour votre confiance."
}'
# Réponse — montants en centimes entiers (symétrie entrée/sortie)
{
"id": "inv_3p7r2x5q",
"object": "invoice",
"status": "draft",
"livemode": false,
"customer": { "ref": "cus_8f2k4m9n" },
"dates": { "issued": "2026-03-25", "due": "2026-04-30" },
"totals": {
"totalHT": 150000,
"totalVAT": 30000,
"totalTTC": 180000,
"currency": "eur"
}
}
Ajoutez des lignes de facturation avec PATCH /v1/invoices/:id.
Les totaux (HT, TVA, TTC) sont recalculés automatiquement à chaque modification, ligne par ligne avec un arrondi conforme à la norme EN 16931 (au plus proche, demi-vers-le-haut sur 2 décimales).
Montants en centimes —
65000 = 650,00 EUR.
Aucun flottant, aucun arrondi ambigu.
TVA en centièmes de pourcent —
2000 = 20,00 %.
Permet les taux exotiques (5,50 % = 550).
Calculs automatiques — line_total, line_tax et totaux globaux
PATCH, pas PUT — mises à jour partielles uniquement
$ curl -X PATCH https://facturino.com/api/v1/invoices/inv_3p7r2x5q \
-H "Authorization: Bearer fac_test_..." \
-H "Content-Type: application/json" \
-d '{
"lines": [
{
"description": "Développement web — Sprint 3",
"quantity": "3",
"unit": "day",
"unitPrice": 65000,
"vatRate": 2000,
"vatCode": "S"
},
{
"description": "Hébergement cloud (avril 2026)",
"quantity": "1",
"unit": "flat_rate",
"unitPrice": 12000,
"vatRate": 2000,
"vatCode": "S"
}
]
}'
# Réponse (totaux calculés automatiquement)
{
"id": "inv_3p7r2x5q",
"status": "draft",
"items": [
{
"description": "Développement web — Sprint 3",
"quantity": "3",
"unit": "day",
"unitPrice": 65000,
"vatRate": 2000,
"vatCode": "S",
"lineAmount": 195000,
"vatAmount": 39000,
"lineTotal": 234000
},
{
"description": "Hébergement cloud (avril 2026)",
"quantity": "1",
"unit": "flat_rate",
"unitPrice": 12000,
"vatRate": 2000,
"vatCode": "S",
"lineAmount": 12000,
"vatAmount": 2400,
"lineTotal": 14400
}
],
"totals": {
"totalHT": 207000,
"totalVAT": 41400,
"totalTTC": 248400
}
}
Appelez POST /v1/invoices/:id/finalize
pour verrouiller la facture. Un numéro séquentiel définitif est attribué (ex: FAC2026-00001)
et un hash SHA-256 est calculé pour la chaîne d'archivage.
La finalisation est irréversible. Une facture finalisée ne peut plus être modifiée.
Pour corriger une erreur, vous devrez émettre un avoir (POST /v1/credit-notes).
Numéro définitif — séquentiel, sans trou (transaction atomique)
Hash SHA-256 — intégrité vérifiable via /verify
Mentions légales — auto-générées selon CGI et régime TVA
$ curl -X POST https://facturino.com/api/v1/invoices/inv_3p7r2x5q/finalize \
-H "Authorization: Bearer fac_test_..."
# Réponse
{
"id": "inv_3p7r2x5q",
"status": "finalized",
"number": "FAC2026-00001",
"totals": {
"totalHT": 207000,
"totalVAT": 41400,
"totalTTC": 248400
},
// La chaîne de hash d'archivage est scellée à la génération du
// Factur-X (étape suivante) ; vérifiable ensuite via GET /invoices/:id/verify
"dates": {
"issued": "2026-03-24T14:30:00Z",
"due": "2026-04-30T00:00:00Z"
}
}
Transmettez la facture à votre destinataire via
POST /v1/invoices/:id/send.
Facturino transmet la facture à la PA connectée par le client — un
connecteur dédié
(Super PDP, Iopole, B2Brouter, Seqino) ou le
connecteur générique AFNOR
pour toute autre PA, configuré côté interface.
Vous pouvez aussi télécharger la facture (GET /v1/invoices/:id/facturx) pour dépôt manuel.
Les changements de statut sont notifiés en temps réel via webhooks.
En mode sandbox (fac_test_),
l'envoi est simulé. Aucune facture n'est transmise à une PA réelle. Utilisez
/v1/sandbox/simulate-status
pour tester les transitions de statut.
14 statuts DGFiP — de deposited à paid, en temps réel
Webhooks — invoice.status.* à chaque transition
Exactly-once — idempotency key PA pour éviter les doublons
$ curl -X POST https://facturino.com/api/v1/invoices/inv_3p7r2x5q/send \
-H "Authorization: Bearer fac_test_..."
# Réponse 202 — envoi en cours
{
"id": "inv_3p7r2x5q",
"object": "invoice",
"status": "sending"
}
# Suivre le statut PA via GET /status
$ curl https://facturino.com/api/v1/invoices/inv_3p7r2x5q/status \
-H "Authorization: Bearer fac_test_..."
{
"status": "deposited",
"einvoicing": {
"paStatus": "deposited",
"paId": "42"
},
"dates": {
"due": "2026-04-30",
"finalizedAt": "2026-03-25T10:00:00Z"
}
}
Récupérez le Factur-X avec GET /v1/invoices/:id/facturx.
Le fichier est un PDF/A-3b avec le XML CII D22B intégré en pièce jointe. Profil EN 16931,
validation Schematron CIUS-FR automatique, métadonnées XMP conformes.
PDF/A-3b — archivable, lisible par tout lecteur PDF
XML CII intégré — factur-x.xml, AFRelationship "Alternative"
Profil EN 16931 — conforme CIUS-FR, ZUGFeRD 2.4
Aussi disponible — /pdf et /xml séparément
# 1. Recuperer l'URL signee (JSON, pas le binaire)
$ curl https://facturino.com/api/v1/invoices/inv_3p7r2x5q/facturx \
-H "Authorization: Bearer fac_test_..."
# 200 -> fichier pret :
{ "object": "file_url", "url": "https://storage.../facture.pdf?...", "expires_in": 900 }
# 202 -> generation en cours : { "object": "job", "id": "job_...", "status": "pending" }
# (repoller l'endpoint jusqu'a recevoir "file_url")
# 2. Telecharger le PDF/A-3b depuis l'URL signee (valide 15 min)
$ curl -o facture-FAC2026-00001.pdf "https://storage.../facture.pdf?..."
# PDF/A-3b avec XML CII integre, profil EN16931, CIUS-FR
# Metadata XMP : conformance "B", factur-x.xml Les conventions essentielles de l'API Facturino pour bien démarrer.
Tous les montants sont des entiers en centimes d'euros.
150000 = 1 500,00 EUR.
Aucun flottant, aucune perte de précision.
Les taux sont en centièmes de pourcent.
2000 = 20,00 %,
550 = 5,50 %.
Arrondi conforme EN 16931, au plus proche.
De draft à
paid, en passant par
deposited,
transmitted et
approved.
Transitions validées côté serveur.
Préfixe fac_test_ pour le sandbox (données isolées, aucun envoi réel).
Préfixe fac_live_ pour la production.
Les environnements sont strictement cloisonnés.
Header Idempotency-Key sur les POST.
Même clé = même résultat pendant 24h. Indispensable pour les retries réseau.
Chaque erreur contient type,
code,
message,
doc_url et
hint.
| Champ | Valeur API | Affichage | Convention |
|---|---|---|---|
| unitPrice | 65000 | 650,00 EUR | Centimes |
| vatRate | 2000 | 20,00 % | Centièmes % |
| vatRate | 550 | 5,50 % | Centièmes % |
| discountPercent | 500 | 5,00 % | Centièmes % |
| totalTTC | 248400 | 2 484,00 EUR | Centimes |
Arrondi : chaque ligne est arrondie à 2 décimales (mode demi-vers-le-haut, le 0,5 monte), puis les lignes sont sommées. Conforme à la norme EN 16931.
Les 6 étapes en un coup d'oeil, avec les endpoints et statuts correspondants.
| Étape | Méthode | Endpoint |
|---|---|---|
| 1. Client | POST | /v1/customers |
| 2. Brouillon | POST | /v1/invoices |
| 3. Lignes | PATCH | /v1/invoices/:id |
| 4. Finaliser | POST | /v1/invoices/:id/finalize |
| 5. Envoyer | POST | /v1/invoices/:id/send |
| 6. Factur-X | GET | /v1/invoices/:id/facturx |
PDF/A-3b + XML CII
Cross-Industry Invoice
Universal Business Language
PDF classique lisible
Votre première facture est envoyée. Voici les prochaines étapes pour aller plus loin.
Explorez les 127+ endpoints, testez les requêtes en direct et consultez les schémas OpenAPI 3.1.
Node.js, Python, PHP, Go. Typage complet, gestion d'erreurs intégrée, pagination automatique.
Recevez des notifications push signées HMAC-SHA256 pour chaque changement de statut.
Créez des devis convertibles en facture, émettez des avoirs liés. Même API, même logique.
Fixtures pré-chargées, simulation de statuts PA, reset instantané. Idéal pour les tests CI/CD.
Tout comprendre sur le PDF/A-3, le XML CII D22B, les profils EN 16931 et la conformité CIUS-FR.
Créez votre compte, obtenez une clé API test et envoyez votre première facture conforme en quelques minutes. Plan gratuit sans carte bancaire.
Besoin d'aide ? Contacter le support