ConformKit API
Base : https://api.conformkit.fr/v1. Messages en français, detail_en inclus. Erreurs applicatives en RFC 7807 (application/problem+json).
Authentification
En-tête Authorization: Bearer ck_live_…. Créez et faites tourner votre clé depuis la console. Le validateur accepte aussi des requêtes anonymes (débit limité).
POST /validate
Corps = octets bruts du fichier (PDF ou XML), nom dans l'en-tête X-CK-Filename. Quatre passes : XSD, Schematron EN 16931, PDF/A-3 (veraPDF), mentions FR.
curl -F "file=@facture.pdf" \
-H "Authorization: Bearer $CONFORMKIT_KEY" \
https://api.conformkit.fr/v1/validateimport os, requests
with open("facture.pdf", "rb") as f:
r = requests.post(
"https://api.conformkit.fr/v1/validate",
headers={
"Authorization": f"Bearer {os.environ['CONFORMKIT_KEY']}",
"Content-Type": "application/octet-stream",
"X-CK-Filename": "facture.pdf",
},
data=f.read(),
)
print(r.json()["status"]) # "valid" | "invalid" | "warning"import { readFile } from "node:fs/promises";
const res = await fetch("https://api.conformkit.fr/v1/validate", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.CONFORMKIT_KEY}`,
"Content-Type": "application/octet-stream",
"X-CK-Filename": "facture.pdf",
},
body: await readFile("facture.pdf"),
});
console.log((await res.json()).status);Réponse 200
{
"status": "invalid",
"format": "facturx-cii",
"profile": "EN 16931",
"checks": { "passed": 103, "errors": 2, "warnings": 1, "unsupported": 3 },
"errors": [
{
"rule_id": "BR-CO-15",
"source": "EN16931",
"severity": "error",
"message_fr": "Le montant total TTC (BT-112) ne correspond pas…",
"fix_fr": "Recalculez BT-112 = BT-109 + BT-110.",
"legal_ref": "EN 16931-1 §6.4",
"location": "/rsm:CrossIndustryInvoice/…",
"section": "en16931"
}
],
"coverage_notes": [
{ "rule_id": "FR-MO-20", "coverage": "unsupported" }
]
}POST /generate
JSON de facture → Factur-X (?format=facturx, défaut), CII (?format=cii) ou UBL (?format=ubl). Renvoie le fichier ; le nom est dans X-CK-Filename.
{
"number": "F2027-0042",
"issue_date": "2027-09-06",
"due_date": "2027-10-06",
"currency": "EUR",
"seller": { "name": "…", "siren": "732829320", "vat_id": "FR47732829320",
"street": "…", "zip": "69001", "city": "Lyon", "country": "FR" },
"buyer": { "name": "…", "siren": "552100554",
"street": "…", "zip": "75017", "city": "Paris", "country": "FR" },
"ship_to": { "country": "DE" }, // requis pour une livraison intracom. (BR-IC-12)
"lines": [
{ "name": "Prestation", "quantity": "10", "unit": "HUR",
"unit_price": "120.00", "vat_percent": "20", "tax_category": "S" }
],
"payment": { "iban": "FR76…", "terms": "Paiement à 30 jours." },
"notes": ["Mention libre…"]
}POST /convert
Corps JSON { "pdf_b64": "<PDF en base64>", "invoice": { … } }. Renvoie un PDF/A-3 Factur-X (XML CII embarqué, profil EN 16931). Essayez-le sur la page dédiée.
POST /extract
Corps = octets bruts. Renvoie un JSON normalisé, ou un CSV avec ?format=csv.
Limites & quotas
| Contexte | Taille max | Cadence |
|---|---|---|
| Anonyme (outil web) | 5 Mo | 10/min · 50/jour |
| Clé API (tous plans) | 10 Mo | quota du plan |
| Pro et Scale (gros fichiers) | 25 Mo | quota du plan |
P95 < 3 s à chaud pour un fichier de 5 Mo. Démarrage à froid < 15 s (scale-to-zero) : prévoyez un retry sur la première requête après une période d'inactivité.