API
Accedi ai dati catastali, geocoding e valutazioni immobiliari di tutta Italia tramite API REST - completamente gratuite.
Ottieni la tua API key gratuita
Crea un account per generare token API personali. 10.000 richieste/ora, tutti i dati inclusi.
Accedi o RegistratiDa una particella a 80+ campi arricchiti in una chiamata.
Seleziona una particella e scopri cosa restituisce GET /api/v2/parcels/{id} - mappa, rischi, valori OMI, demografia, terreno, beni culturali, POI. Tutto JSON, tutto reale.
Questi sono dati reali restituiti dall'endpoint /parcels/{id}. Ogni sezione è filtrabile con ?include= per payload minimi.
Documentazione completa
Catalogo Dati Zornade: 20 blocchi, ~85 M particelle, fonti ufficiali
Documentazione tecnica completa di ogni campo restituito dall'API /parcels/{id}: origine, metodologia di costruzione, frequenza di aggiornamento e licenza. Trasparenza totale, tracciabilità fino alla fonte primaria.
~85 M
Particelle catastali
7.899
Comuni italiani
20
Blocchi dati
15+
Fonti ufficiali
Dati catastali base
/parcels/{id}?include=basicIdentificatori univoci, geometria poligonale, area e comune amministrativo per ogni particella catastale italiana presente nel WFS dell'Agenzia delle Entrate.
Copertura
~85 milioni di particelle, 7.899 comuni (Italia meno Bolzano/Trento serviti da fonti regionali).
Freschezza
Snapshot WFS Agenzia delle Entrate aggiornato in continuo; tabella `parcels` rigenerata su richiesta.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| fid | integer | Identificatore numerico interno Zornade. Stabile per snapshot. |
| gml_id | string | Identificatore GML dell'Agenzia delle Entrate, formato `CadastralParcel.IT.AGE.PLA.<comune><foglio><particella>.<lettera>`. |
| label | string | Numero/lettera particella visibile sulla mappa catastale. |
| cadastral_reference | string | Riferimento catastale completo (foglio/particella/sub) se disponibile dal WFS. |
| area_m2 | number (m²) | Area calcolata in proiezione metrica EPSG:3857 con `ST_Area(ST_Transform(geometry, 3857))`. |
| centroid | object { lat, lng } | Centroide geometrico in WGS84 (EPSG:4326). |
| geometry | GeoJSON Polygon | Geometria 2D in WGS84. Esclusa per default, includibile tramite `include=`. |
| municipality | object | `code` (codice catastale Belfiore), `name`, `province`, `region`. |
Come viene costruito
Ingestion via wfs_parcel_ingestion.py: il WFS dell'Agenzia delle Entrate viene paginato per comune con buffer 16 km e le geometrie validate con ST_MakeValid. Per ogni comune wfs_parcel_count tiene traccia del numero atteso di particelle, validato a fine pull. Bolzano e Trento (non coperti dal WFS AdE) sono integrati da bolzano_parcel_ingestion.py e trento_parcel_ingestion.py tramite i rispettivi portali provinciali.
Fonte primaria
Agenzia delle Entrate - Servizio Cartografico WFS - sito ufficiale
Licenza: Riuso libero (cfr. condizioni AdE).
Foglio catastale, sezione, CAP
/parcels/{id}?include=cadastralDati amministrativi della particella: foglio, sezione urbana, codice catastale del comune e CAP sub-comunale, indispensabili per pratiche edilizie e visure.
Copertura
~302.000 fogli catastali, ~9.200 CAP sub-comunali italiani.
Freschezza
Geometrie fogli aggiornate ad ogni rebuild del WFS; CAP sub-comunali da ISTAT 2024.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| foglio | string | Numero del foglio catastale (composito con sezione_urbana se presente). |
| sezione_urbana | string | Sezione amministrativa quando presente (centri storici, frazioni). |
| comune_code | string | Codice catastale Belfiore (es. "H501" per Roma). |
| postal_code | string | CAP sub-comunale derivato per join spaziale sul centroide. |
Come viene costruito
Join spaziale: per ogni particella si calcola ST_Contains tra il centroide e i poligoni di catasto_fogli (foglio/sezione) e cap_subcomunali. Il codice comune è letto direttamente dal campo parcels.administrativeunit. La tabella parcel_catasto mantiene il match pre-computato (Phase 2 enrichment).
Fonte primaria
Agenzia delle Entrate (fogli) + ISTAT (CAP sub-comunali) - sito ufficiale
Licenza: CC BY 3.0 IT (ISTAT).
Indirizzi (street, number)
/parcels/{id}?include=address + addressesLista degli indirizzi civici che insistono sulla particella, da OpenAddresses e arricchimenti comunali. Utile per geocoding inverso e identificazione fabbricati.
Copertura
~18,7 milioni di civici italiani (copertura disomogenea per regione).
Freschezza
OpenAddresses snapshot 2024; comuni maggiori (Roma, Milano, Torino, Napoli) integrati con feed comunali.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| address | object | null | Primary address deterministico per la particella (`{ street, number, exponent, locality }`) o `null` se non disponibile. |
| addresses[] | array | Lista completa degli indirizzi che intersecano la particella (max 20 elementi). Ogni elemento contiene `street`, `number`, `exponent`, `locality`. |
Come viene costruito
parcel_address contiene per ogni particella il primary address (deterministico per ordine alfabetico) e il conteggio totale. La lista completa è risolta runtime con ST_Intersects su addresses.geom, max 20 risultati per chiamata. Nota: alcuni feed comunali contengono duplicati esatti per lo stesso civico (vedi audit A7).
Fonte primaria
OpenAddresses + feed comunali (Roma Capitale, Comune di Milano, etc.) - sito ufficiale
Licenza: CC0 / ODbL (mix per fonte).
Rischio sismico
/parcels/{id}?include=risk (seismic_zone, pga)Zona sismica ufficiale (1–4) e Peak Ground Acceleration (PGA) per ogni particella, secondo la classificazione INGV/OPCM. Dato chiave per due-diligence immobiliare e Sismabonus.
Copertura
100% del territorio italiano (zonazione OPCM 3274/2003 e aggiornamenti regionali).
Freschezza
Mappa di pericolosità sismica MPS04 (INGV 2004, ancora riferimento normativo). Aggiornamento MPS19 in corso di recepimento.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| seismic_zone | integer (1–4) | 1 = pericolosità molto alta, 4 = pericolosità molto bassa. Restituito nella sezione `risk`. |
| pga | number (g) | Peak Ground Acceleration con probabilità di superamento del 10% in 50 anni. Restituito nella sezione `risk`. |
Come viene costruito
Join spaziale ST_Intersects tra centroide particella e poligoni di ingv_zonesismiche. Per particelle che cadono in zone di transizione tra ordinanze comunali diverse, viene preso il poligono più recente. Tabella pre-calcolata in parcel_risk.
Fonte primaria
INGV - Istituto Nazionale di Geofisica e Vulcanologia - sito ufficiale
Licenza: CC BY 4.0.
Rischio alluvionale (PGRA)
/parcels/{id}?include=risk (flood_level)Livelli di pericolosità idraulica ISPRA-PGRA: HPH (alta), MPH (media), LPH (bassa). Obbligatori per atti notarili e mutui in aree mappate.
Copertura
100% bacini distrettuali idrografici italiani (7 distretti, ciclo PGRA 2021–2027).
Freschezza
Piano Gestione Rischio Alluvioni 2021 (terzo ciclo Direttiva 2007/60/CE). Aggiornamento parziale 2024.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| flood_level | string | Livello peggiore che intersecta la geometria della particella: `HPH` (alta) | `MPH` (media) | `LPH` (bassa) | `null`. Restituito nella sezione `risk`. |
Come viene costruito
Per ogni particella si interroga ispra_alluvioni con ST_Intersects sul centroide (livello centroide) e sull'intera geometria (livello peggiore). La gerarchia HPH > MPH > LPH è applicata in PostGIS via CASE ordinato.
Rischio frane (PAI/IFFI)
/parcels/{id}?include=risk (landslide_level)Pericolosità da frana secondo i Piani di Assetto Idrogeologico (PAI) e inventario IFFI ISPRA. Cinque livelli da P1 (bassa) a P4 (molto alta) + AA (aree di attenzione).
Copertura
100% Italia. ~620.000 frane mappate nell'Inventario IFFI.
Freschezza
PAI aggiornati per autorità di bacino distrettuale. IFFI rilascio 2024.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| landslide_level | string | Livello peggiore di pericolosità da frana: `P1` | `P2` | `P3` | `P4` | `AA` | `null`. Restituito nella sezione `risk`. |
Come viene costruito
ispra_frane contiene la fusione dei PAI dei 7 distretti idrografici. Il LATERAL join sulla geometria della particella usa ARRAY_AGG ordinato per priorità (P4 > P3 > ... > AA) e prende il primo elemento. Vedi audit A9 per ottimizzazione futura.
Subsidenza InSAR (movimenti del suolo)
/parcels/{id}?include=subsidenceVelocità di abbassamento/sollevamento del suolo da interferometria SAR satellitare. Critico per zone bonificate, costiere e aree con estrazione idrica.
Copertura
Pianura Padana, costa adriatica, Roma, Napoli, aree vulcaniche. Copertura disomogenea su Appennino e Alpi.
Freschezza
Dataset PSI (Persistent Scatterer Interferometry) 2014–2023, processato da Sentinel-1.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| velocity_mm_year | number (mm/anno) | Velocità lungo la linea di vista (LOS). Negativo = abbassamento. |
| acceleration | number (mm/anno²) | Variazione della velocità (proxy di stabilità nel tempo). |
| risk_class | integer (0–4) | 0 = stabile, 4 = subsidenza severa. |
| risk_label | string | Etichetta leggibile: "Stabile", "Moderata", "Significativa", "Severa", "Estrema". |
| risk_index | number (0–1) | Indice composito normalizzato (velocità + accelerazione). |
| direction | string | `subsidence` | `uplift` | `stable`. |
| trend | string | `accelerating` | `decelerating` | `linear`. |
Come viene costruito
Punti PSI di subsidenza intersecati con il centroide. Soluzione attuale usa LIMIT 1 non deterministico (audit A4): il punto restituito può non essere il più vicino. Ottimizzazione pianificata: ORDER BY centroide <-> geom LIMIT 1 con prefiltro ST_DWithin.
Fonte primaria
Copernicus Land Monitoring Service - European Ground Motion Service - sito ufficiale
Licenza: Copernicus Data and Information Policy (riuso libero).
Quota, pendenza, esposizione
/parcels/{id}?include=terrainMetriche geomorfologiche calcolate dal DEM TINItaly 10 m: quote, ruggedness, pendenza e aspect prevalente. Indispensabili per valutazioni edificabilità e potenziale solare.
Copertura
100% Italia, risoluzione orizzontale 10 m.
Freschezza
TINItaly DEM versione 1.1 (INGV, rilascio 2023).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| elevation_min | number (m) | Quota minima entro la particella. |
| elevation_max | number (m) | Quota massima. |
| elevation_mean | number (m) | Quota media. |
| elevation_std | number (m) | Deviazione standard delle quote (eterogeneità). |
| ruggedness_index | number (m) | Range di quota (max − min). |
| slope_mean | number (°) | Pendenza media calcolata su raster derivato. |
| slope_max | number (°) | Pendenza massima (0–90°). |
| tri_mean | number (m) | Terrain Ruggedness Index (Riley et al. 1999). |
| aspect_predominant | string | Esposizione prevalente: `N` | `NE` | `E` | `SE` | `S` | `SW` | `W` | `NW` | `flat`. |
Come viene costruito
terrain_enrichment.py esegue zonal statistics su raster TINItaly DEM 10 m e su 3 raster derivati (slope, TRI, aspect) generati con GDAL DEMutilities (prepare_derived_rasters.sh). Output: parcel_terrain, una riga per particella.
Popolazione residente stimata
/parcels/{id}?include=populationStima della popolazione residente per particella tramite redistribuzione dasymetric: somma WorldPop sul comune × frazione footprint edifici residenziali.
Copertura
100% Italia. Accuratezza migliore in aree con elevata copertura OSM/GBA.
Freschezza
WorldPop 2025 (raster 30 m) + footprint edifici aggiornati 2026-05.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| estimated | number | Stima dasymetric: residenti = `municipality_total × residential_footprint_parcel / residential_footprint_muni`. |
| sum | number | Somma raw dei pixel WorldPop entro la particella (baseline). |
| pixel_count | integer | Numero di pixel WorldPop intersecati. |
| mean | number | Media WorldPop nei pixel intersecati. |
| dasymetric | number | Componente dasymetric della stima (in residenti). |
| municipality_total | number | Totale comunale (somma WorldPop sui confini ISTAT). |
| estimation_method | string | `hybrid` | `raster_only` | `fallback_legacy`. |
| estimation_confidence | number (0–1) | Confidenza relativa della stima. |
| source | string | Stringa di provenienza (es. `worldpop_2025_30m+osm_dasymetric`). |
Come viene costruito
population_enrichment.py applica l'approccio dasymetric documentato da WorldPop: (1) calcolo budget comunale, (2) zonal stats raster sulla particella, (3) redistribuzione proporzionale al footprint residenziale OSM. Particelle senza edifici → popolazione 0. Fallback su building_footprint_m2 totale se residential_footprint_m2 nullo per il comune.
Fonte primaria
WorldPop (University of Southampton) + OSM Buildings - sito ufficiale
Licenza: CC BY 4.0 (WorldPop) + ODbL (OSM).
Edifici (footprint e classificazione)
/parcels/{id}?include=buildingsConteggio e footprint degli edifici sulla particella, distinzione residenziale/non residenziale da OpenStreetMap e dal Geoportale Nazionale (GBA buildings).
Copertura
OSM 100% Italia; GBA copertura ufficiale Geoportale Nazionale.
Freschezza
OSM snapshot 2026-05 (mensile); GBA versione 2024.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| count | integer | Numero totale di footprint che intersecano la particella. |
| footprint_m2 | number (m²) | Area totale dei footprint (può eccedere area_m2 in caso di edifici multi-piano). |
| residential_count | integer | Edifici con tag/classificazione residenziale. |
| residential_footprint_m2 | number (m²) | Area cumulativa residenziale. |
| source | string | `osm` | `gba` | `merged`. |
Come viene costruito
building_enrichment.py intersecta i footprint OSM con la particella e classifica come residenziale per tag building=residential|apartments|house|.... gba_buildings_loader.py aggiunge il dataset ufficiale GBA (Geoportale Nazionale) come fonte alternativa e per validazione. Output in parcel_buildings.
Fonte primaria
OpenStreetMap + Geoportale Nazionale (GBA - Geographical Building Atlas) - sito ufficiale
Licenza: ODbL (OSM); riuso ufficiale (GBA).
Redditi MEF e affordability
/parcels/{id}?include=economicsReddito medio dichiarato, distribuzione per scaglioni IRPEF, indice di Gini e affordability immobiliare per CAP sub-comunale. Dati MEF ufficiali aggregati alla zona postale.
Copertura
100% CAP italiani con dichiarazioni IRPEF. Soglia privacy MEF: nessun dato per CAP con < 3 dichiaranti.
Freschezza
Dichiarazioni dei redditi MEF - Dipartimento delle Finanze (ultimo rilascio disponibile).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| average_income | number (EUR) | Reddito imponibile medio per dichiarante. |
| taxpayers | integer | Numero di dichiaranti nel CAP. |
| total_income | number (EUR) | Reddito complessivo aggregato del CAP. |
| net_tax | number (EUR) | IRPEF netta totale del CAP. |
| tax_year | integer | Anno di imposta a cui si riferiscono le dichiarazioni MEF. |
| gini_index | number (0–1) | Coefficiente di Gini calcolato dalle frequenze degli scaglioni IRPEF. |
| affordability_index | number (anni) | Anni di reddito medio per acquistare un appartamento standard al prezzo OMI mediano. |
| affordability_apt_size_m2 | number (m²) | Taglio appartamento usato nel calcolo affordability (default 80 m²). |
| avg_residential_price_m2 | number (EUR/m²) | Prezzo OMI mediano residenziale del CAP. |
| income_brackets | object | Frequenze per scaglione: `lte_zero`, `from_0_to_10k`, `from_10k_to_15k`, `from_15k_to_26k`, `from_26k_to_55k`, `from_55k_to_75k`, `from_75k_to_120k`, `over_120k`. |
Come viene costruito
Dati MEF Direzione Studi e Ricerche Economico Fiscali aggregati per CAP. Il Gini è calcolato a runtime dalla curva di Lorenz delle 7 fasce IRPEF (RPC get_parcel_full_detail). L'affordability combina income_brackets mediano con il prezzo OMI mediano residenziale della zona. Match particella → CAP via centroide.
Fonte primaria
MEF - Dipartimento delle Finanze, Dichiarazioni dei Redditi - sito ufficiale
Licenza: Riuso libero (dati open MEF).
Demografia ISTAT (sezioni censuarie)
/parcels/{id}?include=demographicsComposizione demografica, istruzione, occupazione, stranieri, famiglie e abitazioni alla scala della sezione censuaria ISTAT. Risoluzione molto fine, ideale per analisi di micro-zona.
Copertura
~756.000 sezioni di censimento italiane.
Freschezza
Censimento permanente della popolazione e delle abitazioni (ISTAT, edizione 2021, rilascio 2023).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| population_total | integer | Popolazione residente totale della sezione. |
| male / female | integer | Suddivisione di genere. |
| age_brackets | object | Classi quinquennali da `0_4` a `75_plus`. |
| education | object | Frequenze per titolo di studio: `no_title`, `elementary`, `middle_school`, `high_school`, `university`. |
| employed | integer | Residenti occupati. |
| foreigners | object | Stranieri: `total`, `eu`, `non_eu`. |
| households | object | Famiglie per numero componenti: `1_member`…`6_plus_members`, `total`. |
| dwellings | object | Abitazioni: `total`, `occupied`, `vacant`. |
Come viene costruito
Tabella census_sections popolata con i microdati ISTAT 2021 aggregati a sezione censuaria. Match particella → sezione tramite ST_Contains sul centroide. Privacy ISTAT: variabili con conteggi sotto soglia possono essere arrotondate o oscurate.
Fonte primaria
ISTAT - Censimento Permanente della Popolazione - sito ufficiale
Licenza: CC BY 3.0 IT.
Copertura del suolo (CORINE)
/parcels/{id}?include=land_coverClassificazione standardizzata europea della copertura del suolo CORINE Land Cover livello 3 (44 classi). Riferimento ufficiale per Valutazioni di Impatto Ambientale (VIA).
Copertura
100% Italia (parte del programma Copernicus Land).
Freschezza
CORINE Land Cover 2018 (ultima release confermata; CLC 2024 in pre-release).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| code | string | Codice CLC a 3 cifre (es. "112" = "Tessuto urbano discontinuo"). |
| class | string | Etichetta classe livello 3. |
| subclass | string | Sotto-classificazione se disponibile. |
| description | string | Descrizione estesa della classe. |
Come viene costruito
Tabella corine_landcover popolata via download_corine.py dal portale Copernicus. Match particella → classe via ST_Intersects sul centroide; parcel_landcover mantiene il match pre-calcolato. Source string esplicita: "CORINE Land Cover 2018 - Copernicus/EEA".
Fonte primaria
Copernicus Land Monitoring Service (EEA - European Environment Agency) - sito ufficiale
Licenza: Copernicus Data Policy (riuso libero anche commerciale).
Uso del suolo urbano (Urban Atlas)
/parcels/{id}?include=land_useClassificazione fine dell'uso del suolo nelle Functional Urban Areas (FUA) italiane: 27 classi urbane più alta risoluzione di CORINE. Disponibile per le ~80 città italiane sopra 50.000 abitanti.
Copertura
Solo Functional Urban Areas (FUA) europee. Per l'Italia: tutti i capoluoghi e centri principali.
Freschezza
Urban Atlas 2018 (release più recente per l'Italia).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| code | string | Codice UA 5 cifre (es. "11100" = "Continuous urban fabric"). |
| class | string | Etichetta classe Urban Atlas. |
| level1 | string | Macro-categoria (urbano / industriale / verde / agricolo / acqua). |
| level2 | string | Sotto-categoria livello 2 UA. |
Come viene costruito
download_urban_atlas.py recupera i shapefile dal portale Copernicus per ogni FUA italiana e li carica in urban_atlas. Le particelle fuori FUA restituiscono null per questa sezione (comportamento atteso, non errore).
Fonte primaria
Copernicus Land Monitoring Service - Urban Atlas - sito ufficiale
Licenza: Copernicus Data Policy.
Quotazioni immobiliari OMI
/parcels/{id}?include=valuationValori minimi e massimi di compravendita e locazione per tipologia immobiliare, semestre per semestre, secondo l'Osservatorio del Mercato Immobiliare dell'Agenzia delle Entrate.
Copertura
~24.000 zone OMI sul territorio italiano (escluse aree marginali).
Freschezza
Semestre corrente (OMI 2025-2) + confronto col semestre precedente (OMI 2025-1).
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| zone | string | Codice zona OMI (es. "B29"). |
| zone_description | string | Toponimo descrittivo (es. "VIMINALE (VIA TORINO)"). |
| fascia | string | Fascia OMI (`B` centrale, `C` semicentrale, `D` periferica, `E` suburbana, `R` extraurbana). |
| microzona | integer | Identificativo micro-zona OMI all'interno della zona. |
| municipality | string | Denominazione del comune OMI di riferimento. |
| property_type | string | Tipologia: Abitazioni civili, signorili, economiche, ville, uffici, negozi, magazzini, box, capannoni, etc. |
| condition | string | Stato conservativo: NORMALE | OTTIMO | SCADENTE. |
| purchase.min_eur_m2 / max_eur_m2 | number (EUR/m²) | Forchetta prezzi compravendita. |
| rental.min_eur_m2 / max_eur_m2 | number (EUR/m²·mese) | Forchetta canoni di locazione. |
| previous_semester | object | Stessi campi del semestre precedente per calcolo trend. |
Come viene costruito
omi_ingestion.py importa il pacchetto AdE (CSV QI_*_VALORI + QI_*_ZONE + un KML per comune con i poligoni zona) in omi_2025_2 (semestre corrente) e omi_2025_1 (precedente). La RPC esegue join spaziale del centroide e restituisce TUTTE le righe per la zona (multiple tipologie/condizioni).
Fonte primaria
Agenzia delle Entrate - Osservatorio del Mercato Immobiliare (OMI) - sito ufficiale
Licenza: Riuso libero per finalità non commerciali (cfr. condizioni AdE).
Storico quotazioni OMI (22 semestri)
/parcels/{id}?include=valuation_historySerie storica completa delle quotazioni OMI per la particella, dal primo semestre 2015 al secondo semestre 2025 (22 semestri). Tipologia "Abitazioni civili", stato conservativo NORMALE. Include il tracking del codice zona OMI in ogni semestre, perché le zone possono essere riclassificate nel tempo.
Copertura
Tutte le particelle WFS con zona OMI assegnata (urbane). Le particelle in zone rurali (codici Rxx) restituiscono solo il codice zona, senza valori monetari.
Freschezza
Aggiornato con OMI 2025/2 (ultimo semestre pubblicato). Pre-calcolato nella satellite table `parcel_omi_history` da `10_enrich_omi_history.sql`. Lookup a singolo PK, latenza sub-millisecondo.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| zone_current | string | Codice zona OMI corrente (semestre più recente). |
| municipality_code | string | Codice ISTAT del comune (es. "H501" per Roma). |
| property_type | string | Sempre "Abitazioni civili" in questa release. |
| condition | string | Sempre "NORMALE" in questa release. |
| semesters[] | array<object> | Lista cronologica di 22 elementi (2015/1 → 2025/2). |
| semesters[].semester | string | Identificativo semestre formato `YYYY_S` (es. "2024_2"). |
| semesters[].zone | string | Codice zona OMI attivo in quel semestre (può differire da `zone_current`). |
| semesters[].purchase.{min,max,mid}_eur_m2 | number (EUR/m²) | Forchetta prezzi compravendita; `mid` = media min/max. `null` per zone rurali. |
| semesters[].rental.{min,max,mid}_eur_m2 | number (EUR/m²·mese) | Forchetta canoni di locazione. `null` per zone rurali. |
| semesters[].gross_yield_pct | number (%) | Rendimento lordo annuo: `(rental_mid × 12) / purchase_mid × 100`. |
| metrics | object | Analytics pre-calcolate (CAGR, volatilità, max drawdown). Attualmente `null`, popolato in una release futura. |
| annotations | object | Annotazioni editoriali sui cambi di zona / discontinuità. Attualmente `null`. |
| data_version | string | Versione del dataset storico (es. "omi_2015_1..2025_2_v1"). |
Come viene costruito
10_enrich_omi_history.sql per ogni comune fa lookup della particella sulla tabella OMI di ogni semestre (omi_2015_1 … omi_2025_2) tramite il codice r_omi_comune_amm/ r_omi_zona già materializzato nella satellite parcel_omi, e aggrega i 22 record in un unico jsonb. Le entry con campi monetari assenti (zone rurali) sono compattate via jsonb_strip_nulls per ridurre il payload. Il gross_yield_pct viene calcolato a build-time. Quando la zona OMI di una particella cambia tra semestri, lo storico riflette quella variazione: questo permette di tracciare riclassificazioni urbanistiche del comune nel decennio.
Fonte primaria
Agenzia delle Entrate - Osservatorio del Mercato Immobiliare (OMI), archivio storico semestrale 2015-2025 - sito ufficiale
Licenza: Riuso libero per finalità non commerciali (cfr. condizioni AdE).
Erosione costiera
/parcels/{id}?include=coastal_erosionPer particelle entro 1 km dalla costa: tasso medio di avanzamento/arretramento della linea di riva, tipologia di costa, litologia e indice di severità.
Copertura
Coste italiane (continentale + isole maggiori).
Freschezza
Dataset ISPRA aggiornato 2023.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| dynamic | string | `erosion` | `accretion` | `stable`. |
| avg_change_m_year | number (m/anno) | Variazione media della linea di riva. Negativo = arretramento. |
| max_change_m_year | number (m/anno) | Massima variazione registrata sul tratto. |
| severity_index | number (0–1) | Indice composito di severità. |
| coast_type | string | Tipologia: sabbiosa | rocciosa | ciottolosa | artificiale. |
| lithology | string | Litologia prevalente del tratto. |
| distance_m | number (m) | Distanza in metri dalla linea di riva. |
Come viene costruito
download_coastal_erosion.py importa il vettoriale ISPRA ispra_erosione_costiera. Per ogni particella si filtrano i tratti entro 1 km dal centroide (ST_DWithin) ordinati per distanza, max 5 record restituiti.
Vincoli culturali e paesaggistici
/parcels/{id}?include=cultural_heritageBeni vincolati dal Codice dei Beni Culturali e del Paesaggio (D.Lgs. 42/2004) che insistono sulla particella: monumenti, ville storiche, parchi archeologici, fontane, edifici notificati.
Copertura
Vincoli formalizzati nel SIGECweb del MiC. ~230.000 beni in Italia.
Freschezza
SIGECweb 2024.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| id | string | Identificatore SIGECweb. |
| name | string | Denominazione ufficiale del bene. |
| type | string | Tipologia (fontana, palazzo, chiesa, area archeologica, etc.). |
| class | string | Classe del bene secondo schedatura. |
| address | string | Indirizzo del bene. |
| municipality | string | Comune di ubicazione del bene vincolato. |
| province | string | Sigla provincia di ubicazione del bene. |
| catalog_code | string | Codice di catalogazione storica MiC. |
Come viene costruito
download_vincoli_culturali.py importa il vettoriale dei vincoli MiC in vincoli_culturali. Match runtime via ST_Intersects tra geometria particella e geometria del bene (poligonale, lineare o puntuale).
Fonte primaria
Ministero della Cultura - SIGECweb (Istituto Centrale per il Catalogo e la Documentazione) - sito ufficiale
Licenza: Riuso libero per finalità non commerciali.
Potenziale fotovoltaico (per edificio)
/parcels/{id}?include=solarStima deterministica del potenziale fotovoltaico per ogni edificio sulla particella: kWp installabili, produzione annua kWh, CAPEX, LCOE, NPV a 20 anni e payback. Metodologia Zornade v1.1 conforme alle specifiche PVGIS/JRC.
Copertura
Copertura nazionale: tutti gli edifici del catalogo GBA con footprint ≥ 25 m² in Italia.
Freschezza
Irraggiamento TMY da PVGIS-SARAH3 v5.3 (2005–2023, baseline 2020). Curva CAPEX Italia 2025.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| n_buildings | integer | Numero di edifici sulla particella valutati. |
| kwp_max_total | number (kWp) | Capacità installabile totale somma di tutti gli edifici. |
| pvout_modern_kwh_year_total | number (kWh/anno) | Produzione attesa scenario "moderno" (perdite di sistema 10% + soiling 3%). |
| pvout_pessimistic_kwh_year_total | number (kWh/anno) | Produzione attesa scenario "conservativo" (perdite 14%). |
| lcoe_eur_per_kwh_avg | number (EUR/kWh) | Levelized Cost of Energy medio ponderato sulla potenza. |
| npv_20y_eur_total | number (EUR) | Net Present Value a 20 anni (discount rate 5%, autoconsumo industriale/residenziale + CES + RID). |
| capex_eur_total | number (EUR) | Investimento iniziale stimato. |
| payback_years_simple_avg | number (anni) | Tempo di rientro semplice medio. |
| viability_class_max | string | `alta` | `media` | `bassa` | `non_idoneo`. Classe di fattibilità del miglior edificio sulla particella. |
| roof_pitch_avg_deg | number (°) | Pendenza media tetti (peso = footprint). |
| roof_aspect_avg_deg | number (°) | Azimut medio tetti (0 = Nord, 180 = Sud). |
| buildings[] | array | Dettaglio per edificio. Campi principali: `building_fid`, `roof_shape`, `roof_pitch_deg`, `roof_aspect_deg`, `roof_area_real_m2`, `roof_geometry_regime`, `kwp_max`, `pvout_modern_kwh_year`, `pvout_pessimistic_kwh_year`, `kwh_per_kwp_year_modern`, `kwh_per_kwp_year_pessimistic`, `capex_eur`, `lcoe_eur_per_kwh`, `npv_20y_eur`, `payback_years_simple`, `viability_class`, `bipv_eligible`, `confidence_level`, `shading_data_source`, `exclusion_reason`. |
| data_version | string | Stringa identificativa del dataset (es. `pvgis:v5.3;sarah3:2025-10;model:v1.1;f_ostr:0.5_0.65`). |
| methodology_version | string | Versione metodologia Zornade (attuale: `v1.1`). |
| updated_at | string (ISO 8601) | Timestamp di ricalcolo della particella. |
Come viene costruito
Pipeline a 6 stage (solar_*.py):
- Geometria: footprint da
gba_buildings+ classe d'uso da CORINE → tilt e azimut ottimi. - Orizzonte: 36 bin di skyline calcolati da LIDAR PNRR (viewshed analysis).
- TMY: serie oraria 8760 h da PVGIS-SARAH3 v5.3 (JRC).
- Fisica:
pvlibNOAA SPA + Hay-Davies + Faiman + Martin-Ruiz IAM + Huld 2011 + correzione CSI 2025. - Economia: CAPEX curva Italia 2025 (residenziale/industriale), autoconsumo, CES, RID, ROI 20 anni a sconto 5%.
- Validazione: 5 livelli (schema, sanity envelopes, cross-check PVGIS API, GSE Atlaimpianti, Terna).
Fonte primaria
PVGIS-SARAH3 v5.3 (JRC EU) + GBA buildings (Geoportale Nazionale) + CORINE 2018 + LIDAR PNRR - sito ufficiale
Licenza: PVGIS riuso libero; GBA riuso ufficiale; pipeline Zornade proprietaria.
Punti di interesse (POI)
/parcels/{id}?include=poiEsercizi commerciali, ristoranti, servizi e luoghi di interesse sulla particella, con categoria standardizzata. Utile per analisi di walkability e valutazione retail.
Copertura
Italia, tramite snapshot Foursquare Open Source Places. ~2,8 milioni di POI attivi.
Freschezza
Snapshot Foursquare OS Places, aggiornamento trimestrale.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| id | string | Foursquare venue ID. |
| name | string | Nome commerciale. |
| categories | string | Path di categoria (es. "[Food > Café]"). |
| address | string | Indirizzo del POI. |
| locality | string | Località/quartiere. |
| coordinates | object | `{ lat, lng }`. |
Come viene costruito
Tabella fsq_places, filtro date_closed IS NULL per esercizi attivi. Match via ST_Intersects con la geometria della particella.
Luminosità notturna VIIRS
/parcels/{id}?include=nightlightsRadianza notturna stimata per ogni particella catastale, disaggregata dasymetrically dal composito annuale NASA Black Marble VNP46A4. Proxy quantitativo di attività economica e di antropizzazione, utile per analisi urbane, OSINT e studi di sprawl.
Copertura
100% del territorio nazionale. La disaggregazione usa il building footprint OSM: nei comuni privi di edifici mappati si ricade su distribuzione uniforme; nei comuni senza pixel VIIRS validi (montagna remota, parchi naturali) tutte le particelle restano a `dark`.
Freschezza
Composito annuale VIIRS VNP46A4 Collection 2 (NASA Black Marble). Anno corrente del rilascio: 2023.
Campi restituiti
| campo | tipo | descrizione |
|---|---|---|
| available | boolean | `true` se la particella ha un record in `parcel_nightlights`, `false` altrimenti. In questo secondo caso gli altri campi sono assenti. |
| ntl_parcel | number (nW/cm²/sr) | Radianza notturna assegnata alla particella tramite disaggregazione dasymetric proporzionale al footprint residenziale. |
| ntl_density | number ((nW/cm²/sr)/km²) | Densità di radianza per area particella (`ntl_parcel / area_m2 × 1.000.000`). Permette confronti cross-particella indipendenti dalla taglia. |
| ntl_class | string | Classe ordinale di radianza: `dark` (<0,5), `dim` (0,5–3), `medium` (3–10), `bright` (10–30), `very_bright` (≥30 nW/cm²/sr). Robusta a saturazione e variazioni stagionali. |
| ntl_share | number (0–1) | Quota del budget VIIRS comunale assegnata a questa particella. La somma su tutte le particelle dello stesso comune vale 1,0 (modulo arrotondamenti). |
| ntl_mean_comune | number (nW/cm²/sr) | Radianza media VIIRS dell'intero comune (zonal stats sul confine ISTAT). Utile per contestualizzare il valore singolo. |
| estimation_method | string | `dasymetric` (footprint edifici disponibile, distribuzione pesata); `uniform` (nessun edificio OSM, distribuzione uniforme sulle particelle); `no_ntl` (nessun pixel VIIRS valido per il comune). |
| ntl_year | integer | Anno del composito VNP46A4 utilizzato (es. `2023`). |
| source | string | Identificativo della fonte: `viirs_vnp46a4_c2_2023`. |
| updated_at | string (ISO 8601) | Timestamp dell'ultimo refresh della particella. |
Come viene costruito
Pipeline nightlights_enrichment.py: (1) zonal stats mean del raster VIIRS VNP46A4 sui confini comunali ISTAT → ntl_mean_comune; (2) disaggregazione dasymetric alle particelle pesata sul footprint residenziale OSM: ntl_parcel = ntl_mean_comune × footprint_parcella / footprint_comune; (3) classificazione in 5 bande basata sulle soglie standard della letteratura VIIRS (Elvidge et al. 2017). Le particelle senza edifici ricevono ntl_parcel = 0 (classe dark). Il raster sorgente è il composito annuale Collection 2 a risoluzione nativa ~463 m, già corretto per stray-light, lunare e atmosferici dal pipeline NASA Black Marble. Per il rationale dasymetric vedi app/sql/migrations/011_parcel_nightlights.sql (commento in testa).
Fonte primaria
NASA Black Marble - VIIRS VNP46A4 (Collection 2) - sito ufficiale
Licenza: NASA Earth Science Data - riuso libero anche commerciale (cit. richiesta).
Riferimento tecnico API
Endpoint, autenticazione, headers, errori e best practice per integrare le API REST di Zornade.
API REST unica per geocoding, anagrafiche amministrative e dati catastali arricchiti. Tutto in JSON, solo metodo GET, stessa base URL per ogni endpoint.
Base URL
https://api.zornade.com/api/v2Versione runtime
2.4.0 (endpoint health)
Autenticazione
x-api-key obbligatorio, eccetto /health
Rate limit
10.000 richieste/ora per token
Quickstart in 2 chiamate
1) Verifica servizio con GET /health.
2) Esegui una chiamata autenticata con x-api-key.
curl "https://api.zornade.com/api/v2/health" curl -H "x-api-key: zrn_il_tuo_token" \ "https://api.zornade.com/api/v2/parcels/locate?lat=41.9028&lng=12.4964"
Scopes disponibili:
• geocoding:read - endpoint geocoding
• admin_data:read - regioni/province/comuni
• parcels:read - endpoint particelle e enrichment
Tutti gli endpoint richiedono un token API in header x-api-key, tranne /health.
curl -H "x-api-key: zrn_il_tuo_token" \ "https://api.zornade.com/api/v2/parcels/28009975"
• Non inviare Authorization: Bearer ... su API v2.
• Se ricevi UNAUTHORIZED_NO_AUTH_HEADER o UNAUTHORIZED_INVALID_JWT_FORMAT, il gateway non e allineato (mismatch deploy), non e un errore della tua API key.
• Le risposte autenticate includono sempre gli header X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
Endpoint stabili e orientati a risorsa. Tutti GET.
| Endpoint | Scope | Descrizione |
|---|---|---|
| /api/v2/health | - | Stato servizio, versione, endpoint disponibili |
| /api/v2/geocode/search | geocoding:read | Geocoding diretto per testo |
| /api/v2/geocode/reverse | geocoding:read | Geocoding inverso da coordinate |
| /api/v2/admin/regions | admin_data:read | Elenco regioni |
| /api/v2/admin/provinces | admin_data:read | Province, filtro opzionale per regione |
| /api/v2/admin/municipalities | admin_data:read | Comuni, filtro per provincia/regione |
| /api/v2/parcels/search | parcels:read | Ricerca particelle per comune/foglio/label/sezione |
| /api/v2/parcels/locate | parcels:read | Ricerca per punto, multipunto o bbox |
| /api/v2/parcels/{id} | parcels:read | Dettaglio completo con include selettivo |
Dettaglio completo di una particella con tutti i dati arricchiti. Scope: parcels:read
L'id può essere il fid numerico o il gml_id. Vedi il Catalogo Dati sopra per il dettaglio campo-per-campo di ognuna delle 20 sezioni.
# Tutti i dati GET https://api.zornade.com/api/v2/parcels/12345 # Solo rischio e valutazione GET https://api.zornade.com/api/v2/parcels/12345?include=basic,risk,valuation
Geocoding diretto e inverso. Scope: geocoding:read
# Diretto (max 50 risultati) GET https://api.zornade.com/api/v2/geocode/search?q=Via+del+Corso&city=Roma&limit=10 # Inverso (raggio in metri, max 500) GET https://api.zornade.com/api/v2/geocode/reverse?lat=41.9028&lng=12.4964&radius=100
Ogni risposta autenticata include headers per monitorare il consumo del rate limit:
• X-RateLimit-Limit - Limite massimo (1000)
• X-RateLimit-Remaining - Richieste rimanenti nell'ora
• X-RateLimit-Reset - Unix timestamp del prossimo reset
• Cache-Control - public, max-age=3600 per admin, no-store per dati
Tutte le risposte di errore hanno formato { error, message }.
• 400 - Parametri mancanti o non validi (INVALID_PARAMS, OUT_OF_BOUNDS)
• 401 - API key mancante (API_KEY_REQUIRED) o non valida (INVALID_API_KEY)
• 403 - Scope insufficiente (INSUFFICIENT_SCOPE)
• 404 - Risorsa non trovata (NOT_FOUND)
• 405 - Metodo non supportato - solo GET
• 429 - Rate limit superato (RATE_LIMITED)
• 502 - Errore database (QUERY_ERROR)
• Inizia sempre da /health prima delle chiamate business.
• Invia solo x-api-key e non header JWT per API v2.
• Usa include= su /parcels/{id} per ridurre payload e latenza.
• Logga sempre error, message, status HTTP e rate-limit headers.
• Gestisci 429 con retry progressivo e rispetto di retry_after_seconds.
• Tratta version dell'health come segnale di rollout dopo ogni deploy.
Fonti istituzionali
Tutti i dati sono tracciati fino all'ente pubblico di origine.





