Docsensedocumentazione per sviluppatori · v1

Documenti in ingresso, dati strutturati in uscita.

Invia un documento e uno schema di campi; ricevi JSON con un punteggio di affidabilità calibrato per ogni campo e — come add-on — le coordinate sul documento. Disponibile come API REST e come widget integrabile di cui i tuoi utenti si fideranno davvero.

BASE URLhttps://api.docsense.energyhub.cloud/v1  ·  AUTHAuthorization: Bearer sk_test_… | sk_live_…
Errori in formato RFC 9457 application/problem+json · Idempotency-Key rispettato sulle POST · elaborazione solo in UE (responsabile ex art. 28 GDPR).
Console: accedi con email e password (solo su invito — link monouso dal tuo amministratore). Le chiavi API si creano e si ruotano dalla sezione Chiavi API della console, riservata agli amministratori dello spazio di lavoro.

Quickstart — estrai in due chiamate

1 · Pubblica un template (versioni immutabili)

curl -X POST $BASE/v1/templates \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{
    "name": "electricity-invoice",
    "language_hint": "it",
    "features": {"grounding": true},
    "fields": [
      {"key": "holder_name",  "type": "string", "label": "Intestatario", "required": true},
      {"key": "pod",          "type": "string", "label": "Codice POD", "validate": "pod"},
      {"key": "iban",         "type": "string", "validate": "iban"},
      {"key": "total_amount", "type": "number", "required": true},
      {"key": "due_date",     "type": "date"}
    ]
  }'

Tipi scalari: string · number · integer · boolean · date · enum, più group (oggetto piatto) e table (righe di celle scalari). Validatori: iban · codice_fiscale · partita_iva · pod · pdr · cap · date · email — l'esito arriva campo per campo in checks e alimenta il punteggio di affidabilità.

2 · Esegui un'estrazione

curl -X POST $BASE/v1/extractions \
  -H "Authorization: Bearer $KEY" \
  -F "file=@bolletta.pdf" -F "template=electricity-invoice" -F "mode=sync"
{
  "status": "completed",
  "fields": {
    "pod": {
      "value": "IT001E12345678",
      "raw_text": "IT 001E 1234 5678",
      "confidence": 0.99,
      "status": "found",
      "checks": [{"name": "pod", "passed": true}],
      "locations": [{"page": 1, "bbox": {"x": 0.155, "y": 0.178, "w": 0.129, "h": 0.012}}]
    }
  },
  "usage": {"pages": 1},
  "processing": {"engine": "haiku", "duration_ms": 4800}
}

Usa mode=async (i documenti oltre 10 pagine girano sempre in async) e segui GET /v1/extractions/{id}/events — uno stream SSE che emette ogni campo nel momento in cui viene estratto, poi completed.

Bande di affidabilità usate in tutto il prodotto: ≥ 0,95 affidabile · 0,70–0,95 da controllare · < 0,70 attenzione. Automatizza sul punteggio: è calibrato e mai limitato dal piano. Le coordinate (locations) sono l'add-on grounding a pagamento; la qualità dell'affidabilità è identica con o senza.

Caricamento file & limiti

I documenti sono limitati a 50 MB su ogni percorso. Per tenere gli upload voluminosi fuori dal tuo percorso di richiesta (i byte vanno direttamente allo storage) — o per riusare lo stesso documento in più estrazioni — carica prima il file, poi riferiscilo per id:

curl -X POST $BASE/v1/files \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"filename": "bolletta.pdf", "content_type": "application/pdf"}'
# → { "id": "file_…", "upload": { "url": "https://…", "method": "PUT" }, … }

# carica i byte all'URL restituito (PUT S3 presignata, valida 15 minuti)
curl -X PUT "$UPLOAD_URL" -H "Content-Type: application/pdf" --data-binary @bolletta.pdf

curl -X POST $BASE/v1/extractions \
  -H "Authorization: Bearer $KEY" \
  -F "file_id=file_…" -F "template=electricity-invoice" -F "mode=async"

Verifica lo stato con GET /v1/files/{id}. I file caricati restano riusabili per 24 ore e poi vengono eliminati — ogni estrazione conserva la propria copia del documento secondo la retention del tuo workspace.

Le estrazioni sync (mode=sync) sono limitate per workspace in concorrenza: le risposte portano X-RateLimit-Limit / X-RateLimit-Remaining, e una richiesta oltre il limite riceve 429 con Retry-After. Il percorso async assorbe i picchi tramite la coda.

Widget integrabile

Il widget offre ai tuoi utenti finali caricamento → estrazione progressiva in tempo reale → revisione con evidenziazioni sul documento → conferma, dentro la tua pagina. Nessun account, nessun cookie; il documento va dall'iframe direttamente a Docsense, senza mai passare dalla tua origine.

1 · Crea una sessione (lato server, chiave segreta)

curl -X POST $BASE/v1/widget/sessions \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{
    "template": "electricity-invoice",
    "allowed_origins": ["https://app.yourcompany.com"],
    "locale": "it",
    "consent": "notice",
    "upload_hint": "Carica la tua ultima bolletta"
  }'
# → { "token": "swt_…", "expires_at": "…" }   (TTL 30 min, rinnovabile dal widget)

L'allowlist di origini governa anche la CSP frame-ancestors dell'iframe — solo le origini elencate possono incorporare la sessione. Il widget richiede un template con features.grounding (le evidenziazioni sono il widget).

2 · Integra (lato client)

<script src="https://api.docsense.energyhub.cloud/sdk/docex.js"></script>
<div id="docsense-slot"></div>
<script>
  var widget = DocEx.create({
    sessionToken: 'swt_…',              // dal tuo backend
    container: '#docsense-slot',
    locale: 'it',
    appearance: { variables: { colorPrimary: '#0E8A6A', borderRadius: '8px' } }
  })
  widget.on('fields.confirmed', function (p) {
    // p.values = mappa piatta chiave → valore finale rivisto dall'utente
    form.nome.value = p.values.holder_name || ''
    form.pod.value  = p.values.pod || ''
  })
</script>
Eventi (widget → te)Comandi (te → widget)
ready · upload.started · upload.progress · extraction.started · field.extracted (progressivo) · extraction.completed · fields.confirmed · error · resize · exit prefill(values) · setLocale('it'|'en') · setTheme(appearance) · retry() · destroy()

I tipi TypeScript arrivano con @docex/js. Tutti i messaggi sono nel namespace docex.*, versionati, exact-origin. Prova il flusso completo nella pagina demo.

Webhook

Ricevi una notifica quando un'estrazione termina, senza fare polling. Consegna at-least-once con backoff esponenziale (5 s → 30 s → 2 m → 10 m → 1 h, 6 tentativi).

curl -X POST $BASE/v1/webhook-endpoints \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"url": "https://app.yourcompany.com/hooks/docsense",
       "events": ["extraction.completed", "extraction.failed"]}'
# → { "id": "whe_…", "secret": "whsec_…" }   (secret mostrato una sola volta)

Ogni richiesta porta gli header webhook-id, webhook-timestamp e webhook-signature (schema compatibile svix). Verifica la firma prima di fidarti:

# python
import base64, hmac, hashlib

def verify(secret, headers, body: bytes) -> bool:
    key = base64.b64decode(secret.removeprefix("whsec_"))
    signed = f'{headers["webhook-id"]}.{headers["webhook-timestamp"]}.'.encode() + body
    expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode()
    got = [s.split(",", 1)[1] for s in headers["webhook-signature"].split() if s.startswith("v1,")]
    return any(hmac.compare_digest(expected, g) for g in got)

Payload: {"type": "extraction.completed", "created_at": …, "data": …} dove data è lo stesso body restituito da GET /v1/extractions/{id}. I tentativi di consegna sono ispezionabili su GET /v1/webhook-endpoints/{id}/deliveries.

Consumi e fatturazione

Due contatori, per pagina: pages_basic (valore + testo grezzo + affidabilità + verifiche) e pages_grounded (aggiunge le locations per campo). Il widget conta sempre grounded. Controlla i totali in ogni momento con GET /v1/usage. Le chiavi in modalità test (sk_test_…) non vengono mai fatturate.

Docsense · elaborazione solo in UE · riferimento OpenAPI · demo widget
© 2026 iBill S.r.l. con Socio Unico · Via dei Castani, 144 – 00172 Roma