TaxHarvest API
Sistema RAG per il diritto italiano ed europeo + UAE. Ricerca ibrida (vector HNSW + FTS + reranker) su 648.000+ documenti normativi e giurisprudenziali italiani + UE + UAE + internazionali, sintesi con pipeline anti-hallucination 9-stage, 65 codici indicizzati article-by-article, 67 fonti auto-scraping (61 IT + 6 UAE).
Stats live (20 mag 2026)
| Metric | Value |
|---|---|
| Total documents | 648.000+ (IT) + 836 (UAE) |
| Total chunks | 3.92M IT (pgvector HNSW 1536d) + 28K UAE (Voyage 1024d) |
| Fonti distinte | 67 (61 IT + 6 UAE, auto-scrape via scheduler 1×/day) |
| Codici Normattiva art-by-art | 65 codici / 14.963 articoli |
| Moduli macro-area Lexroom-style | 18 moduli (10 IT per materia + 3 IT per profilo professionale + 5 UAE) |
| Atti UE EUR-Lex indicizzati | 38 (GDPR, AI Act, NIS 1/2, DORA, MiCAR, PSD2, AMLD 4-6, ATAD, DAC, eIDAS, ecc.) |
| Cassazione | 336.000+ sentenze (civile + penale + costituzionale) |
| Giustizia Amministrativa | 269.000+ provvedimenti (TAR 30 sedi + CdS + CGA) |
| Citation hallucination rate | ~1% post Citation Guard + LLM Judge V2 + Re-prompt |
| Latency p50 | 15-25s end-to-end (/answer) · ~100ms (cache hit) · ~1-5s su /query (~700ms UAE) |
| Eval coverage | 305 query golden / 11 dataset / 7 profili (legacy) + 2.250 query / 15 moduli (baseline v25.101) |
Base URL
https://bancadati.doczoom.ai
Quick start (cURL)
curl -X POST https://bancadati.doczoom.ai/api/doczoom/answer \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "Soglia forfettario 2026?", "top_k": 10}'
UI standalone disponibili
| Route | Cosa è |
|---|---|
/ | Monitor live + chat playground |
/api-docs | Questa pagina (API documentation) |
/docs | Swagger UI auto-generato |
/redoc | ReDoc UI alternativo |
/alerts | Norm Alerts dashboard (v25.101): subscribe a fonti/moduli/keyword, vedi eventi |
/benchmark | 🆕 Modules Baseline Benchmark (v25.102): drill-down su 2.250 query baseline per 15 moduli |
/graph | Knowledge graph ontologico (50 concetti) |
/doc/{id} | 📄 Document viewer (v25.109): lettore pubblico del testo completo di un documento. Target consigliato del bottone "Apri fonte" — risolve i link non-deep-linkabili (es. SPA ItalGiure #id=... che obbliga a reinserire il codice della sentenza). Vedi campo viewer_url nelle response. v25.110: bottone Scarica → GET /doc/{id}/download?format=pdf|docx (PDF o Word formattati in stile DocZoom). |
Recent updates
- v25.115 (1 giu 2026): Entity-match SQL disattivato (retrieval più veloce) —
A/B test: lo stadio entity-match contribuiva 0 chunk ai risultati finali, aggiungeva 8-27s di latenza e
rompeva il reranker Voyage. Disattivato (la NER resta attiva per
entities_found). Moduli pesanti comeconsulente-lavoroda ~28s a ~2s. - v25.114 (1 giu 2026): Audit 67 fonti + 15 moduli · recall "Per fonte" + pulizia corpus —
testate tutte le fonti e i moduli esposti. Rimosse dal picker
corte_costituzionale(3.808 doc erano pagine di blocco anti-bot, non sentenze — purgati) edogi(0 doc) →GET /api/sourcesora ritorna 67 fonti utili. Ricerca filtrata per fonte: per filtri selettivi (≤ 10.000 doc) la NN ora è esatta within-source (recall perfetto, risolve fonti di nicchia che potevano tornare 0 risultati); le mega-fonti restano su HNSW. - v25.113 (1 giu 2026): statement_timeout sulla ricerca vettoriale —
tetto di 60s (env
VECTOR_SEARCH_TIMEOUT_S) sulle query vettoriali: una query cold che sfora viene troncata e degrada con grazia (l'API abstiene) invece di causare timeout/saturazione pool. - v25.112 (1 giu 2026): Fix indice HNSW (ricerca filtrata 10-40× più veloce) — le query filtrate per modulo/fonte ora usano correttamente l'indice HNSW (era ignorato per un mismatch di predicato sull'indice parziale): da 32-85s a 0,2-6s a regime.
- v25.110 (1 giu 2026): ⬇ Download PDF / Word dal viewer
/doc/{id}— nuovo bottone "Scarica" (stile Glass, dropdown no-JS) nel lettore:GET /doc/{id}/download?format=pdfoppure?format=docx. Il documento viene generato server-side con la formattazione del design system DocZoom (titolo serif editoriale, accento clay, intestazione con estremi + metadati, corpo giustificato, footer con fonte ufficiale + disclaimer + rif., paginazione per le sentenze lunghe). PDF via reportlab, Word via python-docx. Pubblico (no API key), come il viewer. - v25.109 (31 mag 2026): 📄 Document viewer
/doc/{id}+ campiviewer_url/doc_idnelle response — fix UX sulle fonti Cassazione. Il link che davamo all'utente era la SPA ItalGiurehttps://www.italgiure.giustizia.it/sncass/#id=<solr_id>: un hash-fragment client-side che NON fa deep-link → l'utente atterrava sulla maschera di ricerca e doveva reinserire a mano il codice della sentenza (~340K sentenze, ~100% del corpus Cassazione). Dal Solr scarichiamo solo il testo OCR (nei chunks), non il PDF.
Soluzione: nuovo lettore pubblicoGET /doc/{id}(no API key, contenuti legali pubblici) che ricostruisce il testo completo dai chunks (de-overlap), con intestazione ufficiale (es. Corte di Cassazione · Sez. III · Sent. n. 18633/2026, Pres./Rel.) e link alla fonte ufficiale in fondo. Le response di/query,/answer,/retrieve-legale/referenceora espongono per ogni sourcedoc_id+viewer_url(es.https://bancadati.doczoom.ai/doc/665989):urlresta la fonte ufficiale, usaviewer_urlcome target del bottone "Apri fonte". Funziona per tutte le fonti (Cassazione, Normattiva, AdE, UAE, …). Aggiunto indiceidx_documents_urlper il lookup batchurl→id. - v25.105 (25 mag 2026): ⚡ Fast-path jurisprudence lookup (200ms vs 43s) + fix "cassa→imprese minori" bug —
bug critico rilevato: query
"Cass. 11431/2026"non ritornava la sentenza pur essendo in DB. Cause: (1) la substring "cassa" dentro "Cassazione" triggerava espansione erratacassa→imprese minori; (2)doc_ref_patternsin rag.py copriva solo prassi AdE + leggi, nessun pattern per Cassazione/TAR/CdS/Corte Cost; (3) hybrid search impiega 41-170s su 3.92M chunks → watchdog 40s skip rag.multi_search → reference matching mai applicato.
Fix applicati: (1) DiscriminazionecassavsCassazione: se query contiene\bcassazion[ie]\bo\bcass\.o\bcass\s+(pen|civ|cost|sent|ord|sez|s\.u\.), skipcassada fiscal_terms + concept_thresholds. (2) Estesadoc_ref_patternscon 4 nuovi regex (cassazione, tar, cds, corte_cost) + source_filter applicato in SQL. (3) NEW: Jurisprudence fast-path in /api/doczoom/query: PRIMA di hybrid, verifica match regex sentenza/numero/anno; se sì, SQL diretto su title + source = ANY(...) → return immediato contop_score=1.0, shortcut=jurisprudence_lookup, latency 200-250ms (vs 43-170s precedente). Pattern coperti:Cass. 11431/2026,Cassazione Penale Ordinanza n. 11432/2026,TAR Roma 12345/2024,CdS 1234/2024,Corte Cost. 209/2022.
Verifica live: query "Cass. 11431/2026" ora ritorna in 237ms con top_score=1.0, top chunk = "Cassazione Penale Ordinanza n. 11431/2026" (doc 81817). - v25.104 (20 mag 2026): ⚖️ 13 endpoint giurisprudenza dedicati + fix bug authority filter —
aggiunto shortcut REST per ogni fonte giurisprudenziale:
/api/cassazione (336K),
/api/cassazione/{n}/{anno} (lookup),
/api/tar (242K),
/api/consiglio-stato (20K),
/api/corte-costituzionale (3.8K),
/api/cgue (1.4K),
/api/cedu,
/api/giustizia-tributaria,
/api/abf,
/api/agcm,
/api/agcom,
/api/sentenze-uae (102),
/api/adgm (80),
/api/difc (22).
Inoltre fix bug
/api/legal-judgments?authority=…: il parametro veniva ignorato e tornava sempre giustizia_amministrativa. Oraauthorityè documentato + mappato su_AUTHORITY_MAP(20 slug supportati) + risposta esponesources_searchedper trasparenza._JUDGMENT_SOURCES_ITesteso da 5 a 15 fonti (aggiunte CGUE, CEDU, ABF, AGCM, AGCOM, ANAC, Banca Italia, IVASS, Consob, EPO BoA — prima invisibili al browsing). - v25.103 (20 mag 2026): 👔 3 moduli "per profilo professionale" (commercialista, tributarista, consulente-lavoro) —
estensione di
modules.yamlcon 3 macro-moduli pensati per selezione rapida nel picker Studio. Coesistono con i 10 moduli per materia (Civile, Tributario, Penale…) e con le 66 collections L1-L3 (per profili granulari). Esempio uso:commercialista→ modulo macro generalista (fiscale + societario + bilancio + lavoro base);tributarista→ focused su contenzioso tributario + penale tributario;consulente-lavoro→ lavoro + previdenza + sicurezza + immigrazione. Totale moduli ora: 18 (10 IT materia + 3 IT professione + 5 UAE).GET /api/modulese filtromodules=[…]in/answer//queryli espongono nativamente. - v25.102 (20 mag 2026): 📊 Modules Baseline Benchmark + UI /benchmark —
eseguito retrieval-only benchmark sui 15 moduli (10 IT + 5 UAE),
150 query × modulo = 2.250 query totali in 9h41m.
Findings principali: UAE cluster 0.752-0.778 con 100% success rate
(Voyage-3-large 1024d top quality); IT range 0.500 (ip, gap corpus
reale) → 0.850 (penale, reference matching codificato). Mean IT 0.636
vs Mean UAE 0.770 → conferma valore upgrade embedding IT. Nuova UI
drill-down con tutte le 2.250 query visibili, filtri search/diff/conf,
sort multi-colonna. Risultati in
eval/results/baseline_20260519_224355/. Costo run: ~$0.45. - v25.101 (20 mag 2026): 📡 Norm Alerts + scheduler harmonization 1×/day + 11 sub-collections + api-docs full audit — nuova feature notifiche normative (8 endpoint + UI standalone): 6 sub_type (source/module/collection/keyword/reference/country), scan-on-poll architecture, backfill 7-day per UX iniziale. Scheduler ricalibrato da 38 a 59 entry, ognuna 1×/day spread su 24h UTC (aggiunte 26 fonti IT precedentemente non-scheduled). 11 sub-collections L3 nuove (7 commercialista + 4 tributarista). Full audit api-docs 2026-05-20: 12 drift fixati (12 endpoint nuovi documentati, /answer parameter table espansa 4→11 campi, architecture diagram 6→9 stage, numeri 215K→648K docs, version drift v25.86→v25.100).
- v25.100 (18 mag 2026): 🔗 Slug allineati DZ CODES_CATALOG (fix codici "non trovati") —
estesa
IT_UI_METADATAda 16 a 58 codici per coprire l'intera hardcodedCODES_CATALOGdi doczoom-studio. Bug pre-v25.100: per i 48 codici non in IT_UI_METADATA, l'endpoint auto-generava slug lunghi (es.preleggi-disposizioni-sulla-legge-in-generale), ma DZ hafindCodeBySlughardcoded che cercapreleggibreve → empty state nella detail page. Ora gli slug TaxHarvest matchano 1:1 quelli DZ:preleggi,jobs_act,tu_espropriazioni,cod_pari_opportunita,tu_immigrazione,cod_antimafia, ecc. Restano 6 codici minori in TaxHarvest ma non ancora in DZ CODES_CATALOG (testo-unico-infortuni-lavoro-dpr-1124-1965,ordinamento-giurisdizione-tributaria, ecc.) — questi sono "extra" che DZ può aggiungere quando vuole. - v25.99 (18 mag 2026): 📖 /api/legal-codes DZ drop-in + UAE document detail fix —
refactor di
/api/legal-codesper matchare lo shape che il frontend DocZoom già usa perCODES_CATALOGhardcoded:{slug, name, shortName, description, category, articles, taxharvestSource, taxharvestCategory}. Eliminata la necessità di hardcoding lato DZ:const catalog = (await fetch(...)).categoriesè drop-in con il map/filter esistente.
Percountry=IT: 64 codici Normattiva con UI metadata curated per i 16 core (CC, CPC, CP, CPP, TUIR, TUF, TUB, IVA, Statuto Contribuente, CCII, Cod. Assicurazioni, Cod. Consumo, Costituzione, ecc.). Percountry=AE: 4 catalog entries (DIFC Laws 144 · ADGM Regulations 57 · CBUAE Federal Decree-Laws 190 · FTA Public Clarifications 343).
Fix critico:GET /api/document/{id}ora legge dachunks_uae(Voyage 1024d) per docs UAE invece dichunks. Drawer DocZoom mostra correttamente full_text per leggi UAE (es. DIFC Arbitration Law → 44 chunks, 59.5K char). - v25.98 (18 mag 2026): 📖 /api/legal-codes + /api/legal-judgments (country-aware) —
2 nuovi endpoint per le tab "Codici" e "Sentenze" di DocZoom. Country-aware
(IT/AE), stessa shape per entrambi i paesi. Eliminano l'hardcoding lato
frontend (CODES_CATALOG IT-only, sources=['cassazione'] fisso).
GET /api/legal-codes?country=IT→ 64 codici Normattiva.
GET /api/legal-codes?country=AE→ 734 voci (DIFC Laws + ADGM Regulations + CBUAE Federal Decree-Laws + FTA Guides).
GET /api/legal-judgments?country=AE→ 102 judgments (80 ADGM + 22 DIFC) con court/year/case_number/parties parsed on-the-fly da slug.
GET /api/legal-judgments?country=IT&court=Cassazione&year=2025→ filter su 336K sentenze IT con paginazione. UAE judgment parsing: slug patternADGM-ADGMCFI-2025-262→{court:"ADGM CFI", year:2025, case_number:"ADGMCFI-2025-262", parties:["X","Y"]}. - v25.97 (18 mag 2026): 🔍 GET /api/sources enriched —
risposta ora include per ogni source:
country(IT/AE),doc_count(live count),modules(lista moduli di appartenenza),registered_scraper(bool). Nuovi query params?country=IT|AE|alle?module={id}per filtering server-side. Permette a DocZoom di mostrare il picker fonte-singola filtrato per paese o modulo senza enumerare lato client. Backward compat preservata: chiave"sources"rimane lista di stringhe per i client v1. - v25.96 (18 mag 2026): 📚 Modules full coverage audit — 0 codici orfani —
audit completo del corpus 67 fonti / 64 codici normattiva. Pre-audit:
5 sources orfane (gazzetta_ufficiale, eur_lex, eurlex, eiopa, istat) +
28 codici normattiva orfani + 3 cassazione macro_area orfani.
Post-audit: SOLO
istat(2 docs, marginale) escluso. Aggiunti cross-cutgazzetta_ufficiale+eur_lex+eurlexa tutti i 10 moduli IT. Aggiunti 13 codici genuinamente mancanti (Cod. Assicurazioni Private, CAD, Antimafia, CPP Minorile, TU Pubblico Impiego, Cod. Terzo Settore, ecc.). Fix 10+ string-mismatch alias (DB "Codice del Processo Tributario" vs YAML "Processo tributario"). Coverage doc-count post-fix: amministrativo 110K→285K, privacy 600→11K, lavoro 12K→33K, bancario 6K→26K. Nuovo endpointGET /api/countriesper Settings DocZoom (lista paesi + statistiche, no hardcoding). Benchmark discriminazione: 13/44 primary > distractor (+3 vs v25.95), 0 risposte identiche. - v25.95 (18 mag 2026): 📚 Module filter sub-source granularità —
metadata-aware predicate (cassazione
macro_area+ normattivacodice) applicato pre-truncation. Internal top_k boost (×3, cap 60) per assorbire i drop. Batch SQL enrichment per i record da reference/article match che non portanodoc_metadata. Case-insensitive match. "Untagged fallback" per le 199K cassazione storiche senza macro_area (recall > precision). Live discrimination verified:licenziamento→ lavoro=1, tributario=2, civile=0;GDPR art 6→ privacy=1, civile/lavoro/tributario=0;accertamento DPR 600→ tributario=4, civile/lavoro=0. - v25.94 (18 mag 2026): 🇦🇪 +5 moduli UAE + cross-country validator —
aggiunti 5 moduli UAE (
uae-tax,uae-banking-amlcft,uae-difc,uae-adgm,uae-common-law) che si applicano alla pipeline UAE isolata (Voyage-3-large + chunks_uae). Aggiunto campocountry: IT|AEa ogni modulo nel YAML, e validator cross-country in/api/doczoom/query: se i moduli scelti appartengono a un country diverso da quello del request → HTTP 400module_country_mismatch. Nuovo query param?country=IT|AE|allsuGET /api/modules. Totale moduli ora: 15 (10 IT + 5 UAE). - v25.93 (18 mag 2026): 📚 10 moduli macro-area Lexroom-style —
nuovo sistema di filtraggio per macro-area giuridica cross-source. Definiti
10 moduli (
diritto-civile,diritto-tributario,privacy-data-protection,diritto-bancario,diritto-del-lavoro,diritto-societario,diritto-di-famiglia,diritto-amministrativo,ip-proprieta-intellettuale,diritto-penale) inmodules.yaml. Ogni modulo è una lista di filtri (source + metadata predicate, es. cassazione.macro_area="tributario", normattiva.codice="TUIR"). Nuovi endpoint:GET /api/modules+GET /api/modules/<id>con live doc_counts per source. Nuovo body fieldmodules: list[str]suPOST /api/doczoom/query. Defensive post-filter garantisce che chunks non appartenenti al modulo vengano droppati prima della response. Differenza dacollections: moduli = macro-aree pure (giuridiche), collections = profili professionali / temi commerciali. Possono coesistere. - v25.92 (18 mag 2026): 🇦🇪 UAE final: FTA round 2 completato (522→836 docs) — FTA Public Clarifications cresciuto da 29→343 docs / 622→8.988 chunks dopo secondo bootstrap (timeout 5h, finito in 27min). Pipeline OCR ha gestito bulletins VAT/CT/Excise rasterizzate. 34 PDF rifiutati (text vuoto / ZIP files erroneamente serviti come PDF). UAE corpus finale: 836 docs / 28.379 chunks su 6 sources. Restano bloccate solo eLaws (TCP IP block) e FSRA (text empty upstream).
- v25.91 (18 mag 2026): 🇦🇪 UAE full PDF coverage (413→522 docs, 6/8 sources) — ADGM-Courts (80 docs / 2.976 chunks via OCR Tesseract) + FTA Public Clarifications (29 docs / 622 chunks) importati. ADGM-Courts ha 146 Print-to-PDF judgments rasterizzati, processati in 38 min totali (vs stima 10-20h: cap 30 pp/PDF a DPI 120 sufficiente per la maggior parte dei judgments). Test live retrieval OK su tutti 6 sources con top scores 0.74-0.80. FTA round 2 in BG (5h timeout) per i 126 bulletins rimanenti.
- v25.90 (18 mag 2026): 🇦🇪 UAE corpus expansion (212→413 docs) —
nuovo
common/pdf_extract.pyinlegal-sources-overlay/: pipeline a 3 livelli pypdfium2 streaming → pdfplumber fallback → Tesseract OCR (poppler + pytesseract) per PDF rasterizzati. Cap OCR a 30 pp/PDF + DPI 120 per limitare tempi. Cache PDF a/tmp/uae_pdf_cache/<sha256>. Nuove fonti importate:uae_adgm_legislation(57 docs / 2K chunks — ADGM Courts Regulations + Abu Dhabi laws) +uae_difc_legislation(144 docs / 9.7K chunks — DIFC Arbitration / Common Reporting / Companies / Contract Law). Containertaxharvest-apimemory bumped 2→4G dopo OOM kill durante Voyage multiprocessing embed. FTA + ADGM-Courts in overnight OCR. - v25.89 (18 mag 2026): 🇦🇪 UAE corpus + country isolation —
nuovo param
countryISO-2 (default["IT"], opzionale["AE"]) su/api/doczoom/query. Tabella separatachunks_uaecon embedding Voyage-3-large 1024d (legal-domain). Import iniziale: 190 docs CBUAE (AML/CFT, Federal Decree-Laws, regolamenti) + 22 DIFC Courts judgments. Pipeline UAE: voyage embed → HNSW search → top-K, p50 500ms. Validazione fail-fast: country diverso da IT/AE → HTTP 400unsupported_country. Roadmap: FTA Public Clarifications, ADGM Courts/Legislation, DIFC Legislation, eLaws (PDF extractor in dev). - v25.86 (14 mag 2026): +30 sub_area routing per /retrieve-legal —
7 practice_areas / 42 routings totali. Coverage istituti civili (compravendita,
mutuo, fideiussione, locazione comm./abit., mandato, comodato, appalto,
assicurazione, donazione, successioni, condominio, revocatoria, resp. EC),
lavoro (mobbing, trasferimento azienda), tributario (accertamento, contenzioso,
IVA), penale (reati tributari, bancarotta, 231), amministrativo (urbanistica,
concorrenza), corporate (cessione SRL, op. straordinarie, DD M&A), privacy
(GDPR compliance, data breach). Nuovo endpoint
GET /api/doczoom/practice-areasespone tassonomia live. - v25.83: meta-handler conservativo — solo saluti + identita. Drop falsi positivi su query legali con "costi" / "privacy".
- v25.80:
/retrieve-legalcon must_include anchor, authority_mix, MMR diversity, score_breakdown, exclude_authorities, validation fail-fast HTTP 400. - v25.77: nuovo endpoint
/retrieve-legalcon practice_area routing. - v25.74 (mag 2026): 15 nuove fonti EU + IT + intl (+928 docs) — EBA, EIOPA, ESMA, AMLA, FSB, IASB, BIS BCBS, UIF, AgID, IVASS, INAIL, MLPS, ANAC, ADM, ARERA.
- v25.66: pulizia metadata XML residui in chunks di sentenze TAR/CdS, miglior qualità retrieval su modulo amministrativo.
- v25.55-60: supporto query in inglese su atti UE (GDPR / AI Act / NIS / EPO / HUDOC) con risposta nella stessa lingua. Fix parser Solr Cassazione (text/plain content-type).
- v25.43-54: 6 nuovi scraper — Borsa Italiana regolamenti, EPO Boards of Appeal Case Law 2025, HUDOC CEDU landmark v Italy, Negoziazione Assistita art-by-art, AGCM bollettini settimanali. Privacy boost: EDPB, atti UE Cyber/Data Act, TRIPS WTO, Convenzione Aja, CEDU IT. EUR-Lex 38 atti art-by-art.
- v25.36-42: NIS 2 + DORA + GDPR + CNF Codice Deontologico + Convenzione ONU
Diritti Fanciullo indicizzati art-by-art.
cassazione_macro_areeapplicate ai moduli L1 (riduzione rumore). 14 nuovi moduli L1 (Lexroom-style) incollections.yaml. - v25.18-35: pipeline anti-allucinazione 9-stage
(Citation Guard + LLM Judge V2 + Re-prompt automatico + factuality soft flag). Hallucination
rate residuo ~1%. Endpoint
/api/doczoom/articlesper fetch deterministico articoli. Flagprefer_speed=trueper skip re-prompt (latency ridotta).collectionsparam su/answerper pre-filter retrieval domain-specific.
Authentication
Tutti gli endpoint richiedono una API key passata nell'header X-API-Key.
Le richieste senza key valida ricevono 401 Unauthorized.
X-API-Key: th_live_xxxxxxxxxxxxxxxxxxxxxxxx
taxharvest-demo-2026.
In produzione richiedi una chiave dedicata via email.
Architecture
Ogni chiamata /api/doczoom/answer attraversa una pipeline a 9 stage
con macchina anti-allucinazione (Citation Guard + LLM Judge V2 + Re-prompt automatico +
Factuality soft flag). Latency p50 15-25s end-to-end (cache hit ~100ms). Per pipeline
retrieval-only (/api/doczoom/query): 1-5s IT, 500-800ms UAE.
entities_found.)needs_verification=true (soft, no blocco). Audit log PostgreSQL fire-and-forget.
Note: gli stage 0-2 sono fast-path (bypassano retrieval/LLM se applicabili).
Lo stage 6 (Citation Guard) opera prima del Judge V2 per ridurre falsi positivi. Lo stage 9
(Factuality soft flag) usa lo stesso fact extractor del Citation Guard ma come segnale
all'utente, non come blocco. Pipeline retrieval-only (/api/doczoom/query) salta
stage 5-9 (no LLM).
Componenti
| Layer | Tecnologia | Scopo / config |
|---|---|---|
| Embeddings IT | text-embedding-3-small (OpenAI, 1536d) | Vector search HNSW chunks |
| Embeddings UAE | voyage-3-large (Voyage, 1024d) | Vector search HNSW chunks_uae (country isolation) |
| Vector index | pgvector HNSW (m=16, ef_construction=64) | O(log n) nearest-neighbor + iterative_scan strict_order |
| FTS | PostgreSQL tsvector italiano + GIN trigram | Lexical match con highlighting |
| Reranker | voyage rerank-2.5-lite (Voyage) | Cross-encoder top-50 → top-10. Free 12 mesi (200M token quota). Fallback merge order su 429. |
| Query rewrite | gemini-3.1-flash-lite-preview via OpenRouter | Espansione naturale + load smoother. Redis cache TTL 1h. Kill switch REWRITER_DISABLED=true. |
| LLM synthesis | Configurabile via OPENROUTER_MODEL env (default qwen/qwen3-235b-a22b) | Risposta finale con temp 0.0, max_tokens 4096 |
| LLM judge factuality | gemini-3.1-flash-lite-preview via OpenRouter | Verdetto OK/ISSUE con dossier strutturato (chain-of-thought max_tokens 400) |
| Meta-handler LLM fallback | gemini-3.1-flash-lite-preview (stage-2) | Solo per query non-legali ambigue. Skip se segnali legali nel query. |
| Database | PostgreSQL 16 + pgvector + GIN FTS + trigram | 3.92M chunks IT + 28K UAE indicizzati |
| Cache | Redis 7 | TTL 10 min /answer · 1h rewriter · 10 min rerank |
| Anti-hallucination | Citation Guard + LLM Judge V2 + Re-prompt + Factuality flag | ~1% hallu residue post pipeline (vs ~17% pre-guardrails) |
Errors & Rate limits
Risposte di errore in formato JSON con campi error e detail.
| Status | Significato | Azione |
|---|---|---|
| 200 | OK | Successo |
| 401 | API key mancante o invalida | Verifica header X-API-Key |
| 429 | Rate limit superato | Default 60 req/min per IP. Riduci frequenza |
| 500 | Errore server interno | Riprova; se persiste apri ticket |
Rate limit
Default 60 richieste/minuto per IP. Per limiti più alti contatta il team.
DocZoom Answer
End-to-end RAG: retrieval ibrido + cross-encoder rerank + LLM synthesis. Restituisce una risposta sintetica + lista fonti citabili. Endpoint principale per il frontend DocZoom.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | required | Domanda dell'utente (max 2000 char). |
| top_k | integer | optional | Numero chunk passati al LLM. Default 10, range 1–25. |
| sources | string[] | optional | Filtro fonti specifiche (es. ["normattiva","ade_circolari"]). Unione con collections e modules se forniti. |
| collections | string[] | optional | Filtro collections professionali (es. ["commercialista-iva","tributarista-accertamento"]). Vedi GET /api/collections. |
| min_relevance | float | optional | Soglia minima score reranker. Default 0.3, range 0.0–1.0. Sotto soglia → abstention. |
| document_context | string | optional | Testo di un documento caricato dall'utente (contratto, bilancio, ecc.). Massimo 100K char. Iniettato nel system prompt come contesto aggiuntivo per analisi. |
| document_name | string | optional | Nome del file caricato (per citazione nel prompt). |
| profile | string | optional | Profilo professionale per tuning prompt (es. "Commercialista", "Avvocato Tributarista"). Influenza tono e priorità citazioni. |
| materia | string | optional | Materia giuridica (es. "IVA", "Diritto societario"). Influenza routing e boost di source pertinenti. |
| prefer_speed | boolean | optional | Default false. Se true: timeout aggressivi + skip re-prompt + skip multi_search. Per UX real-time, accetta -5% kw recall. |
| max_output_tokens | integer | optional | Default 4096 (regola cardinale, non ridurre senza motivo). Range 100-8192. Per risposte brevi su query semplici. |
Example request
curl -X POST https://bancadati.doczoom.ai/api/doczoom/answer \
-H "X-API-Key: $TAXHARVEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Qual è la soglia forfettario 2026?",
"top_k": 10,
"profile": "Commercialista",
"materia": "IVA"
}'
import requests, os
resp = requests.post(
"https://bancadati.doczoom.ai/api/doczoom/answer",
headers={"X-API-Key": os.environ["TAXHARVEST_API_KEY"]},
json={
"query": "Qual è la soglia forfettario 2025?",
"top_k": 15,
},
timeout=120,
)
data = resp.json()
print(data["answer"])
const resp = await fetch("https://bancadati.doczoom.ai/api/doczoom/answer", {
method: "POST",
headers: {
"X-API-Key": process.env.TAXHARVEST_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({
query: "Qual è la soglia forfettario 2025?",
top_k: 15,
}),
});
const data = await resp.json();
console.log(data.answer);
Response
{
"query": "Qual è la soglia forfettario 2025?",
"answer": "La soglia per il regime forfettario 2025 è di **85.000 €** di ricavi/compensi (Legge di Bilancio 2025, L. 207/2024). Il superamento oltre 100.000 € comporta uscita immediata dall'IVA forfettario.",
"sources": [
{
"title": "INPS Circolare n. 27 del 30/01/2025",
"url": "https://www.inps.it/...",
"source": "inps_circolari",
"doc_type": "circolare",
"relevance_score": 0.92
}
],
"chunks": [/* 15 chunks completi con testo, citazione formale, autorità */],
"confidence_level": "high",
"top_score": 0.92,
"needs_verification": false,
"has_ai_summary": false,
"timing_ms": {
"embedding_ms": 200,
"vector_search_ms": 800,
"rerank_ms": 350,
"llm_ms": 2500,
"total_ms": 8500
}
}
Response fields
| Field | Type | Description |
|---|---|---|
| answer | string | Risposta sintetizzata dal LLM. 1–4 frasi tipicamente. |
| sources | object[] | Fonti citabili (top 15). Per ogni fonte: title, url (fonte ufficiale), source, doc_type, relevance_score, doc_id, viewer_url (lettore interno /doc/{id} — usalo come target del bottone "Apri fonte"). |
| chunks | object[] | Chunks completi con testo, articolo, citazione formale. |
| confidence_level | string | high (top_score ≥0.7), medium (0.4–0.7), low (<0.4), no_results (0 chunk), cheatsheet_fastpath (v15). |
| top_score | float | Score cross-encoder reranker del chunk top-1. |
| needs_verification | boolean | True se confidence < high. UI deve mostrare warning. |
| has_ai_summary | boolean | True se almeno un chunk è AI-summary (mostrare disclaimer). |
| timing_ms | object | Breakdown latenze per ogni stage (debug). |
DocZoom Retrieve-Legal RACCOMANDATO · v25.86
Endpoint legale strutturato per chat avvocato/commercialista.
Estende /retrieve con practice_area + sub_area routing
dedicato per materia: forza norme base, filtra Cassazione per macro_area,
applica must_include anchor sui ~10 articoli canonici dell'istituto.
Tassonomia practice_area / sub_area (42 routings, v25.86)
Per la lista live + dettaglio routing usa GET /api/doczoom/practice-areas.
| practice_area | sub_areas disponibili |
|---|---|
civile | responsabilita_medica · contratti · locazione_commerciale · locazione_abitativa · fideiussione · compravendita_immobiliare · mandato · mutuo · comodato · appalto · assicurazione · donazione · successioni · responsabilita_extracontrattuale · condominio · azione_revocatoria |
lavoro | patto_non_concorrenza · licenziamento · mobbing_demansionamento · trasferimento_azienda |
tributario | accertamento · contenzioso · iva · forfettario |
penale | reati_tributari · bancarotta · responsabilita_231 |
amministrativo | urbanistica_edilizia · concorrenza · appalti |
corporate | cessione_quote_srl · operazioni_straordinarie · due_diligence |
privacy | gdpr_compliance · data_breach |
Ogni practice_area accetta anche sub_area: null per il routing generico (vedi /api/doczoom/practice-areas per dettagli).
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | required | Domanda dell'avvocato/commercialista. |
| practice_area | string | recommended | Materia (vedi tabella). HTTP 400 se valore sconosciuto. |
| sub_area | string | recommended | Sotto-area specifica per routing dedicato. Default fallback al routing generic della practice_area. |
| must_include | string[] | optional | Anchor articoli che DEVONO uscire (es. ["Art. 1815 Codice Civile"]). Override defaults del routing. |
| must_include_mode | string | optional | "anchor" (default: chunk #1 score 0.99 se trovato in DB) · "boost" (+0.20 al relevance) · "strict" (HTTP 404 se 0 match). |
| authority_mix | object | optional | Bilanciamento top_k: {"norms": 3, "case_law": 7, "practice": 2}. Default da routing. |
| exclude_topics | string[] | optional | Hard filter keyword (es. ["pubblico impiego"]). |
| exclude_authorities | string[] | optional | Filtro doc_type/source (es. ["circolare", "cassazione_penale"]). |
| exclude_date_range | object | optional | {"from": "YYYY-MM-DD", "to": "YYYY-MM-DD"}. |
| max_chunks_per_document | int | optional | MMR diversity (default 2). Evita 3 chunk consecutivi stesso doc. |
| include_score_breakdown | bool | optional | Se true, espone {vector, raw_score, distance, anchor} per chunk. |
| explain | bool | optional | Se true, ritorna campo explain con metadata debug. |
| context_format | string | optional | Default "llm_xml". Anche "compact", "markdown". |
| top_k | int | optional | Default 12. Range 1-30. |
| min_relevance | float | optional | Default 0.3. |
Esempio — Mutuo / usura
curl -X POST https://bancadati.doczoom.ai/api/doczoom/retrieve-legal \
-H "X-API-Key: $TAXHARVEST_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "Verifica tasso usurario mutuo ipotecario 2015 TAEG soglia",
"practice_area": "civile",
"sub_area": "mutuo",
"top_k": 10
}'
Ritorna 5+ chunks: Art. 1813 (nozione mutuo), Art. 1815 (interessi usurari),
Art. 1819 (restituzione rateale), Art. 1820 (mancato pagamento) + Cassazione
bancaria macro_area=banca_finanza.
Esempio — Locazione commerciale 6+6
POST /api/doczoom/retrieve-legal
{
"query": "Locatore vuole rifiutare primo rinnovo 6 anni per uso diretto come studio professionale, art 29 indennità avviamento",
"practice_area": "civile",
"sub_area": "locazione_commerciale",
"explain": true
}
Ritorna anchor injection di 6 articoli L. 392/1978 (artt. 27, 28, 29, 31, 34, 35) con score 0.99 garantito + Cassazione locazione.
Response (DoczoomRetrieveLegalResponse)
Stessa struttura di /retrieve + campi legal:
| Field | Type | Description |
|---|---|---|
| detected_issues | string[] | Issue tags identificati dalla query (es. ["estensione_garanzia", "decadenza_1957"]) |
| rewritten_queries | string[] | Query rewriting tematiche del routing |
| authority_breakdown | object | Distribuzione effettiva: {"norms": 5, "case_law": 7, "practice": 0} |
| explain | object | (se explain=true) routing_slug, filtri applicati, must_include_resolved, ranking_strategy |
| chunks[].published_date | string | ISO date estratta da metadata + parsing title |
| chunks[].section | string | Sezione Cassazione/CdS |
| chunks[].macro_area | string | Macro-area Cassazione (lavoro_previdenza, tributario, ecc.) |
| chunks[].is_abrogated | bool | Norma abrogata (per Normattiva) |
| chunks[].score_breakdown | object | (se include_score_breakdown=true) componenti scoring |
Validation errors
HTTP 400 se practice_area non valida:
{
"detail": {
"error": "invalid_practice_area",
"value": "non_esistente",
"valid": ["amministrativo", "civile", "corporate", "lavoro", "penale", "privacy", "tributario"],
"hint": "Vedi GET /api/doczoom/practice-areas"
}
}
HTTP 404 se must_include_mode="strict" + 0 anchor risolti.
Practice Areas (tassonomia) v25.86
Lista live di tutti i routings disponibili per
/retrieve-legal. Use case: client carica all'avvio +
cache, popola sub_area picker UI + classifier client-side.
Response
{
"total_areas": 7,
"total_routings": 42,
"valid_slugs": ["amministrativo", "civile", "corporate", "lavoro", "penale", "privacy", "tributario"],
"practice_areas": [
{
"practice_area": "civile",
"sub_areas": ["mutuo", "fideiussione", "locazione_commerciale", null, ...],
"routings": [
{
"sub_area": "mutuo",
"slug": "civile__mutuo",
"name": "Civile — Mutuo (artt. 1813-1822 c.c.)",
"sources": ["normattiva", "cassazione"],
"normattiva_codici": ["Codice Civile", "TUB - Testo Unico Bancario"],
"cassazione_macro_aree": ["banca_finanza", "contratti_obbligazioni"],
"must_include_defaults": ["Art. 1813 Codice Civile", "Art. 1815 Codice Civile", ...],
"default_authority_mix": { "norms": 5, "case_law": 5, "practice": 0 }
},
/* ... altre routings ... */
]
},
/* ... altre 6 practice_areas ... */
]
}
Pattern d'uso — Client classifier
# 1. Bootstrap all'avvio (1 volta, cacheable)
PRACTICE_AREAS = requests.get(
f"{TAXHARVEST_BASE}/api/doczoom/practice-areas",
headers={"X-API-Key": KEY},
).json()
VALID_SLUGS = set(PRACTICE_AREAS["valid_slugs"])
# 2. Classifier rule-based client-side
CLASSIFIER_PATTERNS = [
(r"\b(?:mutuo|TAEG|usura|tasso\s+soglia)\b", "civile", "mutuo"),
(r"\b(?:fideiussor|fideiussione|art\s+1936|art\s+1957)\b", "civile", "fideiussione"),
(r"\b(?:locazione|6\+6|L\.\s*392|equo\s+canone)\b", "civile", "locazione_commerciale"),
(r"\b(?:patto\s+(?:di\s+)?non\s+concorrenza|art\s+2125)\b", "lavoro", "patto_non_concorrenza"),
(r"\b(?:demansionamento|dequalifica|art\s+2103)\b", "lavoro", "mobbing_demansionamento"),
(r"\b(?:DD|due\s+diligence|M&A|cessione\s+quote|SPA)\b", "corporate", "due_diligence"),
(r"\b(?:GDPR|consenso|DPO|art\s+37\s+GDPR)\b", "privacy", "gdpr_compliance"),
# ... 35+ pattern (vedi /practice-areas per lista completa)
]
def classify(query: str) -> tuple[str | None, str | None]:
for pat, pa, sa in CLASSIFIER_PATTERNS:
if re.search(pat, query, re.IGNORECASE):
return pa, sa
return None, None
# 3. Chiamata corretta a /retrieve-legal
pa, sa = classify(user_query)
resp = requests.post(
f"{TAXHARVEST_BASE}/api/doczoom/retrieve-legal",
headers={"X-API-Key": KEY},
json={
"query": user_query,
"practice_area": pa, # <-- CRITICO
"sub_area": sa, # <-- CRITICO
"top_k": 12,
},
).json()
Lista completa sub_areas (42 routings)
| Practice area | Sub_area | Articoli base / norme |
|---|---|---|
civile | contratti | Codice Civile contratti |
responsabilita_medica | Art. 1218, 2043, 2236 c.c. | |
responsabilita_extracontrattuale | Art. 2043-2059 c.c. | |
compravendita_immobiliare | Art. 1470, 1487, 1490, 1497, 2643, 2932 c.c. | |
locazione_commerciale | L. 392/1978 art. 27-29, 31, 34, 35 | |
locazione_abitativa | L. 431/1998 | |
condominio | Art. 1117-1138 c.c. | |
fideiussione | Art. 1936-1957 c.c. (10 anchor) | |
mutuo | Art. 1813-1822 c.c. + TUB | |
mandato | Art. 1703-1730 c.c. | |
comodato | Art. 1803-1812 c.c. | |
appalto | Art. 1655-1677 c.c. | |
assicurazione | Art. 1882-1932 c.c. + Cod. Ass. (D.Lgs. 209/2005) | |
donazione | Art. 769-809 c.c. | |
successioni | Art. 587-712 c.c. + TU 346/1990 | |
azione_revocatoria | Art. 2901-2904 c.c. | |
| generic | Codice Civile + CPC | |
lavoro | patto_non_concorrenza | Art. 2125 c.c. + L. 300/70 |
licenziamento | Art. 18 Statuto + L. 604/1966 + Jobs Act | |
mobbing_demansionamento | Art. 2087, 2103, 2729 c.c. | |
trasferimento_azienda | Art. 2112, 2560 c.c. | |
| generic | Lavoro generico | |
tributario | forfettario | TUIR + DPR 633/72 |
accertamento | DPR 600/1973 + Statuto Contribuente | |
contenzioso | D.Lgs. 546/1992 | |
iva | DPR 633/1972 | |
| generic | Tributario generico | |
penale | reati_tributari | D.Lgs. 74/2000 |
bancarotta | RD 267/42 + Codice Crisi | |
responsabilita_231 | D.Lgs. 231/2001 | |
| generic | Codice Penale + CPP | |
amministrativo | appalti | D.Lgs. 36/2023 + CPA |
urbanistica_edilizia | TU Edilizia (DPR 380/2001) | |
concorrenza | L. 287/90 + AGCM bollettini | |
| generic | CPA + L. 241/90 | |
corporate | cessione_quote_srl | Art. 2469-2473 c.c. |
operazioni_straordinarie | Art. 2498-2506 c.c. | |
due_diligence | Art. 1337, 1370, 1489-1497 c.c. (excl. tributario) | |
| generic | Civile societario + TUF | |
privacy | gdpr_compliance | GDPR art. 5, 6, 7, 13, 32, 35, 37, 83 |
data_breach | GDPR art. 32, 33, 34 | |
| generic | eur_lex + Garante + EDPB |
DocZoom Retrieve BYOL · v25.75
Endpoint dedicato Bring Your Own LLM. Stessa engine di
/query ma con default ottimizzati per consumo LLM downstream:
top_k=15, min_relevance=0.4, context_format=llm_xml,
group_by_document=true. Quello che serve a DocZoom per ricevere
chunks pre-filtrati e generare la risposta col proprio LLM.
Differenze rispetto a /query
| Field | /query default | /retrieve default | Perché |
|---|---|---|---|
top_k | 8 | 15 | Più chunks → più contesto per il LLM |
min_relevance | 0.0 | 0.4 | Filtra rumore prima del LLM (evita di sprecargli token su chunks irrilevanti) |
context_format | compact | llm_xml | Struttura ottimale per Anthropic/OpenAI tool use |
group_by_document | false | true | Unisce chunks consecutivi dello stesso doc → context più compatto |
Example — call diretto
curl -X POST https://bancadati.doczoom.ai/api/doczoom/retrieve \
-H "X-API-Key: $TAXHARVEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "patto di non concorrenza durata e corrispettivo",
"sources": ["normattiva", "cassazione"]
}'
Context output format = llm_xml (default)
Il campo context viene popolato in formato XML ottimizzato per Claude/GPT tool use:
<sources>
<source id="1">
<citation>Art. 2125 Codice Civile</citation>
<title>Codice Civile — Art. 2125 Patto di non concorrenza</title>
<url>https://www.normattiva.it/...</url>
<type>normattiva/articolo_codice</type>
<relevance>0.92</relevance>
<text>Il patto con il quale si limita lo svolgimento dell'attività del prestatore di lavoro, per il tempo successivo alla cessazione del contratto, è nullo se non risulta da atto scritto, se non è pattuito un corrispettivo a favore del prestatore di lavoro e se il vincolo non è contenuto entro determinati limiti di oggetto, di tempo e di luogo. La durata del vincolo non può essere superiore a cinque anni, se si tratta di dirigenti, e a tre anni negli altri casi. [...]</text>
</source>
<source id="2">
<citation>Cass. Civ. Sez. Lav. n. 17/2018</citation>
<title>Cassazione — Requisiti validità patto non concorrenza</title>
<url>https://www.italgiure.giustizia.it/...</url>
<type>cassazione/sentenza</type>
<relevance>0.85</relevance>
<text>Il corrispettivo del patto di non concorrenza deve essere determinato o determinabile e non meramente simbolico. [...]</text>
</source>
</sources>
Pattern Anthropic Claude — call diretto
# 1. Retrieve da TaxHarvest
chunks_resp = requests.post(
"https://bancadati.doczoom.ai/api/doczoom/retrieve",
headers={"X-API-Key": TAXHARVEST_KEY},
json={"query": user_question},
).json()
# 2. Costruisci system prompt per Claude
system_msg = f"""Sei un assistente legale italiano. Rispondi citando SOLO le fonti seguenti.
Usa il formato [^N] dove N è l'id della source.
{chunks_resp['context']}
REGOLE:
- Cita ogni claim con riferimento esatto
- NON inventare numeri di sentenze o articoli non presenti
- Se le fonti non bastano, dillo esplicitamente"""
# 3. Chiama il TUO LLM (Anthropic Claude, OpenAI GPT, ...)
from anthropic import Anthropic
client = Anthropic()
answer = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system=system_msg,
messages=[{"role": "user", "content": user_question}],
)
# 4. Componi response finale
return {
"answer": answer.content[0].text,
"sources": chunks_resp["sources"],
"chunks_used": chunks_resp["chunks"],
"confidence": chunks_resp["confidence_level"],
}
Risposta
Stesso schema di /query (DoczoomQueryResponse). Il valore di context
varia in base a context_format.
DocZoom Query BYOL · low-level
Retrieve-only endpoint ottimizzato per Bring Your Own LLM:
ricerca ibrida + reranking + filtering + ranking applicati, ma senza synthesis.
Il client riceve chunks ben filtrati e li passa al proprio LLM per generare la risposta.
Più veloce di /answer (~3–8s vs 15–25s).
- /answer — vuoi che TaxHarvest generi la risposta (chat semplice, mobile, integrazione plug-and-play). Pipeline 9-stage anti-allucinazione.
- /query — hai il tuo LLM/applicazione (DocZoom Word plugin, orchestratore custom, RAG su dati propri da combinare). Ricevi chunks pre-filtrati e li componi col tuo LLM. Massima flessibilità.
Cosa è già applicato sui chunks ritornati
- Hybrid search: vector HNSW + FTS italiano + entities + ontology
- Cross-encoder reranker: top 50 candidati → top 15 con scoring multilingue
- Junk filtering: rimossi chunks <80 char, firme digitali, numeri pagina, chunks con <30% caratteri alfabetici
- Title-aware boost: query con riferimenti normativi (es. "L. 392/1978 art. 27") boostano i chunks con quel numero/anno nel titolo (anti fake-match)
- Source hierarchy boost: Cass. SU > Cass. > Normattiva > AdE circolari
- Vigenza penalty: atti abrogati downgradati (−0.10)
- Dedup per URL + top-K cap
- Confidence layer:
high(top ≥ 0.7) /medium/low/no_results
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| query | string | required | Domanda dell'utente. |
| top_k | integer | optional | Default 8, range 1–30. Per BYOL consigliato 15–20. |
| sources | string[] | optional | Filtro per fonte (es. ["normattiva", "ade_circolari"]). |
| collections | string[] | optional | Raccolte tematiche L1 (es. ["diritto-civile"]) — alternativa a sources. |
| min_relevance | float | optional | Default 0.0. Filtra chunks sotto soglia. |
| use_hybrid | boolean | optional | Default true. Se false, solo vector search (più veloce ma meno preciso). |
| include_text | boolean | optional | Default true. Se false, ritorna solo metadata (utile per UI "fonti suggerite"). |
| context_format | string | optional | v25.75+ Formato del campo context: "compact" (default, stringa pre-formatted plain), "llm_xml" (XML strutturato ottimo per Anthropic/OpenAI), "markdown" (footnote refs [^1]). |
| group_by_document | boolean | optional | v25.75+ Default false. Se true, raggruppa chunks consecutivi dello stesso documento — riduce context size del ~40%. |
| country | string[] | optional | v25.89+ Filtro paese ISO-2 (default ["IT"] se omesso). Per chunks UAE (chunks_uae table, embedding Voyage-3-large 1024d) passare ["AE"] esplicitamente. Solo "IT" e "AE" supportati oggi; ogni altro valore → HTTP 400 unsupported_country. Il default IT non breaking change: tutti i client esistenti continuano a vedere solo corpus italiano. |
| modules | string[] | optional | v25.93+ Filtro per macro-area giuridica (es. ["diritto-civile"]). 10 moduli Lexroom-style: diritto-civile, diritto-tributario, diritto-penale, diritto-del-lavoro, diritto-amministrativo, diritto-societario, diritto-bancario, diritto-di-famiglia, privacy-data-protection, ip-proprieta-intellettuale. Restringe retrieval ai source + metadata del modulo. Compone in OR con sources/collections. Vedi GET /api/modules per dettagli. Module_id invalido → HTTP 400. |
TaxHarvest ora indicizza fonti legali UAE in tabella separata
chunks_uae con embedding Voyage-3-large 1024d
(legal-domain, qualità superiore a text-embedding-3-small su inglese giuridico).
Corpus finale (v25.92): 836 docs / 28K chunks · 6 sources cablate:
uae_cbuae (190 — Central Bank: AML/CFT, Federal Decree-Laws),
uae_fta (343 — FTA VAT/CT/Excise Public Clarifications),
uae_difc_legislation (144 — DIFC Arbitration / Companies / Contract / ecc.),
uae_adgm_courts (80 — ADGM CFI judgments OCR Tesseract),
uae_adgm_legislation (57 — ADGM Regulations + Abu Dhabi laws),
uae_difc (22 — DIFC Courts judgments).
Test live retrieval: top scores 0.74-0.80 (high confidence) su query ADGM judgments / DIFC arbitration law / FTA VAT clarifications.
Bloccate: uae_elaws (TCP timeout Hetzner —
serve Cloudflare Worker proxy .ae), uae_fsra
(upstream text vuoto).
Pipeline: Voyage embed query (≈400ms) → HNSW search su
chunks_uae → top-K. NO reranker, NO FTS italian, NO routing pratica IT
(UAE è pipeline isolata). Tempo p50 ≈ 500ms (vs 3-9s pipeline IT).
Example — BYOL flow completo
curl -X POST https://bancadati.doczoom.ai/api/doczoom/query \
-H "X-API-Key: $TAXHARVEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "ravvedimento operoso entro 90 giorni aliquota",
"top_k": 15,
"sources": ["normattiva", "ade_circolari"],
"min_relevance": 0.4
}'
Example — UAE corpus query (v25.89)
curl -X POST https://bancadati.doczoom.ai/api/doczoom/query \
-H "X-API-Key: $TAXHARVEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "anti-money laundering CBUAE suspicious transactions reporting",
"country": ["AE"],
"top_k": 5
}'
Response identica come schema (chunks + sources + confidence). Differenze:
timing_ms.country = "AE", timing_ms.embedding_model = "voyage-3-large",
chunk.source.source ∈ {"uae_cbuae", "uae_difc"}.
Niente meta-handler / niente factuality judge / niente reranker (pipeline UAE isolata).
Response schema
{
"query": "ravvedimento operoso entro 90 giorni aliquota",
"total_results": 15,
"confidence_level": "high",
"top_score": 0.87,
"needs_verification": false,
"timing_ms": { "hybrid": 1200, "rerank": 340, "total": 1850 },
"chunks": [
{
"text": "Art. 13 — Ravvedimento. 1. La sanzione è ridotta:\na) ad un decimo del minimo nei casi di mancato pagamento del tributo...",
"source": {
"title": "D.Lgs. 472/1997 — Art. 13 Ravvedimento",
"url": "https://www.normattiva.it/atto/caricaDettaglioAtto?atto.dataPubblicazioneGazzetta=1997-12-19&atto.codiceRedazionale=097G0509&art.idArticolo=13",
"source": "normattiva",
"doc_type": "decreto_legislativo",
"relevance_score": 0.87,
"doc_id": 12345,
"viewer_url": "https://bancadati.doczoom.ai/doc/12345"
},
"formal_citation": "Art. 13 D.Lgs. 472/1997",
"article_path": "art_13",
"authority": "Stato",
"validity": "vigente",
"document_date": "1997-12-18",
"category": "legislazione",
"is_ai_summary": false,
"chunk_index": 0,
"entities": [{"type": "norm", "value": "D.Lgs. 472/1997"}]
},
/* ... altri 14 chunks ordinati per relevance_score ... */
],
"sources": [
/* lista deduped delle source (chunks possono condividere stessa source) */
],
"entities_found": [
{ "type": "norm", "value": "D.Lgs. 472/1997", "count": 8 },
{ "type": "percentage", "value": "0.083%", "count": 3 }
],
"concepts_activated": [
{ "concept": "ravvedimento_operoso", "score": 0.92 }
],
"context": "[NORMATTIVA | decreto_legislativo] D.Lgs. 472/1997 — Art. 13 Ravvedimento\nFonte: https://www.normattiva.it/...\nRilevanza: 87%\n---\nArt. 13 — Ravvedimento. 1. La sanzione...\n\n===\n\n[ADE_CIRCOLARI | circolare] Circolare 27/E 2013...\n..."
}
BYOL pattern — sintesi col tuo LLM
Una volta ottenuti i chunks pre-filtrati, costruisci il system prompt del tuo LLM con
il campo context (già formattato). Esempio Python con qualsiasi provider:
# 1. Retrieve da TaxHarvest
resp = requests.post(
"https://bancadati.doczoom.ai/api/doczoom/query",
headers={"X-API-Key": API_KEY},
json={
"query": user_question,
"top_k": 15,
"min_relevance": 0.4, # filtra chunks deboli
},
).json()
if resp["confidence_level"] == "no_results":
return resp["no_results_message"] # "Non ho trovato fonti..."
# 2. Passa al tuo LLM con il context pre-formattato
system = f"""Sei un assistente legale. Rispondi SOLO usando le fonti seguenti.
Cita ogni claim con il riferimento normativo esatto.
FONTI (in ordine di rilevanza):
{resp['context']}"""
answer = your_llm.complete(system=system, user=user_question)
# 3. Componi response finale con citation tracking
return {
"answer": answer.text,
"sources": resp["sources"],
"confidence": resp["confidence_level"],
"chunks_used": resp["chunks"],
}
Decision matrix dettagliata
| Caso d'uso | Endpoint | Note |
|---|---|---|
| Plugin Word/Excel/PDF con documento allegato | /query | Combina chunks con testo allegato nel tuo LLM |
| App mobile chat semplice | /answer | Risposta plug-and-play con anti-allucinazione end-to-end |
| Orchestratore agent multi-step | /query | Componi step di reasoning con i chunks |
| UI con timeline ricerca/stage | /stream | SSE typed events per progress bar |
| Combinare con knowledge base proprietaria | /query | Merge chunks TaxHarvest + chunks tuoi nel tuo LLM |
| Domanda con riferimento normativo specifico | /articles | Fetch deterministico per art. esatto (bypass semantic search) |
DocZoom Stream (SSE)
Streaming Server-Sent Events della risposta LLM. Stessa logica di /answer
ma con eventi tipizzati per timeline UI Onyx-like.
Eventi SSE emessi
| Event | Data | Description |
|---|---|---|
| stage | {id, state, label, ms} | Stage del pipeline (retrieval, rerank, llm). State: start/done/skipped. |
| sources | {sources, chunks, confidence_level} | Sources e chunks dopo retrieval. |
| delta | {text} | Token incrementali del LLM (token-by-token). |
| meta | {timing_ms, llm_provider} | Metadati finali. |
| done | {finish_reason, truncated} | v25.8: finish_reason ∈ "stop" | "length" | "content_filter" | "error" (OpenAI-compatible). truncated: true sse finish_reason == "length" (max_output_tokens raggiunto). |
| error | {message} | Errore. |
Request body
Accetta lo stesso schema di /answer (vedi sezione DocZoom Answer). Tutti i field sotto sono supportati anche su /stream.
| Field | Type | Description |
|---|---|---|
| query | string | Domanda dell'utente. |
| top_k | integer | Numero chunks retrieval (default 10, range 1-25). Stesso schema di /answer. |
| sources | array<string> | Filtro fonti (es. ["normattiva","cassazione"]). |
| collections | array<string> | Slug collections L1 (es. ["diritto-civile","privacy-data-protection"]). |
| document_context | string | v25.2+ Testo opzionale di un documento allegato dall'utente (contratto, parere, circolare aziendale). Il LLM lo analizza usando la banca dati come authority retrieval. Max 100.000 caratteri (~25K token, sotto il context window del modello attivo). NON comprimere il documento dentro query: passa il testo intero qui e tieni query per la domanda del consulente ("è valido?", "rischi?", "compliance GDPR?"). |
| document_name | string | Nome file dell'allegato (es. "contratto_locazione.pdf"). Usato come label nel system prompt per dare contesto al LLM. Max 200 caratteri. |
| profile | string | Profilo professionale utente (es. "Avvocato Tributarista", "Notaio"). Attiva controlli verticali sul LLM judge. |
| materia | string | Materia (es. "IVA", "Lavoro", "Successioni"). |
| prefer_speed | boolean | Se true, salta re-prompt automatico in caso di ISSUE judge. Latency −15-25s; trade-off qualità. Default false. |
| max_output_tokens | integer | v25.70+ Override max token output LLM. Range 100-8192, default 4096. Per Q&A breve usa 1000; per analisi documento intero usa 4096; per redaction multi-clausola fino a 8192. |
Use case: Legal Chat con documento allegato
Il client (Plugin DocZoom Word / Legal Chat) ha l'utente che carica un contratto, una circolare aziendale, un parere — qualunque PDF/DOCX che deve essere analizzato contro la banca dati normativa.
Pattern corretto: estrai il testo del documento lato client e passalo come document_context, NON comprimerlo dentro la query. La banca dati TaxHarvest viene usata come source/authority retrieval, il LLM ragiona sul documento allegato con il diritto italiano come riferimento.
POST /api/doczoom/stream
{
"query": "Questa clausola di non concorrenza è valida secondo il diritto italiano?",
"document_context": "ART. 7 — PATTO DI NON CONCORRENZA\nIl Lavoratore si impegna, per la durata di 36 mesi dalla cessazione del rapporto di lavoro, a non svolgere attività concorrenziale presso aziende del settore alimentare in tutto il territorio della Repubblica Italiana. A titolo di corrispettivo, il Lavoratore percepirà la somma di € 5.000 una tantum alla cessazione del rapporto.\n\n[... resto del contratto ...]",
"document_name": "contratto_lavoro_mario_rossi.pdf",
"max_output_tokens": 2048,
"profile": "Avvocato Civilista",
"materia": "Lavoro"
}
Il LLM riceverà nel system prompt:
"L'utente ha allegato il documento 'contratto_lavoro_mario_rossi.pdf'..."
e nel context il testo del contratto + i 10 chunks più rilevanti dalla banca dati (art. 2125 c.c., Cass. 17/2018 sui requisiti, ecc.).
Example (browser, streaming consumption)
const resp = await fetch("/api/doczoom/stream", {
method: "POST",
headers: {"X-API-Key": KEY, "Content-Type": "application/json"},
body: JSON.stringify({
query: "È valido il patto di non concorrenza?",
document_context: contractText, // estratto lato client da .pdf/.docx
document_name: "contratto.pdf",
max_output_tokens: 2048,
}),
});
const reader = resp.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
// Parse SSE: event: delta\ndata: {"text": "L'art..."}
const chunk = decoder.decode(value);
console.log(chunk);
}
DocZoom Reference
Lookup di un riferimento normativo specifico (es. "art. 13 DPR 633/72"). Più preciso di /answer per citazioni dirette.
Request body
| Field | Type | Description |
|---|---|---|
| reference | string | Citazione libera. v25.28+ riconosce articolo specifico + codici brevi (c.c., c.p., c.p.c., c.p.p., TUIR, TUF, TUB, ecc.). |
| article | string | Numero articolo opzionale (es. "27", "2112-bis"). Estratto da reference se presente. |
| codice | string | Codice opzionale (mappato da abbrev → nome canonico). |
Example
curl -X POST https://bancadati.doczoom.ai/api/doczoom/reference \
-H "X-API-Key: $KEY" \
-d '{"reference": "L. 392/1978 art. 27"}'
# → "Equo Canone (L. 392/1978) - Art. 27" (1 risultato esatto)
curl -X POST https://bancadati.doczoom.ai/api/doczoom/reference \
-H "X-API-Key: $KEY" \
-d '{"reference": "art. 1384 c.c."}'
# → "Codice Civile - Art. 1384 - Riduzione della penale"
DocZoom Articles v25.30
Fetch deterministico di articoli specifici per una legge o un codice. Bypassa completamente il semantic search — ideale per audit di conformità su tipo di contratto noto, dove il client predefinisce una whitelist di articoli imperativi e li fetcha sempre.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| law | string | opzionale* | Legge speciale (es. "L. 392/1978", "DPR 633/1972", "D.Lgs. 81/2008"). |
| codice | string | opzionale* | Codice (es. "c.c.", "Codice Civile", "TUIR", "TUF"). |
| articles | (string|int)[] | required | Lista numeri articoli da fetchare (es. [27, 32, 34] o ["1384", "2112-bis"]). Min 1, max 50. |
| include_text | boolean | opzionale | Default true. Se false ritorna solo metadata (no testo articolo). |
* Almeno uno tra law e codice richiesto.
Response
{
"law": "L. 392/1978",
"codice": null,
"articles_requested": ["27", "32", "34", "36"],
"found_count": 4,
"missing_count": 0,
"articles": [
{
"article": "27",
"found": true,
"title": "Equo Canone (L. 392/1978) - Art. 27",
"url": "https://www.brocardi.it/legge-equo-canone/...",
"source": "normattiva",
"doc_type": "legge",
"citation": "art. 27 L. 392/1978",
"text": "La durata delle locazioni e sublocazioni di immobili urbani non può essere inferiore a sei anni..."
},
// ... altri articoli
]
}
Examples
# Locazione commerciale: 4 articoli imperativi della L. 392/1978
curl -X POST https://bancadati.doczoom.ai/api/doczoom/articles \
-H "X-API-Key: $KEY" \
-d '{"law": "L. 392/1978", "articles": [27, 32, 34, 36]}'
# Codice Civile: clausola penale + illecito + trasferimento azienda
curl -X POST https://bancadati.doczoom.ai/api/doczoom/articles \
-H "X-API-Key: $KEY" \
-d '{"codice": "c.c.", "articles": [1384, 2043, 2112]}'
# TUIR articoli (no testo, solo metadata)
curl -X POST https://bancadati.doczoom.ai/api/doczoom/articles \
-H "X-API-Key: $KEY" \
-d '{"codice": "TUIR", "articles": [54, 85], "include_text": false}'
Use case principale
Plugin DocZoom Word — audit di conformità contratti. Il Compliance Query Planner predefinisce una whitelist di articoli imperativi per ogni ContractType (es. locazione commerciale = L. 392/1978 art. 27/32/34/36 + art. 1384 c.c.) e fetcha sempre questi via /articles. Risolve il limit di /query sul ranking semantico delle leggi speciali.
Special norm aliases (v25.37)
Norme orizzontali NON ancora indicizzate art-by-art (es. GDPR Reg. UE 2016/679) ritornano una response strutturata invece di matchare per substring fuzzy. Esempio:
curl -X POST https://bancadati.doczoom.ai/api/doczoom/articles \
-H "X-API-Key: $KEY" \
-d '{"law": "GDPR", "articles": [6, 7]}'
# Response (no FP su Codice Protezione Civile):
{
"law": "Reg. UE 2016/679",
"found_count": 0,
"missing_count": 2,
"articles": [
{"article": "6", "found": false, "_not_indexed": true,
"_message": "Il Regolamento UE 2016/679 (GDPR) non è ancora indicizzato..."}
],
"_warning": "...usare Codice Privacy nazionale come proxy."
}
Aliases attualmente configurati: GDPR, Reg. UE 2016/679, Regolamento Generale Protezione Dati. Più verranno aggiunti man mano che si trovano gap di indicizzazione.
Garanzie
- Deterministico: stessa request → stesso output. No semantic ranking variability.
- Articoli mancanti ritornano
{found: false}invece di errore HTTP — il client può aggregare lo stato. - Performance: ~50-200ms per request (1 SQL query/articolo).
- Costo: $0 (no LLM, no embedding).
Compliance Contract Types v25.32
Lista dei tipi di contratto curati per il flow audit conformità. Sostituisce hardcoding lato plugin.
Response
{
"count": 7,
"contracts": [
{"type": "locazione-commerciale", "label": "Locazione commerciale (uso non abitativo)", "description": "..."},
{"type": "locazione-abitativa", "label": "Locazione abitativa", "description": "..."},
{"type": "lavoro-subordinato", "label": "Contratto di lavoro subordinato", "description": "..."},
{"type": "patto-non-concorrenza", "label": "Patto di non concorrenza", "description": "..."},
{"type": "nda-riservatezza", "label": "Accordo di riservatezza (NDA)", "description": "..."},
{"type": "compravendita-immobile", "label": "Compravendita immobiliare", "description": "..."},
{"type": "appalto-privato", "label": "Contratto di appalto privato", "description": "..."}
]
}
Example
curl https://bancadati.doczoom.ai/api/compliance/contracts \
-H "X-API-Key: $KEY"
Compliance Contract Detail v25.32 + v25.37
Whitelist imperative_norms (specifiche del tipo contratto) + tipiche_violazioni (checklist) + horizontal_norms (norme cross-cutting che si applicano sempre — GDPR, Codice Consumo, ecc.). Pensato per il flow Conformità del plugin DocZoom Word: il client lo chiama dopo che l'utente ha selezionato il tipo contratto, e ottiene tutti i riferimenti legali da prependere al normativeContext.
Path params
| Field | Description |
|---|---|
| contract_type | Chiave del tipo contratto (es. locazione-commerciale). Vedi /api/compliance/contracts per la lista. |
Query params
| Field | Type | Default | Description |
|---|---|---|---|
| fetch_text | boolean | false | Se true, fetcha il testo completo degli articoli imperativi (chiamata interna a /articles con cache 24h). Latency ~200-500ms. |
Response
{
"type": "locazione-commerciale",
"label": "Locazione commerciale (uso non abitativo)",
"description": "Contratto di locazione di immobile urbano adibito ad uso diverso...",
"imperative_norms": [
{"law": "L. 392/1978", "articles": [27, 32, 34, 36, 37, 38, 39, 40, 41, 42],
"tema": "Disciplina locazioni uso diverso: durata, ISTAT, indennità avviamento..."},
{"codice": "c.c.", "articles": [1384, 1385, 1571, 1573, 1575],
"tema": "Clausola penale, caparra, nozione locazione, obblighi locatore"}
],
"tipiche_violazioni": [
"Durata < 6 anni (L. 392 art. 27)",
"Aggiornamento ISTAT > 75% indice (L. 392 art. 32)",
"Limitazione/condizionamento del diritto di recesso del conduttore per gravi motivi (L. 392 art. 27 c. 8 — il diritto è inderogabile)",
"Mancanza informativa privacy / trattamento dati conduttore (GDPR / D.Lgs. 196/2003)",
...
],
"horizontal_norms": [ // v25.37 — norme cross-cutting che si applicano a questo tipo
{
"key": "gdpr",
"label": "Privacy / Trattamento dati personali (GDPR)",
"law": "Reg. UE 2016/679",
"fallback_codice": "Codice della Privacy",
"articles": [6, 7, 13, 14, 15, 17, 22, 28, 32, 35, 44],
"tema": "Basi legali, consenso, informativa, diritti interessato...",
"indicizzato": false,
"fallback_indicizzato": true,
"warning": "GDPR non indicizzato art-by-art; usare Codice Privacy come proxy"
}
],
"articles": [...] // se fetch_text=true: imperative + horizontal aggregati con field `category` (imperative|horizontal)
}
Examples
# Lista whitelist (lightweight, no testo articoli)
curl https://bancadati.doczoom.ai/api/compliance/contracts/locazione-commerciale \
-H "X-API-Key: $KEY"
# Con full articles (testo completo)
curl "https://bancadati.doczoom.ai/api/compliance/contracts/locazione-commerciale?fetch_text=true" \
-H "X-API-Key: $KEY"
Audit Trending v25.34
Metriche daily aggregate per detection automatica regressioni qualità (hallu rate, judge rate, re-prompt, latency p50/p95). Auto-alert se metrica oggi differisce significativamente dalla media 7 giorni precedenti.
Query params
| Field | Type | Default | Description |
|---|---|---|---|
| days | int | 14 | Numero giorni da retrievare. |
Response
{
"days": 14,
"trending": [
{
"day": "2026-05-03",
"total_queries": 846,
"hallu_caught_pct": 2.0,
"judge_issue_pct": 24.7,
"reprompt_pct": 19.5,
"tier2_override_pct": 1.2,
"abstain_pct": 0.0,
"latency_avg_ms": 38542,
"latency_p50_ms": 25103,
"latency_p95_ms": 97104
},
...
],
"alerts": [
{
"metric": "latency_p95_ms",
"today": 97104,
"avg_prev_7d": 36748,
"severity": "warning"
}
],
"summary": {
"total_calls": 3040,
"avg_hallu_caught_pct": 2.44,
"avg_p95_ms": 54834
}
}
DocZoom Tool
Strumenti real-time (VIES check, ricerca articoli, ecc.). Vedi /api/doczoom/capabilities per la lista completa.
Request body
| Field | Type | Description |
|---|---|---|
| tool | string | Nome tool (vies_check, article_lookup, etc.). |
| params | object | Parametri specifici del tool. |
DocZoom Capabilities
Lista delle capabilities/tools disponibili.
Chat
Chat con context multi-turn. Mantiene history per follow-up domande.
Request
| Field | Type | Description |
|---|---|---|
| message | string | Messaggio utente (max 10000 char). |
| history | object[] | Storia conversazione (lista {role, content}). |
Search (basic)
Endpoint di ricerca legacy. Per nuove integrazioni preferisci /api/doczoom/query.
Sources
Lista delle 61 fonti IT dati disponibili (+ 6 UAE), scrapate automaticamente da scheduler interno. Backend di acquisizione: 3-tier (HTTP proxy interno, Browser rendering, direct fetch).
Inventario completo (counts 13 mag 2026)
Giurisprudenza (610K+ documenti)
| Source | Docs | Descrizione | Backend |
|---|---|---|---|
cassazione | 335.188 | Sentenze civili + penali + costituzionali Corte di Cassazione (1996-oggi) | Solr ItalGiure (direct + cortedicassazione.it) |
giustizia_amministrativa | 267.795 | TAR 30 sedi + Consiglio di Stato + CGA Sicilia (2020-oggi, backfill in corso) | Playwright Liferay portlet form |
corte_costituzionale | 3.808 | Sentenze + ordinanze Corte Costituzionale | Playwright cortecostituzionale.it |
curia_cgue | 1.410 | Comunicati stampa CGUE Curia Lussemburgo (IT) | proxy interno curia.europa.eu |
giustizia_tributaria_massimario | 1.069 | Massime tributarie Cassazione | Scraping ufficio massimario |
hudoc_cedu | 9 | Sentenze landmark CEDU v. Italia (Cestaro, Torreggiani, Provenzano, ecc.) | HUDOC PDF endpoint |
corte_dei_conti | 1 | SPA banchedati.corteconti.it (limitato, richiede session dedicata) | — |
giustizia_tributaria | 3 | Limitato (Akamai+QueueIT block) | — |
Normativa italiana (15K+ articoli)
| Source | Docs | Descrizione |
|---|---|---|
normattiva | 14.963 | 65 codici art-by-art: CC, CP, CPC, CPP, Costituzione, TUIR, TUB, TUF, Cod. Crisi Impresa, Cod. Privacy, Nuovo Cod. Appalti, Statuto Lavoratori, Negoziazione Assistita, ecc. |
gazzetta_ufficiale | 2.837 | Atti GU serie generale (RSS daily + backfill) |
Normativa UE (1.8K+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
eur_lex | 1.747 | 38 atti UE art-by-art: GDPR, AI Act, NIS 1+2, DORA, DSA, DMA, MiCAR, PSD2, MAR, eIDAS 1+2, Data Act, DGA, CRA, CER, ENISA, ePrivacy, AMLD 4-6, Reg. AML 2024, ATAD, DAC 1+7, Mifid II, Direttiva OPA, Reg. Prospetto, Direttiva Trasparenza, Whistleblowing + 15 decisioni adeguatezza GDPR |
eurlex | 76 | Dataset EUR-Lex legacy (pre-v25.43) |
Prassi fiscale (7.4K+ documenti AdE)
| Source | Docs | Descrizione |
|---|---|---|
ade_interpelli | 3.237 | Risposte interpello AdE |
ade_risoluzioni | 2.972 | Risoluzioni AdE (2006-oggi) |
ade_circolari | 781 | Circolari AdE interpretative |
ade_provvedimenti | 139 | Provvedimenti del Direttore AdE |
ade_guide | 104 | Guide pratiche AdE (Forfettario, Cedolare, Superbonus, ecc.) |
ade_modelli | 11 | Modelli dichiarativi + istruzioni |
agenzia_entrate_news | 28 | News + comunicati stampa AdE |
mef_convenzioni_doppia_imposizione | 73 | Convenzioni internazionali bilaterali contro doppie imposizioni |
mef_finanze | 25 | Comunicati MEF |
agenzia_dogane | 2 | Circolari ADM dogane/accise |
Previdenza & Lavoro (8.2K+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
cnel_ccnl | 6.762 | Contratti Collettivi Nazionali (CCNL settoriali archivio CNEL) |
inps_messaggi | 821 | Messaggi INPS operativi |
inps_circolari | 595 | Circolari INPS |
ministero_lavoro | 5 | Min. Lavoro atti/circolari |
ispettorato_lavoro | 1 | INL note ispezioni |
Authority indipendenti IT (1.9K+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
agcm_bollettini | 808 | Bollettini settimanali AGCM antitrust (2010-2026 backfill, intese/concentrazioni/abusi) |
agcom | 537 | Delibere AGCOM autorità comunicazioni |
abf | 280 | Decisioni ABF Arbitro Bancario Finanziario |
uif | 87 | UIF Banca d'Italia — Quaderni antiriciclaggio + Avvisi |
agid | 80 | AgID — Linee guida PA digitale + notizie + circolari |
anac | 67 | ANAC — atti, comunicati, notizie autorità anticorruzione |
adm | 45 | ADM — Circolari, determinazioni, risoluzioni dogane (Liferay PDF) |
banca_italia | 35 | Disposizioni vigilanza Banca d'Italia + BCE rates daily |
ivass | 33 | IVASS — Regolamenti + bollettini vigilanza assicurazioni |
arera | 9 | ARERA — Delibere autorità energia, reti, ambiente |
consob | 4 | News Consob (SPA limitato) |
Ministeri & Enti pubblici IT (270+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
mlps | 77 | Ministero del Lavoro — Notizie + comunicati istituzionali |
inail | 65 | INAIL — Pubblicazioni + scadenze + avvisi |
ministero_lavoro | 5 | Min. Lavoro atti/circolari (legacy) |
ispettorato_lavoro | 1 | INL note ispezioni |
Authority UE (440+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
eba | 200 | EBA — Guidelines + RTS + ITS + Opinions banking (PDF diretti) |
eiopa | 92 | EIOPA — Publications + Solvency II rulebook insurance/pensions |
esma | 87 | ESMA — Press releases + publications + databases securities markets |
amla | 21 | AMLA — Anti-Money Laundering Authority (agenzia UE 2024) |
Standard-setter internazionali (65+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
iasb | 42 | IASB — IFRS / IAS Standards internazionali (testi master) |
fsb | 16 | FSB — Financial Stability Board publications globali |
bis_bcbs | 7 | BIS BCBS — Basel Committee banking standards |
Privacy & GDPR (440+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
wp29 | 226 | WP29 Article 29 Working Party archive (legacy pre-EDPB) |
edpb | 115 | EDPB European Data Protection Board (linee guida + opinion) |
garante_privacy | 62 | Provvedimenti Garante Privacy IT |
Internazionale & specialistiche (270+ documenti)
| Source | Docs | Descrizione |
|---|---|---|
borsa_italiana | 263 | Regolamenti + avvisi storici Borsa Italiana (16 sezioni) |
cnf_deontologico | 75 | Codice Deontologico Forense (CNF 2014) |
un_treaties | 51 | Convenzione ONU Diritti del Fanciullo (51 art.) |
oic_principi_contabili | 48 | Principi contabili nazionali OIC 8-32 |
oic | 42 | OIC legacy (eventi/categorie homepage) |
uibm | 41 | Circolari + decreti UIBM proprietà industriale |
fnc_commercialisti | 25 | FNC Fondazione Nazionale Commercialisti documenti |
hcch_treaties | 2 | Convenzioni Aja 1980 + 1996 (sottrazione/protezione minori) |
istat | 2 | ISTAT comunicati rilevanti |
epo_boards_appeal | 1 | EPO Boards of Appeal Case Law 2025 (1988 pp, 3259 chunks full text) |
wipo_treaties | 1 | TRIPS Agreement (WTO 1994) |
council_europe | 1 | CEDU testo italiano (Convenzione Europea Diritti dell'Uomo) |
Response example
{
"sources": [
{"name": "cassazione", "count": 335188},
{"name": "giustizia_amministrativa", "count": 267795},
{"name": "normattiva", "count": 14963},
{"name": "cnel_ccnl", "count": 6762},
/* ... totale 61 fonti IT (+ 6 UAE), vedi tabella sopra */
]
}
Modules (macro-area + profilo) v25.93+25.103 · LEXROOM-STYLE
18 moduli totali: 10 IT macro-area giuridica (Civile,
Tributario, Penale, ecc.) + 3 IT per profilo professionale
(v25.103: commercialista, tributarista, consulente-lavoro) + 5 UAE. Permettono
a DocZoom di filtrare il retrieval senza enumerare manualmente le 67 sources.
Per profili più granulari (es. commercialista-iva) usa le 66
collections L1-L3.
Lista i 18 moduli disponibili con id, name, icon, description, filter_count e sources coperte.
Response schema
{
"modules": [
{
"id": "diritto-civile",
"name": "Diritto Civile",
"icon": "⚖️",
"short": "Civile",
"description": "Codice Civile, CPC, Cassazione civile...",
"filter_count": 6,
"sources": ["cassazione", "corte_costituzionale", ...]
},
/* ... 10 moduli totali */
],
"count": 18,
"usage_hint": "Passa modules=['diritto-civile'] o ['commercialista'] a POST /api/doczoom/query"
}
Query params
| Field | Type | Required | Description |
|---|---|---|---|
| country | string | optional | v25.94+ Filtro paese ISO-2: IT | AE | all (default all). Es. ?country=AE → solo i 5 moduli UAE. |
🇮🇹 Moduli IT per materia giuridica (10, Lexroom-style)
| ID | Nome | Macro-area |
|---|---|---|
| diritto-civile | Diritto Civile | CC, CPC, Cass. civile, Cod. Consumo, Crisi Impresa, CGUE, CNF |
| diritto-tributario | Diritto Tributario | TUIR, IVA, Statuto Contribuente, AdE, Cass. tributario, CGUE |
| diritto-penale | Diritto Penale | CP, CPP, D.Lgs. 74/2000, Cass. penale |
| diritto-del-lavoro | Diritto del Lavoro | Statuto Lavoratori, INPS, INAIL, CCNL, Cass. lavoro |
| diritto-amministrativo | Diritto Amministrativo | Cod. Appalti, TAR, CdS, AGCM, AGCOM, ANAC, Corte dei Conti |
| diritto-societario | Diritto Societario | CC libro V, TUF, Consob, ESMA, Borsa IT, OIC |
| diritto-bancario | Diritto Bancario e Finanziario | TUB, TUF, ABF, Banca d'Italia, EBA, BCBS |
| diritto-di-famiglia | Diritto di Famiglia | CC famiglia, CEDU, Convenzione Aja, Cass. famiglia |
| privacy-data-protection | Privacy e Data Protection | GDPR, Cod. Privacy, Garante, EDPB, WP29, CEDU privacy |
| ip-proprieta-intellettuale | IP — Proprietà Intellettuale | Cod. PI, WIPO, EPO, UIBM, CGUE IP |
👔 Moduli IT per profilo professionale (3, v25.103)
Macro-moduli che aggregano fonti di più materie secondo le esigenze tipiche del professionista. Per granularità maggiore (sub-tematiche L2/L3) vedi le 66 collections.
| ID | Nome | Coverage |
|---|---|---|
| commercialista | Commercialista | Fiscale (IVA+IRPEF+IRES+IRAP+dichiarazioni) + bilancio (OIC/IFRS) + societario + crisi impresa + lavoro consulenza. 27 filters, 5 macro_area cassazione. |
| tributarista | Avvocato Tributarista | Contenzioso tributario (CTP/CTR + Cass. trib.) + penale tributario (D.Lgs. 74/2000) + procedure deflattive + riscossione. Più focused su contenzioso vs commercialista. |
| consulente-lavoro | Consulente del Lavoro | Contratti (a termine, apprendistato, somministrazione, smart working) + licenziamenti + CCNL + sicurezza (D.Lgs. 81/2008) + INPS/INAIL + immigrazione. |
🇦🇪 Moduli UAE disponibili (country=AE)
| ID | Nome | Coverage |
|---|---|---|
| uae-tax | UAE Tax | FTA Public Clarifications: VAT 5%, Corporate Tax 9%, Excise (343 docs) |
| uae-banking-amlcft | UAE Banking & AML/CFT | Central Bank UAE: AML/CFT, Federal Decree-Laws, licensing financial institutions (190 docs) |
| uae-difc | UAE — DIFC (Dubai) | DIFC Courts judgments + DIFC Laws (Arbitration, Companies, Contract, ecc.) — 166 docs |
| uae-adgm | UAE — ADGM (Abu Dhabi) | ADGM Courts CFI judgments (OCR) + ADGM Regulations — 137 docs |
| uae-common-law | UAE Common Law (DIFC + ADGM) | Cross-cut sui 2 financial centres common-law UAE (303 docs) |
⚠️ Cross-country validation: i moduli UAE richiedono
country=["AE"]; i moduli IT richiedono country=["IT"]
(o default). Mismatch → HTTP 400 module_country_mismatch.
Esempio cURL
curl https://bancadati.doczoom.ai/api/modules \
-H "X-API-Key: $TAXHARVEST_API_KEY"
Module Detail (live counts)
Dettaglio di un singolo modulo + count documenti per source (live).
Path params
| Field | Type | Description |
|---|---|---|
| module_id | string | ID modulo (es. diritto-tributario). Vedi GET /api/modules per la lista. |
Response schema
{
"id": "diritto-tributario",
"name": "Diritto Tributario",
"icon": "💶",
"short": "Tributario",
"description": "Normativa tributaria nazionale + UE...",
"filters": [
{"source": "cassazione", "metadata": {"macro_area": ["tributario"]}},
{"source": "normattiva", "metadata": {"codice": ["TUIR..."]}},
/* ... 17 filtri totali */
],
"sources": ["cassazione", "ade_circolari", "ade_interpelli", ...],
"doc_counts": {
"cassazione": 71101,
"corte_costituzionale": 3808,
"ade_interpelli": 3237,
/* ... per ogni source */
},
"total_docs": 85304
}
Usage in retrieval
Passa modules in POST /api/doczoom/query per filtrare i chunks ai soli source/metadata del modulo:
curl -X POST https://bancadati.doczoom.ai/api/doczoom/query \
-H "X-API-Key: $TAXHARVEST_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"query": "ravvedimento operoso entro 90 giorni",
"modules": ["diritto-tributario"],
"top_k": 10
}'
Note: i moduli compongono in OR con sources e collections
(più permissive). Un module_id non valido → HTTP 400 unknown_module.
Quando country=["AE"], i moduli vengono ignorati (UAE pipeline isolata).
Source Categories
Macro-categorie per una fonte specifica (es. Normattiva → CC, CP, TUIR, ...).
Response (v25.8+)
Per normattiva, ogni categoria contiene un slug stable usabile come parametro filtro:
{
"source": "normattiva",
"categories": [
{"name": "Codice Civile", "slug": "cc", "count": 3029},
{"name": "TUIR - Testo Unico Imposte sui Redditi", "slug": "tuir", "count": 236},
/* ... vedi tabella 65 codici sotto */
]
}
65 codici Normattiva disponibili (count 13 mag 2026)
Codici fondamentali
| Slug | Nome | Articoli |
|---|---|---|
cc | Codice Civile | 3.029 |
cpc | Codice di Procedura Civile | 1.139 |
cp | Codice Penale | 864 |
cpp | Codice di Procedura Penale | 803 |
cost | Costituzione | 140 |
preleggi | Preleggi (Disposizioni sulla Legge in Generale) | 31 |
disp_att_cc | Disposizioni Attuazione Codice Civile | 312 |
disp_att_cpp | Disposizioni di attuazione Cod. Proc. Penale | 323 |
cpp_minori | Codice di Procedura Penale Minorile (DPR 448/1988) | 47 |
Tributario
| Slug | Nome | Articoli |
|---|---|---|
tuir | TUIR - Testo Unico Imposte sui Redditi | 236 |
iva | Decreto IVA (DPR 633/1972) | 171 |
dpr600 | Accertamento Imposte sui Redditi (DPR 600/1973) | 107 |
tur | Testo Unico Imposta di Registro (DPR 131/1986) | 83 |
statuto_contribuente | Statuto del Contribuente (L. 212/2000) | 37 |
reati_tributari | Legge sui Reati Tributari (D.Lgs. 74/2000) | 34 |
cpt | Codice del Processo Tributario (D.Lgs. 546/1992) | 94 |
tusd | Testo Unico Successioni e Donazioni (D.Lgs. 346/1990) | 66 |
irap | Riordino Finanza Enti Territoriali / IRAP (D.Lgs. 446/1997) | 50 |
Bancario, finanziario, assicurazioni
| Slug | Nome | Articoli |
|---|---|---|
tuf | TUF - Testo Unico Intermediazione Finanziaria | 514 |
tub | TUB - Testo Unico Bancario | 363 |
cap | Codice delle Assicurazioni Private (D.Lgs. 209/2005) | 611 |
Lavoro
| Slug | Nome | Articoli |
|---|---|---|
tusl | Testo Unico Sicurezza Lavoro (D.Lgs. 81/2008) | 321 |
jobs_act | Jobs Act - Disciplina Organica Contratti (D.Lgs. 81/2015) | 66 |
statuto_lavoratori | Statuto dei Lavoratori (L. 300/1970) | 41 |
tupi | Testo Unico Pubblico Impiego (D.Lgs. 165/2001) | 104 |
pari_opp | Codice delle Pari Opportunità (D.Lgs. 198/2006) | 72 |
l104 | Legge 104 - Disabilità (L. 104/1992) | 48 |
Amministrativo, appalti, edilizia
| Slug | Nome | Articoli |
|---|---|---|
cpa | Codice del Processo Amministrativo | 139 |
appalti | Nuovo Codice Appalti (D.Lgs. 36/2023) | 233 |
appalti_vecchio | Codice dei Contratti Pubblici (legacy) | 222 |
tue | Testo Unico Edilizia | 151 |
tuel | Testo Unico Enti Locali (D.Lgs. 267/2000) | 291 |
espropriazioni | Testo Unico Espropriazioni (DPR 327/2001) | 70 |
cgcc | Codice di Giustizia Contabile (D.Lgs. 174/2016) | 221 |
l241 | Legge sul Procedimento Amministrativo (L. 241/1990) | 51 |
cad | Codice dell'Amministrazione Digitale (D.Lgs. 82/2005) | 123 |
antimafia | Codice Antimafia (D.Lgs. 159/2011) | 136 |
protezione_civile | Codice della Protezione Civile (D.Lgs. 1/2018) | 51 |
Penale specialistico
| Slug | Nome | Articoli |
|---|---|---|
ord_pen | Ordinamento Penitenziario (L. 354/1975) | 137 |
stupefacenti | Testo Unico Stupefacenti (DPR 309/1990) | 142 |
Civile specialistico
| Slug | Nome | Articoli |
|---|---|---|
codice_consumo | Codice del Consumo (D.Lgs. 206/2005) | 241 |
privacy | Codice della Privacy | 221 |
ambiente | Codice dell'Ambiente (D.Lgs. 152/2006) | 443 |
cpi | Codice della Proprietà Industriale (D.Lgs. 30/2005) | 291 |
beni_culturali | Codice dei Beni Culturali e del Paesaggio (D.Lgs. 42/2004) | 192 |
strada | Codice della Strada (D.Lgs. 285/1992) | 266 |
cce | Codice delle Comunicazioni Elettroniche (D.Lgs. 259/2003) | 267 |
terzo_settore | Codice del Terzo Settore (D.Lgs. 117/2017) | 105 |
cdt | Codice del Turismo (D.Lgs. 79/2011) | 77 |
cdnd | Codice della Nautica da Diporto (D.Lgs. 171/2005) | 94 |
mediazione | Mediazione Civile e Commerciale (D.Lgs. 28/2010) | 44 |
negoziazione_assistita | Negoziazione Assistita (DL 132/2014 conv. L. 162/2014) | 37 |
Crisi d'impresa, immobiliare, famiglia, immigrazione
| Slug | Nome | Articoli |
|---|---|---|
ccii | Codice della Crisi d'Impresa e dell'Insolvenza | 411 |
lf | Legge Fallimentare (RD 267/1942) | 301 |
locazioni | Disciplina Locazioni Abitative (L. 431/1998) | 16 |
equo_canone | Equo Canone (L. 392/1978) | 85 |
ldiv | Legge sul Divorzio (L. 898/1970) | 16 |
immigrazione | Testo Unico Immigrazione (D.Lgs. 286/1998) | 77 |
Altro
| Slug | Nome | Articoli |
|---|---|---|
altri | Atti normativi vari (non codificati) | — |
I client possono usare sia lo slug (es. cc) sia il nome canonico
(es. "Codice Civile") come parametro category. La response include
resolved_category per breadcrumb UI.
Source Documents
Query params
| Param | Type | Description |
|---|---|---|
| category | string | Filtro categoria. Per normattiva, accetta slug (es. cc, tuir) oppure nome canonico (es. "Codice Civile") — alias trasparente. Slug altri raggruppa atti non codificati. |
| limit | integer | Default 50, max 200. |
| offset | integer | Paginazione. |
Response field (v25.8)
resolved_category espone il nome canonico matchato (utile per breadcrumb UI quando il client passa uno slug).
Examples
# Slug stable
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/source/normattiva/documents?category=cc&limit=10"
# Equivalente con nome esteso
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/source/normattiva/documents?category=Codice%20Civile"
# Atti non codificati (decreto_legislativo, legge, dpr, decreto_legge, ...)
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/source/normattiva/documents?category=altri"
Document Full (con testo)
Nuovo in v25.8.2: ritorna metadati documento + chunks + full_text.
Usato dal frontend DocZoom (Codici Navigator) per renderizzare il testo dell'articolo
cliccato. /source/.../documents ritorna solo metadata; questo endpoint
fornisce il testo completo.
Path params
| Param | Type | Description |
|---|---|---|
| id | integer | Document ID (es. ottenuto da /source/normattiva/documents). |
Response
{
"id": 211124,
"source": "normattiva",
"doc_type": "altro",
"title": "Codice di Procedura Penale - Art. 1 - Giurisdizione penale",
"url": "https://it.wikisource.org/wiki/Codice_di_procedura_penale#Art._1",
"unique_id": "normattiva::https://it.wikisource.org/...",
"published_date": "1988-09-22",
"metadata": {"codice": "Codice di Procedura Penale", "articolo": "1", /* ... */},
"chunks": [
{
"id": 1715309,
"chunk_index": 0,
"total_chunks": 1,
"text": "1. La giurisdizione penale è esercitata dai giudici previsti...",
"metadata": {"source_summary": "wikisource_verbatim"}
}
],
"chunks_count": 1,
"full_text": "1. La giurisdizione penale è esercitata dai giudici..."
}
Examples
# Ottieni full text di un articolo CC
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/document/211124"
# Pattern frontend: lista → click → fetch full text
const list = await fetch('/api/source/normattiva/documents?category=cc');
const docId = list.documents[0].id;
const full = await fetch(`/api/document/${docId}`);
console.log(full.full_text); // rendering immediato
Recent Documents
Ultimi documenti importati (cronologia harvest).
Query params
| Param | Type | Description |
|---|---|---|
| limit | integer | Default 20. |
Stats
Statistiche aggregate del database (IT + UAE corpus). I numeri sono live al momento della chiamata.
{
"total_documents": 648931,
"total_chunks": 3920561,
"total_entities": 637000,
"chunks_uae": 28379,
"sources": {/* breakdown per source — 67 fonti totali */},
"last_harvest": "2026-05-20T05:30:00"
}
Per stats per-modulo: GET /api/modules/{id} (con counts live).
Per stats per-source: GET /api/sources.
Articles
Lookup diretto di un articolo per numero (es. /api/articles/2473 per art. 2473 CC).
Countries v25.96
Lista paesi supportati dal corpus con stats. Usato da DocZoom Settings per popolare il selettore Country.
Response example
{
"countries": [
{"code": "IT", "name": "Italia", "docs": 648095, "sources": 61, "modules": 10},
{"code": "AE", "name": "United Arab Emirates", "docs": 836, "sources": 6, "modules": 5}
]
}
Legal Codes (DocZoom-compatible) v25.98
Lista dei 65 codici Normattiva indicizzati article-by-article, con slug DocZoom-compatible (allineati 1:1 a CODES_CATALOG di doczoom-studio v25.100). Drop-in replacement per la pagina codici DZ.
Response shape
{
"codes": [
{
"slug": "codice-civile",
"name": "Codice Civile",
"short": "CC",
"articles_count": 3029,
"chunks_count": 3230,
"category": "civile",
"description": "Codice civile italiano (R.D. 262/1942)..."
},
/* ... 64 più ... */
],
"total": 65
}
Slug allineati (esempi)
Tutti gli slug sono kebab-case deterministici, 1:1 con DZ CODES_CATALOG. Esempi:
codice-civile, cpc, cp, cpp, tuir, tub, tuf, preleggi, jobs_act, tu_espropriazioni, cod_pari_opportunita, tu_immigrazione, cod_antimafia, statuto_lavoratori, codice_appalti (D.Lgs. 36/2023), codice_consumo, ecc.
Example
curl -H "X-API-Key: $KEY" https://bancadati.doczoom.ai/api/legal-codes
Legal Judgments (DocZoom-compatible) v25.98
Lista delle fonti giurisprudenziali con conteggi live. Drop-in per la pagina giurisprudenza DZ.
Query params
| Field | Type | Description |
|---|---|---|
| authority | string | Filtro opzionale: cassazione, cds, tar, corte_costituzionale, cgue, cedu, abf, ecc. |
| year_from | integer | Filtro anno minimo (es. 2020) |
| limit | integer | Default 50, max 500 |
Response shape
{
"authorities": [
{"slug": "cassazione", "name": "Corte di Cassazione", "docs": 336818, "subtypes": ["civile", "penale", "costituzionale"]},
{"slug": "giustizia_amministrativa", "name": "Giustizia Amministrativa", "docs": 269254, "subtypes": ["tar", "cds", "cga"]}
]
}
Reference Lookup
Lookup di un riferimento normativo o giurisprudenziale già normalizzato (es. art-2473-cc, cass-civ-12345-2023, dlgs-74-2000-art-2). Ritorna il documento + chunks principali.
Example
curl -H "X-API-Key: $KEY" \
https://bancadati.doczoom.ai/api/reference/art-2473-cc
Response shape
{
"reference": "art-2473-cc",
"document": {"id": 12345, "title": "Art. 2473 c.c. – Recesso del socio", "source": "normattiva"},
"chunks": [/* top chunks */]
}
Reference History
Cronologia delle versioni di un riferimento normativo (modifiche, abrogazioni, sostituzioni). Utile per verificare la vigenza di una norma a una data.
Example
curl -H "X-API-Key: $KEY" \
https://bancadati.doczoom.ai/api/reference/art-18-statuto-lavoratori/history
Reference Cited-By
Lista di documenti (sentenze, circolari, dottrina) che citano il riferimento. Costruito dal knowledge graph delle cross-reference estratte dai chunks.
Example
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/reference/art-2473-cc/cited-by?limit=20"
Collections — list
Lista delle 66 collections professionali (profili commercialista, tributarista, avvocato civilista, notaio, consulente del lavoro + materie). 21 L1, 27 L2, 18 L3 (v25.101: aggiunte 7 sub-commercialista + 4 sub-tributarista). Cf. taxharvest/collections.yaml.
Profili professionali L1 esposti (7)
| Slug | Nome | L2/L3 figli |
|---|---|---|
commercialista | Commercialista | 12 (5 L2 + 7 L3) |
avvocato-tributarista | Avvocato Tributarista | 4 L3 |
avvocato-civilista | Avvocato Civilista | L2 |
avvocato-penalista | Avvocato Penalista | L2 |
avvocato-amministrativista | Avvocato Amministrativista | L2 |
consulente-lavoro | Consulente del Lavoro | L2 |
notaio | Notaio | L2 |
Sub-collections commercialista (esempio gerarchia)
L1 commercialista
├── L2 commercialista-fiscale
│ ├── L3 commercialista-dichiarazioni // v25.101
│ ├── L3 commercialista-contenzioso-tributario // v25.101
│ ├── L3 commercialista-ravvedimento-sanzioni // v25.101
│ ├── L3 commercialista-internazionale // v25.101
│ ├── L3 commercialista-cripto-assets // v25.101
│ └── L3 commercialista-startup-pmi // v25.101
├── L2 commercialista-contabile-bilancio
│ └── L3 commercialista-bilanci-revisione // v25.101
├── L2 commercialista-societario
├── L2 commercialista-crisi-impresa
└── L2 commercialista-lavoro
Response shape
{
"collections": [
{
"slug": "commercialista-fiscale",
"name": "Commercialista — Fiscale",
"level": "L1",
"parent": null,
"sources": ["ade_circolari", "ade_interpelli", "normattiva", "cassazione"],
"docs_estimate": 340000
}
/* ... */
]
}
Collections — tree
Struttura gerarchica L1 → L2 → L3 delle collections, pronta per il widget tree-view di DocZoom Studio.
Collections — detail
Dettaglio di una singola collection: descrizione, sources, normattiva_codici, cassazione_macro_aree, parent/children, doc_count live.
Example
curl -H "X-API-Key: $KEY" \
https://bancadati.doczoom.ai/api/collections/commercialista-iva
Collections — documents
Documenti appartenenti a una collection. Supporta paginazione (?limit=50&offset=0) e filtri (?source=ade_circolari&year=2026).
Norm Alerts v25.101 · NEW
Sistema di notifiche per cambiamenti normativi. L'utente registra "subscription" (per source, modulo, collection, keyword,
reference o country) e l'API genera "events" quando nuovi documenti matchano i criteri. Architettura
scan-on-poll: alla GET /api/alerts scan automatico dei documenti creati dopo l'ultima poll
della subscription. Idempotente. UI built-in su /alerts.
Lista degli eventi (notifiche) per l'API key corrente. Trigger scan automatico se scan=true (default).
Query params
| Field | Type | Description |
|---|---|---|
| unread_only | boolean | Solo eventi non letti (default false) |
| limit | integer | Default 50, max 500 |
| offset | integer | Paginazione |
| scan | boolean | Default true. Se true, scan + create events PRIMA di ritornare |
Response shape
{
"events": [
{
"id": 42,
"subscription": {"id": 1, "name": "Watch Circolari AdE", "sub_type": "source", "target": "ade_circolari"},
"document_id": 656712,
"title": "Circolare 14/E del 2026 — Forfettario 2026",
"url": "https://...",
"source": "ade_circolari",
"country": "IT",
"created_at": "2026-05-20T08:15:00Z",
"read_at": null
}
],
"total": 128,
"new_events_just_created": 3
}
Norm Alerts — create subscription
Request body
| Field | Type | Description |
|---|---|---|
| sub_type | string | Tipo subscription: source | module | collection | keyword | reference | country |
| target | string | Valore da osservare. Esempi: "ade_circolari" (source), "diritto-tributario" (module), "superbonus" (keyword), "art-2 D.Lgs. 74/2000" (reference), "AE" (country) |
| name | string | Opzionale. Label friendly per la UI (es. "Watch Circolari AdE") |
| target_meta | object | Opzionale. Metadata addizionali (es. {"min_relevance": 0.5}) |
Example
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
https://bancadati.doczoom.ai/api/alerts/subscriptions \
-d '{"sub_type":"keyword","target":"superbonus","name":"Watch superbonus"}'
Backfill 7-day
Al primo poll dopo la creazione, l'API ritorna anche gli eventi degli ultimi 7 giorni (UX: l'utente vede subito attività). Poi solo eventi nuovi.
Norm Alerts — list subscriptions
Lista delle subscription attive per l'API key. Include conteggio eventi pendenti per ognuna.
Norm Alerts — toggle subscription
Attiva/disattiva una subscription senza eliminarla. Le subscription inattive non generano nuovi eventi.
Norm Alerts — delete subscription
Elimina definitivamente la subscription. Gli eventi storici restano in DB ma non saranno più mostrati.
Norm Alerts — mark event read
Marca un singolo evento come letto (setta read_at = NOW()).
Norm Alerts — mark all read
Marca TUTTI gli eventi pendenti dell'utente come letti. Response: {"marked_read": N}.
Norm Alerts — stats
Response shape
{
"subscriptions_active": 5,
"subscriptions_total": 7,
"events_total": 312,
"events_unread": 12,
"last_scan_at": "2026-05-20T08:15:00Z"
}
Audit Stats
Aggregati audit log: tasso abstention, avg top_score, tasso citation hallucinations, success rate retrieval, ultimi N giorni. Endpoint per dashboard interna.
Response shape
{
"period_days": 7,
"total_queries": 12483,
"abstention_rate": 0.034,
"avg_top_score": 0.71,
"hallucination_rate": 0.011,
"reprompt_rate": 0.16,
"factuality_flag_rate": 0.04
}
Audit Recent
Ultime N entry dell'audit_log (query, top_score, citation_hallucinations, factuality_issues, timing_ms). Per debug e fine-tuning.
Audit Analytics
Aggregati per dimensione (source citata, modulo richiesto, giorno). Restituisce time series + distribuzione.
Scheduler Status v25.101
Stato dello scheduler per ogni source: ultima ingestion, ore da ultima, cron schedule, country, ecc.
Tutte le 67 fonti devono apparire con hours_since_last <= 48. Sorgente di verità per "tutte le fonti aggiornate 1×/giorno?".
Response shape
{
"sources": [
{
"source": "ade_circolari",
"country": "IT",
"last_doc_at": "2026-05-20T08:15:00Z",
"hours_since_last": 3,
"scheduled": true,
"cron_hint": "daily 08:15 UTC",
"is_stale": false
}
/* ... 66 più ... */
],
"stale_sources": [],
"stale_threshold_hours": 48
}
Health — Sources freshness
Health check sulle source: ritorna HTTP 200 se tutte le 67 sources hanno ingestion entro 48h, HTTP 207 se 1-2 stale, HTTP 503 se ≥3 stale. Per integrazione UptimeRobot / Healthchecks.io.
Health — Cloudflare Proxy
Stato del Cloudflare Worker proxy per i domini gov bloccati (normattiva.it, gazzettaufficiale.it, italgiure.giustizia.it, giustizia-amministrativa.it, eur-lex.europa.eu). Ritorna HTTP 200 se tutti i 5 domini sono raggiungibili via proxy, 207 se 1-2 down, 503 se ≥3 down.
Response shape
{
"proxy_url": "https://taxharvest-proxy.dilan-80e.workers.dev",
"domains": [
{"domain": "italgiure.giustizia.it", "status": 200, "latency_ms": 340},
{"domain": "normattiva.it", "status": 200, "latency_ms": 512}
/* ... */
],
"fail_count": 0,
"last_check_at": "2026-05-20T06:30:00Z"
}
Tools — list
Schema vivo dei tools real-time disponibili (VIES P.IVA, Codice Fiscale, cambio valuta BCE, ecc.) per il routing di /api/doczoom/tool e /api/tool/{tool_name}. Usato dal frontend per popolare bottoni "verifica P.IVA", "calcola CF", ecc.
Response shape
{
"tools": [
{"name": "vies", "label": "Verifica P.IVA UE (VIES)", "params": ["country", "vat_number"]},
{"name": "codice_fiscale", "label": "Calcolo Codice Fiscale", "params": ["name", "surname", "birth_date", "birth_place", "gender"]},
{"name": "exchange_rate", "label": "Cambio valuta BCE", "params": ["from", "to", "date"]}
]
}
Cassazione — full corpus v25.104
Lista delle sentenze Corte di Cassazione (336.824 docs: civile, penale, costituzionale, relazioni Massimario). Shortcut di GET /api/legal-judgments?authority=cassazione.
Query params
| Field | Type | Description |
|---|---|---|
| court | string | Filtro libero su title (es. ?court=Civile, ?court=Penale, ?court=SU) |
| year | integer | Filtro anno (es. ?year=2024) |
| parties | string | Substring match su title (parti) |
| q | string | Full-text su title |
| page / per_page | integer | Paginazione (default 1 / 20, max 100) |
Example
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/cassazione?court=Civile&year=2024&per_page=10"
Cassazione — lookup specifico
Lookup di una Cassazione specifica per numero+anno. Match su pattern "n. NUMERO/ANNO" nel title. Ritorna lista di match (di solito 1, ma può essere >1 se ci sono ordinanze + sentenze con stesso numero).
Example
curl -H "X-API-Key: $KEY" https://bancadati.doczoom.ai/api/cassazione/12345/2024
# → { numero, anno, matches: [{ id, title, court, year, case_number, ... }] }
404 quando non trovata
HTTP 404
{ "error": "cassazione_not_found", "numero": 99999999, "anno": 2024 }
TAR — Tribunali Amministrativi Regionali
Lista sentenze TAR (242.019 provvedimenti, 30 sedi regionali). Shortcut di ?authority=tar.
Query params
| Field | Type | Description |
|---|---|---|
| sede | string | Sede TAR (es. ROMA, MILANO, NAPOLI, LATINA, BARI, ecc. — 30 sedi totali). Match su title. |
| year | integer | Filtro anno |
| parties / q | string | Match su title |
Example
curl -H "X-API-Key: $KEY" \
"https://bancadati.doczoom.ai/api/tar?sede=ROMA&year=2026&per_page=20"
Consiglio di Stato + CGA + Adunanza Plenaria
Lista decisioni CdS, CGARS e Adunanza Plenaria (~20.575 docs). Shortcut di ?authority=cds.
Example
curl -H "X-API-Key: $KEY" "https://bancadati.doczoom.ai/api/consiglio-stato?year=2026"
Corte Costituzionale
Sentenze, ordinanze, decreti Corte Cost. (3.808 docs). Shortcut di ?authority=corte-costituzionale (alias ?authority=cost).
CGUE — Corte di Giustizia UE
Sentenze + comunicati IT della Corte di Giustizia dell'Unione Europea (1.410 docs).
CEDU — Corte Europea Diritti Umani
Sentenze CEDU (HUDOC) — 9 docs (corpus in espansione).
Giustizia Tributaria + Massimario CGT
Massimario delle Corti di Giustizia Tributaria (1.112 massime). Coverage CGT di primo e secondo grado.
ABF — Arbitro Bancario Finanziario
Decisioni dell'Arbitro Bancario Finanziario (280 docs). Risoluzione stragiudiziale controversie banca-cliente.
AGCM — Antitrust
Bollettini AGCM (808 docs): abuso posizione dominante, intese restrittive, concentrazioni, pratiche commerciali scorrette.
AGCOM — Autorità Comunicazioni
Delibere AGCOM (537 docs): TLC, audiovisivo, postale, copyright digitale.
🇦🇪 Sentenze UAE (ADGM + DIFC combinate)
Lista combinata sentenze UAE court (102 docs: 80 ADGM CFI + 22 DIFC). Shortcut di ?country=AE.
Query params
| Field | Type | Description |
|---|---|---|
| court | string | Filtro libero (es. ?court=ARB per arbitration cases) |
| year / parties / q | string | Standard |
Example
curl -H "X-API-Key: $KEY" "https://bancadati.doczoom.ai/api/sentenze-uae?per_page=20"
🇦🇪 ADGM — Abu Dhabi Global Market
Sentenze ADGM Courts (80 docs CFI) — Court of First Instance Abu Dhabi Global Market. Common law in lingua inglese. Shortcut di ?authority=adgm&country=AE.
🇦🇪 DIFC — Dubai International Financial Centre
Sentenze DIFC Courts (22 docs) — Court of First Instance + Court of Appeal + Small Claims Tribunal Dubai. Common law in inglese. Shortcut di ?authority=difc&country=AE.
Health Check
Uptime check (no auth richiesta). Latenza tipica ~1ms.
{"status": "ok", "timestamp": "2026-04-29T11:30:00Z"}
System Info
Info sistema (versione, uptime, container memory).
TaxHarvest API · v25.110 · bancadati.doczoom.ai · Last updated 2026-06-01 · 65 codici Normattiva art-by-art · 67 fonti (61 IT + 6 UAE) · 648K+ docs · 3.92M+ chunks IT + 28K UAE · 18 moduli · 66 collections · 13 endpoint giurisprudenza dedicati · ⚡ fast-path lookup sentenze 200ms · 📄 document viewer /doc/{id} (⬇ PDF/Word)