Documentation de l'API DocSolved

DocSolved fournit une API REST pour extraire des données structurées de documents téléversés ou de pièces jointes d’e-mails normalisées. Les tâches persistantes, l’approbation humaine, les webhooks signés et les exports comptables prennent en charge les automatisations dans Make, n8n, Zapier ou des intégrations personnalisées.

Vous développez plutôt avec un agent de codage qu'avec du code applicatif ? DocSolved MCP connecte Codex, Claude Code, Gemini CLI et d'autres agents compatibles MCP à cette même API.

Extrayez votre premier document en moins de 3 minutes

  1. Créez une clé API dans les Paramètres développeur. La portée extract suffit pour cette boucle ; la clé n'est affichée qu'une fois.
  2. Soumettez le document comme tâche asynchrone, interrogez l'état jusqu'à la fin, récupérez le résultat.
  3. Chaque champ de result.extracted_fields[] possède les mêmes clés : confidence, page, evidence (le texte source), match_status et bounding_box. Sur la voie OCR, elles sont renseignées lorsque la valeur a pu être localisée sur la page (match_status exact, fuzzy ou llm_located) ; une valeur que l'OCR n'a pas pu ancrer est not_found avec un cadre nul. Les e-factures structurées sont analysées depuis leur XML : leurs champs ne portent ni page ni cadre.

cURL

export DOCAI_API_KEY="sk_docai_YOUR_KEY"

# 1. submit (a retried submit with the same Idempotency-Key returns the same job)
JOB_ID=$(curl -s -X POST https://docsolved.ai/api/v1/jobs \
  -H "Authorization: Bearer $DOCAI_API_KEY" \
  -H "Idempotency-Key: invoice-2026-0847" \
  -F "[email protected]" | python3 -c 'import json,sys; print(json.load(sys.stdin)["job_id"])')

# 2. poll until status is completed / review_required / failed
until curl -s https://docsolved.ai/api/v1/jobs/$JOB_ID \
  -H "Authorization: Bearer $DOCAI_API_KEY" | grep -qE '"status": ?"(completed|review_required|failed)"'; do sleep 2; done

# 3. result
curl -s https://docsolved.ai/api/v1/jobs/$JOB_ID/result \
  -H "Authorization: Bearer $DOCAI_API_KEY"

Python

import os, time, requests

BASE = "https://docsolved.ai/api/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['DOCAI_API_KEY']}"}

with open("invoice.pdf", "rb") as f:
    submit = requests.post(f"{BASE}/jobs", headers={**HEADERS, "Idempotency-Key": "invoice-2026-0847"},
                           files={"file": ("invoice.pdf", f, "application/pdf")}, timeout=60)
submit.raise_for_status()
job_id = submit.json()["job_id"]

while True:
    status = requests.get(f"{BASE}/jobs/{job_id}", headers=HEADERS, timeout=30).json()["status"]
    if status in ("completed", "review_required", "failed"):
        break
    time.sleep(2)

result = requests.get(f"{BASE}/jobs/{job_id}/result", headers=HEADERS, timeout=30).json()["result"]
for field in result["extracted_fields"]:
    print(field["field"], field["value"], field["confidence"], field.get("page"), field.get("evidence"))

JavaScript / Node.js 20+

import { readFile } from "node:fs/promises";

const BASE = "https://docsolved.ai/api/v1";
const headers = { Authorization: `Bearer ${process.env.DOCAI_API_KEY}` };

const form = new FormData();
form.append("file", new Blob([await readFile("invoice.pdf")], { type: "application/pdf" }), "invoice.pdf");
const submit = await fetch(`${BASE}/jobs`, { method: "POST", headers: { ...headers, "Idempotency-Key": "invoice-2026-0847" }, body: form });
const { job_id } = await submit.json();

let status;
do {
  await new Promise((r) => setTimeout(r, 2000));
  ({ status } = await (await fetch(`${BASE}/jobs/${job_id}`, { headers })).json());
} while (!["completed", "review_required", "failed"].includes(status));

const { result } = await (await fetch(`${BASE}/jobs/${job_id}/result`, { headers })).json();
for (const f of result.extracted_fields) console.log(f.field, f.value, f.confidence, f.page, f.evidence);

Ensuite : webhooks au lieu du polling, envois idempotents, revue et approbation, exports, ingestion d'e-mails, ou la même API depuis un agent de codage via MCP.

Authentification

Créez et gérez vos clés API sur la page Paramètres développeur. Envoyez la clé comme jeton bearer ; les scopes et le quota mensuel de pages de la clé sont appliqués à chaque requête.

Authorization: Bearer sk_docai_<your_key>

Les clés API commencent par sk_docai_. Gardez-les secrètes. Elles ne sont affichées qu'une seule fois lors de leur création.

Utilisez la portée extract pour soumettre des tâches et lire leurs résultats. Ajoutez la portée history pour lister les enregistrements sauvegardés et télécharger les exports comptables, et la portée webhooks pour gérer les points de terminaison webhook. Ce sont les seules portées de clé API prises en charge. Les clés n'expirent pas ; révoquez une clé depuis les Paramètres développeur dès qu'elle n'est plus nécessaire.

Limites de débit

L'utilisation des analyses est régie par le quota de pages et de stockage de votre forfait. Il n'existe pas de plafond distinct par requête ou par jour.

Les clés API décomptent en outre les pages OCR du quota mensuel de pages de la clé.

Les requêtes à court de pages ou de stockage renvoient HTTP 402 ; une clé API ayant dépassé son quota mensuel de pages renvoie HTTP 429 avec un indice Retry-After.

Les points de terminaison auxiliaires (aides à la validation, création/test/relecture de webhooks, liens de partage publics) ont un garde-fou de 60 requêtes par minute et par IP, 600 pour les appelants authentifiés ; chaque 429 porte Retry-After en secondes. Les valeurs en vigueur sont publiées par GET /api/v1/capabilities sous rate_limits.

Format des erreurs

{
  "detail": "File too large. Maximum upload size is 15 MB.",
  "request_id": "3f1c9d2e8b4a4c0e9a7d1b2c3d4e5f60",
  "error": {
    "code": "FILE_TOO_LARGE",
    "message": "File too large. Maximum upload size is 15 MB.",
    "retryable": false,
    "request_id": "3f1c9d2e8b4a4c0e9a7d1b2c3d4e5f60"
  }
}

Testez error.code, jamais le texte. Codes : INVALID_REQUEST, AUTHENTICATION_REQUIRED, PERMISSION_DENIED, NOT_FOUND, FILE_TOO_LARGE, UNSUPPORTED_DOCUMENT, RATE_LIMITED, QUOTA_EXCEEDED, IDEMPOTENCY_KEY_CONFLICT, PROCESSING_TIMEOUT, INTERNAL_ERROR. Ne réessayez que si retryable est vrai, en respectant Retry-After, et renvoyez la même Idempotency-Key. Citez request_id (aussi envoyé dans l'en-tête X-Request-ID) quand vous contactez le support.

Compatibilité

Dans /api/v1, les changements sont uniquement additifs : chemins, champs, codes d'erreur et états de tâche ne sont jamais supprimés ni retypés. Les changements incompatibles sortent en /api/v2 avec au moins 12 mois de chevauchement, annoncés dans le journal des modifications et avec les en-têtes Deprecation et Sunset. Lisez GET /api/v1/capabilities au démarrage plutôt que de coder en dur formats et limites.

Extraction de document synchrone

POST/api/v1/analyze

Téléversez un document et obtenez les résultats d'extraction de manière synchrone. Idéal pour les petits documents (< 2 pages).

Requête

Données de formulaire multipart :

ChampTypeDescription
filefileobligatoirePDF, PNG, JPG, HEIC, AVIF, TIFF, BMP ou WEBP (15 Mo max)
filenamestringfacultatifRemplacer le nom de fichier affiché

Exemple

curl -X POST https://docsolved.ai/api/v1/analyze \
  -H "Authorization: Bearer sk_docai_..." \
  -F "file=@purchase_order.pdf"

Réponse

{
  "request_id": "3fa8...",
  "filename": "purchase_order.pdf",
  "document_type": "purchase_order",
  "document_type_confidence": 0.94,
  "summary": "Purchase order from Acme Corp to Widget Co.",
  "language": "en",
  "extracted_fields": [
    {
      "field": "po_number",
      "value": "PO-2026-0042",
      "confidence": 0.97,
      "page": 1,
      "evidence": "PO-2026-0042"
    }
  ],
  "warnings": [],
  "ocr": { "pages": 1, "tokens": 312, "language": "eng+pol" },
  "llm": { "status": "success", "provider": "openai", "model": "gpt-4o-mini" }
}

Extraction en flux (SSE)

POST/api/v1/analyze/stream

Identique à l'extraction synchrone, mais diffuse des Server-Sent Events indiquant la progression du traitement. Idéal pour les interfaces en temps réel.

Créer une tâche asynchrone

POST/api/v1/jobs

Téléversez un document et obtenez un identifiant de tâche. Le traitement s'effectue en arrière-plan.

curl -X POST https://docsolved.ai/api/v1/jobs \
  -H "Authorization: Bearer sk_docai_..." \
  -F "[email protected]"
{ "job_id": "abc123", "status": "queued", "request_id": "xyz..." }

Ingérer des pièces jointes par e-mail

POST/api/v1/ingest/email

Passerelle d'e-mails entrants indépendante du fournisseur. Postmark, Mailgun, SendGrid, Amazon SES, Make, n8n ou un autre adaptateur doit analyser la charge utile du fournisseur et envoyer les pièces jointes acceptées sous forme de données de formulaire multipart. DocSolved n'héberge pas de boîte aux lettres et n'effectue pas d'analyse MIME propre au fournisseur.

ChampTypeDescription
message_idstringobligatoireIdentifiant de message stable provenant du fournisseur
source_namespacestringobligatoirePortée fournisseur/compte stable, telle que postmark:server-123
filesfile[]obligatoireRépétez pour chaque pièce jointe prise en charge
organization_idstringfacultatifEspace de travail cible ; l'appelant doit disposer de l'autorisation d'importer
curl -X POST https://docsolved.ai/api/v1/ingest/email \
  -H "Authorization: Bearer sk_docai_..." \
  -F "message_id=provider-message-42" \
  -F "source_namespace=postmark:server-123" \
  -F "organization_id=org_..." \
  -F "[email protected];type=application/pdf" \
  -F "[email protected];type=image/jpeg"
{
  "message_id": "provider-message-42",
  "source_namespace": "postmark:server-123",
  "accepted_count": 1,
  "duplicate_count": 1,
  "jobs": [
    {"job_id": "job-new", "status": "queued", "filename": "invoice.pdf", "duplicate": false},
    {"job_id": "job-old", "status": "completed", "filename": "receipt.jpg", "duplicate": true}
  ]
}

L'idempotence comprend le propriétaire authentifié, l'espace de noms fournisseur/compte, la destination, l'identifiant du message, le nom de fichier normalisé, le contenu du fichier et l'occurrence parmi les pièces jointes identiques. Les nouvelles tentatives réordonnées du fournisseur renvoient les identifiants de tâche d'origine. Une ingestion échouée peut remettre en file la même tâche avec de nouveaux octets pour un maximum de trois tentatives au total ; les tâches actives et terminées ne sont jamais traitées deux fois.

Obtenir le statut de la tâche

GET/api/v1/jobs/{job_id}

curl https://docsolved.ai/api/v1/jobs/abc123 \
  -H "Authorization: Bearer sk_docai_..."
{
  "id": "abc123",
  "status": "completed",
  "progress_pct": 100,
  "document_type": "invoice",
  "pages_processed": 2
}

Statuts possibles : queued, processing, review_required, completed, failed, cancelled.

Obtenir le résultat de la tâche

GET/api/v1/jobs/{job_id}/result

Renvoie le résultat d'extraction complet une fois l'état de la tâche completed ou review_required. Accepte la portée extract ou history, si bien qu'une clé limitée à extract couvre toute la boucle envoi, interrogation, résultat.

curl https://docsolved.ai/api/v1/jobs/abc123/result \
  -H "Authorization: Bearer sk_docai_..."

Exporter en JSON

POST/api/v1/export/json

Envoyez le résultat d'extraction dans le corps JSON et obtenez un fichier d'export propre.

curl -X POST https://docsolved.ai/api/v1/export/json \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_docai_..." \
  -d '{"request_id":"...","extracted_fields":[...]}' \
  -o export.json

Exporter en CSV

POST/api/v1/export/csv

curl -X POST https://docsolved.ai/api/v1/export/csv \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk_docai_..." \
  -d '{"request_id":"...","extracted_fields":[...]}' \
  -o fields.csv

Exporter en XLSX

POST/api/v1/export/xlsx

Renvoie un classeur Excel avec des feuilles Résumé, Champs, Lignes d'articles, Avertissements et Métadonnées.

Lister l'historique

GET/api/v1/history

curl https://docsolved.ai/api/v1/history \
  -H "Authorization: Bearer sk_docai_..."

Flux de révision et d’approbation

POST/api/v1/history/{record_id}/workflow

Appliquez une transition de flux contrôlée à un enregistrement sauvegardé. Cette route nécessite une session Clerk interactive : les clés API ne peuvent pas approuver de documents. Les membres d'un espace de travail peuvent réviser ; ses administrateurs peuvent approuver, demander des modifications ou rejeter. Le propriétaire d'un enregistrement personnel assume les deux rôles.

{
  "action": "approve",
  "comment": "Ready to post"
}

Actions : start_review, complete_review, reopen_review, submit_for_approval, approve, request_changes, reject et accept_partial_analysis. L'approbation valide ensemble l'événement d'audit du flux et l'événement de boîte d'envoi document.approved.

Supprimer tout l'historique

DELETE/api/v1/history

Supprime définitivement toutes les analyses enregistrées de votre compte.

Lister les clés API

GET/api/v1/keys

Créer une clé API

POST/api/v1/keys

curl -X POST https://docsolved.ai/api/v1/keys \
  -H "Authorization: Bearer <clerk_session_token>" \
  -H "Content-Type: application/json" \
          -d '{"name": "My automation key", "scopes": "extract,history"}'
{
  "id": "...",
  "name": "My automation key",
  "key": "sk_docai_...",   // shown ONCE - save it now
  "prefix": "sk_docai_abc",
  "scopes": "extract,history",
  "created_at": "2026-06-10T12:00:00Z"
}

Révoquer une clé API

DELETE/api/v1/keys/{key_id}

Créer un webhook

POST/api/v1/webhooks

curl -X POST https://docsolved.ai/api/v1/webhooks \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
          -d '{"name": "My webhook", "endpoint_url": "https://my.app/hook", "event_types": ["document.completed", "document.review_required", "document.approved", "document.failed"]}'

La réponse inclut un secret pour la vérification de la signature. Enregistrez-le maintenant, il ne sera plus affiché.

Types d’événements webhook

ÉvénementLorsqu'il se déclenche
document.completedL'extraction est terminée et le résultat a été enregistré
document.review_requiredLa validation ou le routage selon la confiance nécessite une révision humaine ; se déclenche également avec document.completed
document.approvedUn approbateur autorisé a validé la décision d'approbation ; utilisez cet événement pour les écritures comptables
document.failedLe traitement a échoué ; les tâches ingérées par e-mail incluent des métadonnées sur la possibilité de nouvelle tentative et le nombre de tentatives
Utilisez document.approved, et non document.completed, comme point de contrôle pour enregistrer des données dans un système comptable. L'extraction peut être terminée alors que des champs nécessitent encore une correction.

Tester un webhook

POST/api/v1/webhooks/{webhook_id}/test

Vérifier la signature du webhook

Chaque livraison inclut ces en-têtes :

import hashlib, hmac

def verify(secret, body_str, timestamp, signature_header):
    msg = f"{timestamp}.{body_str}"
    digest = hmac.new(secret.encode(), msg.encode(), hashlib.sha256).hexdigest()
    return hmac.compare_digest(f"sha256={digest}", signature_header)

Événements durables échoués

DocSolved réessaie automatiquement les livraisons sortantes. Si un événement durable de boîte d'envoi ne peut pas être développé après cinq tentatives, il devient un message non distribuable. Le propriétaire peut examiner les métadonnées sans exposer la charge utile stockée et relancer l'événement après avoir corrigé la cause.

GET/api/v1/webhook-outbox/failed

curl https://docsolved.ai/api/v1/webhook-outbox/failed \
  -H "Authorization: Bearer sk_docai_..."

POST/api/v1/webhook-outbox/{event_id}/replay

curl -X POST https://docsolved.ai/api/v1/webhook-outbox/EVENT_ID/replay \
  -H "Authorization: Bearer sk_docai_..."

Les mêmes contrôles sont disponibles dans Paramètres développeur → Événements nécessitant une attention. Les enregistrements de livraison et de boîte d'envoi terminaux sont conservés pendant 30 jours.

Utilisation avec Make / n8n / Zapier

Pour les importations directes, appelez /api/v1/jobs. Pour les e-mails entrants, laissez le fournisseur analyser les pièces jointes et appelez /api/v1/ingest/email avec un identifiant de message et un espace de noms source stables. Les deux routes créent les mêmes tâches persistantes et utilisent le même flux de révision.

Abonnez-vous aux événements de fin et de révision pour connaître l'état, puis utilisez document.approved pour déclencher des actions comptables aval contrôlées. Les webhooks signés éliminent la nécessité d'interroger le service.

Questions fréquentes

Comment m'authentifier auprès de l'API DocSolved ?

Créez une clé API sur /developer — elle n'est affichée qu'une seule fois — puis envoyez-la comme jeton Bearer dans l'en-tête Authorization : Authorization: Bearer sk_docai_your_key.

Quelle est la différence entre /api/v1/analyze et /api/v1/jobs ?

/api/v1/analyze renvoie le résultat dans la même requête, ce qui convient à une utilisation interactive. /api/v1/jobs met le document en file d'attente : vous interrogez le job ou recevez un webhook signé à la fin — préférable pour les lots et les documents volumineux.

Comment suis-je averti lorsqu'un document est terminé ?

Enregistrez un webhook. DocSolved envoie en POST un événement signé HMAC-SHA256 sur document.completed, document.review_required, document.failed et document.approved. Vérifiez l'en-tête X-DocAI-Signature et renvoyez un code HTTP 2xx dans les cinq secondes.

L'API fournit-elle des preuves de provenance pour les valeurs extraites ?

Pour les documents numérisés, chaque champ porte le texte dont il provient et, lorsque l'OCR a localisé la valeur, sa page et son cadre de délimitation. Les factures électroniques structurées sont analysées à partir de leur XML et n'ont volontairement aucun cadre de délimitation.