API HTTP
Trois endpoints. Tout est en JSON ou multipart, réponses en PDF binaire (sauf /health).
Aucune authentification — limite de débit nginx : 10 req/s par IP.
POST
/generate
Génère une facture Factur-X (PDF/A-3 + XML CII embarqué, profil EN 16931). Le PDF visuel est produit côté serveur à partir des données structurées.
Requête
Content-Type: application/json
{
"invoice_number": "2025-001", // requis
"invoice_date": "2025-05-21", // requis, ISO 8601 (YYYY-MM-DD)
"currency": "EUR", // optionnel, défaut EUR
"due_date": "2025-06-21", // optionnel
"delivery_date": "2025-05-21", // optionnel (date de prestation)
"payment_terms": "Paiement à 30 jours", // optionnel
"iban": "FR76 1234...", // optionnel, affiché dans le pied de page
"legal_notice": "Texte légal personnalisé", // optionnel
"seller": { // requis
"name": "Entreprise XYZ", // requis
"address": "123 Rue de la Paix\n75001 Paris", // requis
"vat_id": "FR12345678901", // optionnel, préfixe pays auto-ajouté si absent
"country": "FR", // optionnel, défaut FR
"siren": "123456789", // optionnel
"siret": "12345678900012", // optionnel (prioritaire sur siren)
"legal_form": "SARL au capital de 10 000 €", // optionnel
"email": "contact@xyz.fr", // optionnel
"phone": "+33 1 23 45 67 89" // optionnel
},
"buyer": { // requis
"name": "Client ABC", // requis
"address": "456 Avenue Victor Hugo\n69002 Lyon", // requis
"vat_id": "FR98765432109", // optionnel
"country": "FR", // optionnel, défaut FR
"siren": "987654321", // optionnel
"reference": "PO-2025-042" // optionnel (référence acheteur, BT-10)
},
"items": [ // requis, au moins 1 ligne
{
"description": "Service de développement", // requis
"quantity": 10, // requis (nombre)
"unit_price": 150.00, // requis (HT)
"vat_rate": 20.0 // requis (%, ex. 20 / 5.5 / 0)
}
]
}
Réponse
- 200 ·
application/pdf— le PDF Factur-X (Content-Disposition: attachment) - 400 ·
application/json— payload absent ou invalide :{"error":"..."} - 500 ·
application/json— erreur de génération (XSD/schematron) :{"error":"...","trace":"..."}
Exemple — curl
curl -X POST https://facture-electronique.chevay.fr/generate \
-H "Content-Type: application/json" \
-d @facture.json \
-o facture.pdf
Exemple — Python
import requests
payload = {
"invoice_number": "2025-001",
"invoice_date": "2025-05-21",
"seller": {"name": "XYZ", "address": "123 Rue...", "vat_id": "FR12345678901"},
"buyer": {"name": "ABC", "address": "456 Avenue..."},
"items": [{"description": "Dev", "quantity": 10, "unit_price": 150, "vat_rate": 20}],
}
r = requests.post("https://facture-electronique.chevay.fr/generate", json=payload)
r.raise_for_status()
open("facture.pdf", "wb").write(r.content)
Exemple — JavaScript (fetch)
const resp = await fetch("https://facture-electronique.chevay.fr/generate", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
});
const blob = await resp.blob();
// blob est un PDF, à sauvegarder ou afficher
POST
/merge
Fusionne un PDF existant et un XML Factur-X / CII en un PDF/A-3 conforme
(métadonnées XMP, pièce jointe avec relation Alternative).
Requête
Content-Type: multipart/form-data
| Champ | Type | Description | |
|---|---|---|---|
| file | requis | PDF source, sera converti en PDF/A-3 | |
| xml | file | requis | XML Factur-X / CII à embarquer |
| level | string | opt. | autodetect (défaut), minimum, basicwl, basic, en16931, extended |
| lang | string | opt. | Code langue ex. fr-FR |
| check_xsd | string | opt. | true (défaut) / false — désactive la validation XSD + schematron |
Réponse
- 200 ·
application/pdf— PDF/A-3 fusionné - 400 — fichiers manquants :
{"error":"Both 'pdf' and 'xml' file fields are required"} - 500 — erreur de validation ou de fusion
Exemple — curl
curl -X POST https://facture-electronique.chevay.fr/merge \
-F pdf=@invoice.pdf \
-F xml=@factur-x.xml \
-F level=en16931 \
-o factur-x.pdf
Exemple — Python
import requests
with open("invoice.pdf", "rb") as p, open("factur-x.xml", "rb") as x:
r = requests.post(
"https://facture-electronique.chevay.fr/merge",
files={"pdf": p, "xml": x},
data={"level": "en16931"},
)
r.raise_for_status()
open("factur-x.pdf", "wb").write(r.content)
GET
/health
Vérification de l'état du service. À utiliser pour les health checks (uptime monitoring, CI).
Réponse
HTTP/1.1 200 OK
Content-Type: application/json
{"status":"ok"}
Notes
- La validation Factur-X tourne en deux temps : XSD (structure XML) puis schematron (règles métier EN 16931). Une violation des deux remonte dans le champ
errorde la réponse 500. - Le n° de TVA fourni sans préfixe pays est auto-préfixé avec le
countryde la partie (défautFR). - Les montants sont calculés côté serveur en
Decimal, leunit_priceest interprété comme HT. - Taille maximale d'upload pour
/merge: 25 MB (réglé au niveau nginx).