Documentazione API DocSolved

DocSolved fornisce un’API REST per estrarre dati strutturati da documenti caricati o allegati e-mail normalizzati. Job persistenti, approvazione umana, webhook firmati ed esportazioni contabili supportano le automazioni in Make, n8n, Zapier o integrazioni personalizzate.

Stai sviluppando con un agente di coding invece che con codice applicativo? DocSolved MCP collega Codex, Claude Code, Gemini CLI e altri agenti compatibili con MCP a questa stessa API.

Estrai il tuo primo documento in meno di 3 minuti

  1. Crea una chiave API nelle Impostazioni sviluppatore. L'ambito extract basta per questo ciclo; la chiave viene mostrata una sola volta.
  2. Invia il documento come job asincrono, interroga lo stato fino al completamento, recupera il risultato.
  3. Ogni campo in result.extracted_fields[] ha le stesse chiavi: confidence, page, evidence (il testo di origine), match_status e bounding_box. Sul percorso OCR sono valorizzate quando il valore è stato localizzato sulla pagina (match_status exact, fuzzy o llm_located); un valore che l'OCR non è riuscito ad ancorare è not_found con riquadro nullo. Le fatture elettroniche strutturate sono lette dal loro XML, quindi i loro campi non portano né pagina né riquadro.

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);

Poi: webhook al posto del polling, invii idempotenti, revisione e approvazione, esportazioni, ingestione via e-mail, oppure la stessa API da un agente di codifica tramite MCP.

Autenticazione

Crea e gestisci le chiavi API nella pagina Impostazioni sviluppatore. Invia la chiave come token bearer; gli scope e la quota mensile di pagine della chiave vengono applicati a ogni richiesta.

Authorization: Bearer sk_docai_<your_key>

Le chiavi API iniziano con sk_docai_. Mantienile segrete. vengono mostrate una sola volta al momento della creazione.

Usa l'ambito extract per inviare job e leggerne i risultati. Aggiungi l'ambito history per elencare i record salvati e scaricare le esportazioni contabili, e l'ambito webhooks per gestire gli endpoint webhook. Sono gli unici ambiti supportati per le chiavi API. Le chiavi non scadono; revoca una chiave dalle Impostazioni sviluppatore non appena non serve più.

Limiti di frequenza

L'utilizzo dell'analisi è regolato dal limite di pagine e dalla quota di archiviazione del tuo piano: non esiste un limite separato per richiesta o giornaliero.

Le chiavi API inoltre conteggiano le pagine OCR sul contingente mensile di pagine della chiave.

Le richieste che esauriscono le pagine o lo spazio restituiscono HTTP 402; una chiave API oltre il suo contingente mensile di pagine restituisce HTTP 429 con un suggerimento Retry-After.

Gli endpoint ausiliari (helper di validazione, creazione/test/reinvio dei webhook, link di condivisione pubblici) hanno un limite di burst di 60 richieste al minuto per IP, 600 per i chiamanti autenticati; ogni 429 include Retry-After in secondi. I valori correnti sono pubblicati da GET /api/v1/capabilities sotto rate_limits.

Formato degli errori

{
  "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"
  }
}

Decidi in base a error.code, mai al testo. Codici: INVALID_REQUEST, AUTHENTICATION_REQUIRED, PERMISSION_DENIED, NOT_FOUND, FILE_TOO_LARGE, UNSUPPORTED_DOCUMENT, RATE_LIMITED, QUOTA_EXCEEDED, IDEMPOTENCY_KEY_CONFLICT, PROCESSING_TIMEOUT, INTERNAL_ERROR. Riprova solo quando retryable è vero, rispettando Retry-After, e reinvia la stessa Idempotency-Key. Cita request_id (inviato anche nell'header X-Request-ID) quando contatti il supporto.

Compatibilità

Dentro /api/v1 le modifiche sono solo additive: percorsi, campi, codici di errore e stati dei job non vengono mai rimossi né cambiati di tipo. Le modifiche incompatibili escono come /api/v2 con almeno 12 mesi di sovrapposizione, annunciate nel registro delle modifiche e con gli header Deprecation e Sunset. Leggi GET /api/v1/capabilities all'avvio invece di fissare formati e limiti nel codice.

Estrazione sincrona di documenti

POST/api/v1/analyze

Carica un documento e ottieni i risultati dell'estrazione in modo sincrono. Ideale per documenti piccoli (< 2 pagine).

Richiesta

Dati del form multipart:

CampoTipoDescrizione
filefileobbligatorioPDF, PNG, JPG, HEIC, AVIF, TIFF, BMP o WEBP (max 15 MB)
filenamestringfacoltativoSostituisci il nome file visualizzato

Esempio

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

Risposta

{
  "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" }
}

Estrazione in streaming (SSE)

POST/api/v1/analyze/stream

Come l'estrazione sincrona, ma trasmette Server-Sent Events che mostrano l'avanzamento dell'elaborazione. Ideale per interfacce in tempo reale.

Crea job asincrono

POST/api/v1/jobs

Carica un documento e ottieni un ID del job. L'elaborazione avviene in background.

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..." }

Acquisisci allegati e-mail

POST/api/v1/ingest/email

Ponte per e-mail in ingresso indipendente dal provider. Postmark, Mailgun, SendGrid, Amazon SES, Make, n8n o un altro adattatore devono analizzare il payload del provider e inviare gli allegati accettati come dati del modulo multipart. DocSolved non ospita una casella di posta né esegue l'analisi MIME specifica del provider.

CampoTipoDescrizione
message_idstringobbligatorioIdentificatore di messaggio stabile del provider
source_namespacestringobbligatorioAmbito stabile di provider/account, ad esempio postmark:server-123
filesfile[]obbligatorioRipeti per ogni allegato supportato
organization_idstringfacoltativoSpazio di lavoro di destinazione; il chiamante deve disporre dell'autorizzazione al caricamento
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'idempotenza include il proprietario autenticato, lo spazio dei nomi del provider/account, la destinazione, l'ID messaggio, il nome file normalizzato, il contenuto del file e l'occorrenza tra allegati identici. I tentativi ripetuti del provider riordinati restituiscono gli ID job originali. Un'acquisizione non riuscita può riaccodare lo stesso job con byte nuovi fino a tre tentativi complessivi; i job attivi e completati non vengono mai elaborati due volte.

Ottieni lo stato del job

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
}

Stati possibili: queued, processing, review_required, completed, failed, cancelled.

Ottieni il risultato del job

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

Restituisce il risultato completo dell'estrazione quando lo stato del job è completed o review_required. Accetta l'ambito extract oppure history, quindi una chiave con il solo extract copre l'intero ciclo invio, polling, risultato.

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

Esporta JSON

POST/api/v1/export/json

Invia il risultato dell'estrazione come corpo JSON e ottieni un file di esportazione pulito.

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

Esporta 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

Esporta XLSX

POST/api/v1/export/xlsx

Restituisce una cartella di lavoro Excel con i fogli Riepilogo, Campi, Voci, Avvisi e Metadati.

Elenca cronologia

GET/api/v1/history

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

Flusso di revisione e approvazione

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

Applica una transizione controllata del flusso di lavoro a un record salvato. Questa route richiede una sessione Clerk interattiva: le chiavi API non possono approvare documenti. I membri dello spazio di lavoro possono effettuare la revisione; gli amministratori dello spazio di lavoro possono approvare, richiedere modifiche o rifiutare. Il proprietario di un record personale svolge entrambi i ruoli.

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

Azioni: start_review, complete_review, reopen_review, submit_for_approval, approve, request_changes, reject e accept_partial_analysis. L'approvazione registra insieme l'evento di audit del flusso di lavoro e l'evento outbox document.approved.

Elimina tutta la cronologia

DELETE/api/v1/history

Elimina definitivamente tutte le analisi salvate per il tuo account.

Elenca le chiavi API

GET/api/v1/keys

Crea una chiave 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"
}

Revoca una chiave API

DELETE/api/v1/keys/{key_id}

Crea 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 risposta include un secret per la verifica della firma. salvalo subito, non verrà mostrato di nuovo.

Tipi di evento webhook

EventoQuando si attiva
document.completedEstrazione completata e risultato salvato
document.review_requiredLa convalida o l'instradamento basato sulla confidenza richiedono una revisione umana; si attiva anche con document.completed
document.approvedUn approvatore autorizzato ha confermato la decisione di approvazione; usa questo evento per le scritture contabili
document.failedElaborazione non riuscita; i job acquisiti tramite e-mail includono la possibilità di ripetizione e i metadati dei tentativi
Usa document.approved, non document.completed, come punto di controllo per registrare dati in un sistema contabile. L'estrazione può essere completata mentre i campi richiedono ancora correzioni.

Testa webhook

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

Verifica la firma del webhook

Ogni consegna include queste intestazioni:

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)

Eventi durevoli non riusciti

DocSolved riprova automaticamente le consegne in uscita. Se un evento durevole nella coda outbox non può essere elaborato dopo cinque tentativi, diventa una dead letter. Il proprietario può ispezionare i metadati senza esporre il payload memorizzato e riprodurre l'evento dopo aver corretto la causa.

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_..."

Gli stessi controlli sono disponibili in Impostazioni sviluppatore → Eventi che richiedono attenzione. I record di consegna e outbox terminali sono conservati per 30 giorni.

Utilizzo con Make / n8n / Zapier

Per i caricamenti diretti, chiama /api/v1/jobs. Per le e-mail in ingresso, lascia che il provider analizzi gli allegati e chiami /api/v1/ingest/email con un ID messaggio e uno spazio dei nomi di origine stabili. Entrambe le route creano gli stessi job persistenti e usano lo stesso flusso di revisione.

Iscriviti agli eventi di completamento e revisione per lo stato, poi usa document.approved per attivare azioni contabili downstream controllate. I webhook firmati eliminano la necessità di effettuare polling.

Domande frequenti

Come mi autentico con l'API DocSolved?

Crea una chiave API su /developer — viene mostrata una sola volta — quindi inviala come token Bearer nell'header Authorization: Authorization: Bearer sk_docai_your_key.

Qual è la differenza tra /api/v1/analyze e /api/v1/jobs?

/api/v1/analyze restituisce il risultato nella stessa richiesta, adatto per un uso interattivo. /api/v1/jobs mette il documento in coda, così puoi interrogare il job o ricevere un webhook firmato al termine — soluzione migliore per lotti e documenti di grandi dimensioni.

Come vengo avvisato quando un documento è pronto?

Registra un webhook. DocSolved invia tramite POST un evento firmato con HMAC-SHA256 su document.completed, document.review_required, document.failed e document.approved. Verifica l'header X-DocAI-Signature e rispondi con un HTTP 2xx entro cinque secondi.

L'API restituisce le prove di origine per i valori estratti?

Per i documenti scansionati, ogni campo riporta il testo da cui è stato letto e, quando l'OCR ha individuato il valore, la relativa pagina e il rettangolo di delimitazione. Le fatture elettroniche strutturate vengono analizzate a partire dal loro XML e, per progettazione, non hanno un rettangolo di delimitazione.