Documentation API

Base URL : https://api.lectio.foliolabs.fr

Démarrage rapide

Quatre étapes pour obtenir votre premier résultat JSON.

  1. Créez un compte sur /public/register — 5 crédits d'essai offerts à l'activation.
  2. Validez votre adresse e-mail — cliquez sur le lien reçu dans votre boîte mail pour activer votre compte.
  3. Créez une clé API depuis votre tableau de bord sous Mes clés. Copiez-la immédiatement — elle ne s'affiche qu'une seule fois.
  4. Envoyez votre premier document :
curl -X POST https://api.lectio.foliolabs.fr/v1/invoices/parse \
  -H "Authorization: Bearer <votre_clé>" \
  -F "file=@facture.pdf"

Remplacez <votre_clé> par votre clé API et facture.pdf par votre fichier.

Authentification

Toutes les requêtes API nécessitent un header Authorization avec un Bearer token :

Authorization: Bearer <votre_clé>
  • CrĂ©ez et rĂ©voquez vos clĂ©s depuis Mes clĂ©s.
  • Une clĂ© dĂ©sactivĂ©e ne peut pas ĂŞtre rĂ©activĂ©e — crĂ©ez-en une nouvelle si nĂ©cessaire.
  • Header manquant ou clĂ© invalide → 401 Unauthorized.

POST /v1/invoices/parse

Analyse une facture (document_type = facture). Retourne 422 (document_type_mismatch) si le document est un devis, ou 422 (unsupported_document) s'il n'est ni l'un ni l'autre.

RequĂŞte

curl -X POST https://api.lectio.foliolabs.fr/v1/invoices/parse \
  -H "Authorization: Bearer <votre_clé>" \
  -F "file=@facture-renovation-2026.pdf"
  • Format : multipart/form-data, champ file
  • Taille max : 5 Mo — Pages max : 10
  • PDFs natifs (texte) et PDFs scannĂ©s sont tous deux supportĂ©s.

Exemple de réponse — facture de rénovation (multi-sections, TVA mixte)

{
  "document_type": "facture",
  "document_number": "FAC-2026-0042",
  "date": "2026-03-15",
  "issuer": {
    "name": "Rénovation Express SARL",
    "address": "12 rue des Artisans, 69003 Lyon",
    "siret": "812 345 678 00019",
    "tva_intracom": "FR 22 812345678",
    "email": "contact@renovation-express.fr",
    "phone": "04 72 12 34 56"
  },
  "client": {
    "name": "Dupont & Fils SARL",
    "address": "8 avenue de la République, 69001 Lyon",
    "siret": "923 456 789 00023",
    "tva_intracom": null,
    "email": null,
    "phone": null
  },
  "line_items": [
    {
      "description": "Fourniture et pose de carrelage 30Ă—60",
      "quantity": 60.0, "unit": "m²",
      "unit_price_ht": 35.0, "tva_rate": 20.0,
      "total_ht": 2100.0, "total_ttc": 2520.0,
      "is_optional": false, "section": "Gros œuvre"
    },
    {
      "description": "Main d'œuvre pose carrelage",
      "quantity": 18.0, "unit": "h",
      "unit_price_ht": 28.0, "tva_rate": 10.0,
      "total_ht": 504.0, "total_ttc": 554.4,
      "is_optional": false, "section": "Gros œuvre"
    },
    {
      "description": "Remplacement robinetterie salle de bains",
      "quantity": 3.0, "unit": null,
      "unit_price_ht": 185.0, "tva_rate": 20.0,
      "total_ht": 555.0, "total_ttc": 666.0,
      "is_optional": false, "section": "Plomberie"
    },
    {
      "description": "Main d'œuvre plomberie",
      "quantity": 8.0, "unit": "h",
      "unit_price_ht": 55.0, "tva_rate": 10.0,
      "total_ht": 440.0, "total_ttc": 484.0,
      "is_optional": false, "section": "Plomberie"
    },
    {
      "description": "RevĂŞtement mural peinture (option)",
      "quantity": 1.0, "unit": null,
      "unit_price_ht": 1200.0, "tva_rate": 10.0,
      "total_ht": 1200.0, "total_ttc": 1320.0,
      "is_optional": true, "section": null
    }
  ],
  "totals": { "total_ht": 4799.0, "total_tva": 745.4, "total_ttc": 5544.4 },
  "payment_terms": "30 jours net à réception de facture",
  "confidence": "high",
  "anomalies": [
    { "code": "model_reported", "detail": "Numéro de TVA intracommunautaire client absent", "affects_confidence": false }
  ],
  "pdf_type": "native_digital"
}

POST /v1/quotes/parse

Analyse un devis (document_type = devis). Retourne 422 (document_type_mismatch) si le document est une facture, ou 422 (unsupported_document) s'il n'est ni l'un ni l'autre.

RequĂŞte

curl -X POST https://api.lectio.foliolabs.fr/v1/quotes/parse \
  -H "Authorization: Bearer <votre_clé>" \
  -F "file=@devis-projet-web.pdf"

Exemple de réponse — devis multi-phases avec ligne optionnelle

{
  "document_type": "devis",
  "document_number": "DEV-2026-0018",
  "date": "2026-04-02",
  "issuer": {
    "name": "Tech Conseil SASU",
    "address": "47 rue du Commerce, 75015 Paris",
    "siret": "789 012 345 00034",
    "tva_intracom": "FR 15 789012345",
    "email": "devis@tech-conseil.fr",
    "phone": "01 45 67 89 10"
  },
  "client": {
    "name": "Groupe Martin SA",
    "address": "3 boulevard Haussmann, 75009 Paris",
    "siret": "634 789 012 00056",
    "tva_intracom": "FR 40 634789012",
    "email": "achats@groupe-martin.fr",
    "phone": null
  },
  "line_items": [
    {
      "description": "Analyse des besoins et rédaction du cahier des charges",
      "quantity": 5.0, "unit": "j",
      "unit_price_ht": 950.0, "tva_rate": 20.0,
      "total_ht": 4750.0, "total_ttc": 5700.0,
      "is_optional": false, "section": "Phase 1 — Cadrage"
    },
    {
      "description": "Développement application web — module gestion clients",
      "quantity": 20.0, "unit": "j",
      "unit_price_ht": 900.0, "tva_rate": 20.0,
      "total_ht": 18000.0, "total_ttc": 21600.0,
      "is_optional": false, "section": "Phase 2 — Développement"
    },
    {
      "description": "Tests et recette",
      "quantity": 4.0, "unit": "j",
      "unit_price_ht": 800.0, "tva_rate": 20.0,
      "total_ht": 3200.0, "total_ttc": 3840.0,
      "is_optional": false, "section": "Phase 2 — Développement"
    },
    {
      "description": "Formation utilisateurs (demi-journée, 10 personnes)",
      "quantity": 1.0, "unit": null,
      "unit_price_ht": 1800.0, "tva_rate": 20.0,
      "total_ht": 1800.0, "total_ttc": 2160.0,
      "is_optional": false, "section": "Phase 3 — Formation"
    },
    {
      "description": "Contrat de maintenance corrective — 12 mois (option)",
      "quantity": 12.0, "unit": "mois",
      "unit_price_ht": 350.0, "tva_rate": 20.0,
      "total_ht": 4200.0, "total_ttc": 5040.0,
      "is_optional": true, "section": null
    }
  ],
  "totals": { "total_ht": 31950.0, "total_tva": 6390.0, "total_ttc": 38340.0 },
  "payment_terms": "30 % Ă  la commande, solde Ă  la livraison",
  "confidence": "high",
  "anomalies": [],
  "pdf_type": "native_digital"
}

POST /v1/documents/parse

Analyse un document dont le type n'est pas connu à l'avance : le type (facture ou devis) est détecté automatiquement et renvoyé dans document_type. Ne retourne jamais 422 (document_type_mismatch) pour une incohérence de type — mais retourne toujours 422 (unsupported_document) si le document n'est ni un devis ni une facture.

RequĂŞte

curl -X POST https://api.lectio.foliolabs.fr/v1/documents/parse \
  -H "Authorization: Bearer <votre_clé>" \
  -F "file=@document.pdf"

La réponse a le même format que /v1/invoices/parse et /v1/quotes/parse (voir exemples ci-dessus) — seul document_type varie selon le document envoyé.

GET /v1/account

Retourne le solde de crédits par lot d'achat. Aucun crédit consommé. Utile pour vérifier votre solde avant un traitement en masse.

RequĂŞte

curl https://api.lectio.foliolabs.fr/v1/account \
  -H "Authorization: Bearer <votre_clé>"

Exemple de réponse

{
  "credits_total": 347,
  "batches": [
    { "credits": 47,  "expires_at": "2026-12-31T23:59:59" },
    { "credits": 300, "expires_at": "2027-05-15T23:59:59" }
  ]
}

Les lots sont consommés dans l'ordre d'expiration (FIFO). credits_total est la somme des lots non expirés.

Niveau de confiance

Chaque réponse inclut un champ confidence qui reflète l'auto-évaluation du modèle sur la qualité de l'extraction.

high

Les totaux s'équilibrent et le modèle est certain de l'extraction. Intégration automatique sûre.

medium

Incertitude mineure : cellule floue, taux de TVA ambigu, mise en page inhabituelle. Vérifiez le document avant de comptabiliser.

low

Doute significatif sur l'extraction. Causes typiques : PDF scanné de mauvaise qualité, mise en page non standard, document partiellement illisible. Vérification manuelle obligatoire.

Le tableau anomalies complète confidence : même une réponse high peut signaler une anomalie (ex. : écart d'arrondi sur le total TTC, numéro de TVA absent). Vérifiez anomalies.length > 0 dans votre logique d'intégration.

Garantie : dès que confidence n'est pas "high", la réponse contient toujours au moins une entrée dans anomalies avec affects_confidence: true expliquant pourquoi — jamais un tableau vide sans explication. Filtrez sur affects_confidence pour isoler les entrées qui justifient le niveau de confiance des simples remarques qualité.

code Cause affects_confidence
total_field_defaultedUn champ de total était absent du document — remplacé par 0.0false
line_item_droppedUne ligne incomplète (quantité, PU ou total HT manquant) a été écartéefalse
totals_mismatch_htLa somme des lignes HT ne correspond pas au total HT déclarétrue
totals_mismatch_ttcLa somme des lignes TTC ne correspond pas au total TTC déclarétrue
model_reportedRemarque du modèle sur le document (mise en page, lisibilité, ambiguïté…)selon la confidence de la réponse
low_confidence_unspecifiedConfidence non-high sans autre explication disponible (garantie de repli)true

Référence du schéma de réponse

Les endpoints /v1/invoices/parse, /v1/quotes/parse et /v1/documents/parse retournent le mĂŞme objet.

Champ Type Notes
document_type"facture" | "devis"Type détecté dans le document
document_numberstring | nullNuméro de pièce (ex. FAC-2026-0042)
datestring | nullFormat YYYY-MM-DD
issuerobjectÉmetteur — voir champs Party ci-dessous
clientobjectDestinataire — mêmes champs que issuer
line_itemsarrayToutes les lignes du document — voir ci-dessous
totalsobjecttotal_ht, total_tva, total_ttc (float)
payment_termsstring | nullConditions de règlement extraites
confidence"high" | "medium" | "low"Voir Niveau de confiance
anomaliesobject[]{code, detail, affects_confidence} — voir Niveau de confiance ; liste vide si aucune anomalie
pdf_type"native_digital" | "scanned"Natif = texte extractable ; scanné = traité par vision IA

Champs Party (issuer / client)

Champ Type Notes
namestring | nullRaison sociale ou nom
addressstring | nullAdresse complète
siretstring | nullNuméro SIRET (14 chiffres)
tva_intracomstring | nullNuméro de TVA intracommunautaire
emailstring | nullExtrait du document si présent
phonestring | nullExtrait du document si présent

Champs LineItem

Champ Type Notes
descriptionstringLibellé de la ligne
quantityfloatQuantité
unitstring | nullUnité (ex. m², h, j, mois)
unit_price_htfloatPrix unitaire HT (hors taxes)
tva_ratefloat | nullValeurs valides : 0, 2.1, 5.5, 10, 20
total_htfloatMontant HT de la ligne
total_ttcfloat | nullMontant TTC (toutes taxes comprises)
is_optionalboolLigne optionnelle — fréquent dans les devis
sectionstring | nullEn-tête de section du document si présent

HT = hors taxes (excl. TVA) · TTC = toutes taxes comprises (incl. TVA)

Codes d'erreur

Chaque erreur renvoie {"code": "...", "detail": "..."} — code est une chaîne stable à utiliser pour brancher votre code, detail est un message lisible qui peut évoluer.

HTTP code Cause Action recommandée
401missing_token / invalid_api_keyClé API manquante ou invalideVérifier le header Authorization: Bearer <clé> — gérer vos clés sur Mes clés
402insufficient_creditsCrédits insuffisants ou expirésRecharger sur Facturation ou vérifier le solde via GET /v1/account
413file_too_largeFichier au-delà de la limite (5 Mo)Réduire la taille du PDF avant l'envoi
422document_type_mismatchType de document incorrect pour l'endpoint appeléAppeler le bon endpoint (/v1/quotes/parse pour un devis), ou /v1/documents/parse qui n'exige pas de type attendu
422unsupported_documentLe document n'est ni un devis ni une facture (ex : CV, contrat, relevé bancaire)Ne pas réessayer — l'API ne traite que des devis/factures françaises
422document_unparseableLe document n'a pas pu être structuré (mise en page inhabituelle, scan illisible…)Vérifier la qualité du PDF (texte sélectionnable ou scan net) ; contacter le support si persistant
422suspicious_contentContenu suspect détecté (injection, script)Ne pas réessayer
429rate_limitedLimite de requêtes atteinte (5/min ou 50/h)Attendre et réessayer — respecter l'en-tête Retry-After
500internal_errorErreur serveurRéessayer une fois — contacter le support via Support si persistant

Crédits & limites

  • 1 document = 1 crĂ©dit, dĂ©bitĂ© avant l'appel au modèle d'IA — quel que soit le rĂ©sultat.
  • Les crĂ©dits sont suivis par lot d'achat, chacun avec sa propre date d'expiration. Consommation FIFO (lot expirant en premier consommĂ© en premier).
  • Limite de dĂ©bit : 5 requĂŞtes/minute et 50 requĂŞtes/heure par clĂ© API.
  • Taille de fichier : 5 Mo max — Pages : 10 pages max.
  • Format acceptĂ© : PDF uniquement. PDFs natifs (texte) et PDFs scannĂ©s sont tous deux pris en charge.

Exemples de code

Python (httpx)

import httpx

API_KEY = "sk_live_..."
BASE_URL = "https://api.lectio.foliolabs.fr"

def parse_invoice(pdf_path: str) -> dict:
    with open(pdf_path, "rb") as f:
        response = httpx.post(
            f"{BASE_URL}/v1/invoices/parse",
            headers={"Authorization": f"Bearer {API_KEY}"},
            files={"file": (pdf_path, f, "application/pdf")},
            timeout=60.0,
        )
    response.raise_for_status()
    result = response.json()
    for a in result["anomalies"]:
        marker = "!" if a["affects_confidence"] else "-"
        print(f"{marker} [{a['code']}] {a['detail']}")
    return result

invoice = parse_invoice("facture-2026-03.pdf")
print(f"Total TTC : {invoice['totals']['total_ttc']} €  — confiance : {invoice['confidence']}")

JavaScript (fetch)

const API_KEY = "sk_live_...";
const BASE_URL = "https://api.lectio.foliolabs.fr";

async function parseInvoice(file) {
  const form = new FormData();
  form.append("file", file);

  const res = await fetch(`${BASE_URL}/v1/invoices/parse`, {
    method: "POST",
    headers: { Authorization: `Bearer ${API_KEY}` },
    body: form,
    signal: AbortSignal.timeout(60_000),
  });

  if (!res.ok) throw new Error(`${res.status} ${res.statusText}`);
  const result = await res.json();
  for (const a of result.anomalies) {
    console.warn(`[${a.code}]${a.affects_confidence ? " (affects confidence)" : ""} ${a.detail}`);
  }
  return result;
}

// Usage (browser file input)
document.querySelector("#file").addEventListener("change", async (e) => {
  const invoice = await parseInvoice(e.target.files[0]);
  console.log("Total TTC :", invoice.totals.total_ttc, "€");
});

Bonnes pratiques

  • VĂ©rifiez confidence et anomalies avant d'intĂ©grer les montants dans votre comptabilitĂ© automatisĂ©e — filtrez sur anomalies[].affects_confidence pour isoler les entrĂ©es qui justifient le niveau de confiance des simples remarques qualitĂ©.
  • Appelez GET /v1/account avant un traitement en masse pour confirmer que votre solde est suffisant.
  • Si vous connaissez dĂ©jĂ  le type de document, utilisez /v1/quotes/parse (devis) ou /v1/invoices/parse (factures) pour que l'API valide le type et retourne 422 en cas d'erreur. Si le type n'est pas connu Ă  l'avance (ex. : pièces jointes d'une boĂ®te mail), utilisez /v1/documents/parse, qui dĂ©tecte le type automatiquement.
  • PrĂ©voyez un timeout de 60 secondes — les PDFs scannĂ©s prennent plus de temps (appel vision IA).
  • N'enregistrez jamais une clĂ© API en clair dans vos logs. En cas de compromission, rĂ©voquez-la depuis Mes clĂ©s et crĂ©ez-en une nouvelle.
  • Ajoutez un jitter entre les requĂŞtes lors d'un traitement en masse pour Ă©viter les pics de dĂ©bit.

Pas encore de compte ? Créez-en un gratuitement et obtenez 5 crédits d'essai.