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.
Estrai il tuo primo documento in meno di 3 minuti
- Crea una chiave API nelle Impostazioni sviluppatore. L'ambito
extractbasta per questo ciclo; la chiave viene mostrata una sola volta. - Invia il documento come job asincrono, interroga lo stato fino al completamento, recupera il risultato.
- Ogni campo in
result.extracted_fields[]ha le stesse chiavi:confidence,page,evidence(il testo di origine),match_statusebounding_box. Sul percorso OCR sono valorizzate quando il valore è stato localizzato sulla pagina (match_statusexact,fuzzyollm_located); un valore che l'OCR non è riuscito ad ancorare ènot_foundcon 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:
| Campo | Tipo | Descrizione | |
|---|---|---|---|
file | file | obbligatorio | PDF, PNG, JPG, HEIC, AVIF, TIFF, BMP o WEBP (max 15 MB) |
filename | string | facoltativo | Sostituisci 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.
| Campo | Tipo | Descrizione | |
|---|---|---|---|
message_id | string | obbligatorio | Identificatore di messaggio stabile del provider |
source_namespace | string | obbligatorio | Ambito stabile di provider/account, ad esempio postmark:server-123 |
files | file[] | obbligatorio | Ripeti per ogni allegato supportato |
organization_id | string | facoltativo | Spazio 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
| Evento | Quando si attiva |
|---|---|
document.completed | Estrazione completata e risultato salvato |
document.review_required | La convalida o l'instradamento basato sulla confidenza richiedono una revisione umana; si attiva anche con document.completed |
document.approved | Un approvatore autorizzato ha confermato la decisione di approvazione; usa questo evento per le scritture contabili |
document.failed | Elaborazione non riuscita; i job acquisiti tramite e-mail includono la possibilità di ripetizione e i metadati dei tentativi |
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:
X-DocAI-Event. Tipo di evento (es.document.completed)X-DocAI-Timestamp. Timestamp UTC ISO 8601X-DocAI-Signature.sha256=<hmac>
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.