Skip to content

Commit d28eb98

Browse files
aborrusoclaude
andcommitted
docs: add reverse-engineered OpenAPI spec for IGM Verto Online API
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent a7042a1 commit d28eb98

3 files changed

Lines changed: 309 additions & 0 deletions

File tree

LOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# LOG
22

3+
## 2026-06-09 — docs: spec OpenAPI dell'API IGM (reverse engineering)
4+
5+
- Aggiunta `docs/openapi.yaml`: documentazione OpenAPI 3.1.0 **non ufficiale** dell'endpoint IGM Verto Online, ricostruita dal manuale (`ref/`) e dal codice. Modella fedelmente il servizio RPC: **un solo path POST** discriminato da `richiesta` (`info`/`conversione`), **errori in HTTP 200** con `stato: errore`, `utente`/`chiave` obbligatori ma ignorati, ordine assi e-prima, limite 32000, no conversioni stesso datum. Esempi nominati dal manuale (typo `"x"``"n"` corretto). `security: []` (servizio senza auth).
6+
- Validata con `openapi-spec-validator` (OK) e `redocly lint` (solo warning 4xx, lasciato di proposito: il servizio non usa 4xx).
7+
- README: nuova sezione "API del servizio IGM" che linka la spec.
8+
39
## 2026-06-09 — docs: riferimento CLI completo
410

511
- Aggiunta `docs/cli.md`: guida completa a tutti i comandi e opzioni (opzioni globali, codici di uscita, comportamento `--skip-invalid`, gotcha ordine assi, output strutturato in `batch`).

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,12 @@ Nessuna. Il servizio è libero e gratuito; i campi `utente`/`chiave` richiesti d
149149
- La griglia IGM copre l'Italia e i mari circostanti: coordinate fuori copertura vengono rifiutate (usa `detect`/`inspect` per controllare assi e EPSG).
150150
- **Il servizio IGM è gratuito e pubblico: non abusarne.** Quando un job supera le **32000 coordinate** (il limite per richiesta) e viene quindi spezzato in più blocchi, openverto mette una pausa di **2 secondi tra un blocco e l'altro** (`--throttle`, o `set_throttle()` nella libreria). Una conversione singola (≤32000) non viene mai rallentata. `--throttle 0` disabilita la pausa, ma usalo con criterio.
151151

152+
## API del servizio IGM
153+
154+
openverto si appoggia all'API pubblica di IGM Verto Online, che non ha una
155+
documentazione OpenAPI ufficiale. Ne abbiamo ricostruita una **non ufficiale**
156+
per reverse engineering, leggibile e con esempi: [`docs/openapi.yaml`](docs/openapi.yaml).
157+
152158
## Crediti
153159

154160
Servizio dati: [IGM Verto Online](https://igmi.esercito.difesa.it/servizi/verto-online/), Istituto Geografico Militare.

docs/openapi.yaml

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
openapi: 3.1.0
2+
3+
info:
4+
title: IGM Verto Online API
5+
version: "1.0.0"
6+
summary: Conversione di coordinate tra i sistemi di riferimento italiani.
7+
description: |
8+
Documentazione **non ufficiale** dell'API del servizio
9+
[IGM Verto Online](https://igmi.esercito.difesa.it/servizi/verto-online/)
10+
dell'Istituto Geografico Militare, ricostruita per reverse engineering a
11+
partire dal manuale ufficiale e dall'osservazione delle richieste reali.
12+
13+
Il servizio converte coordinate tra tutti i sistemi di riferimento italiani
14+
(Roma40/Monte Mario, ED50, IGM95, ETRS89, RDN2008) appoggiandosi alle
15+
griglie NTv2 ufficiali, **senza doverle installare in locale**.
16+
17+
## Modello dell'API
18+
19+
Il servizio espone **un solo endpoint** che riceve richieste POST in JSON e
20+
risponde in JSON. Non è un'API REST con più risorse: il tipo di operazione è
21+
scelto dal campo `richiesta` nel corpo della richiesta, che vale `info`
22+
(elenco dei sistemi supportati) oppure `conversione` (trasformazione di un
23+
insieme di coordinate).
24+
25+
## Punti da conoscere
26+
27+
- **Ordine degli assi: `e` (est) prima, `n` (nord) dopo.** Per i sistemi
28+
proiettati `e` è l'easting e `n` il northing (in metri); per i sistemi
29+
geografici `e` è la **longitudine** e `n` la **latitudine** (in gradi
30+
sessadecimali). Attenzione: per i CRS geografici questo è l'inverso
31+
dell'ordine lat/long del registro EPSG — la longitudine va sempre per prima.
32+
- **Gli errori arrivano con HTTP 200.** Un fallimento applicativo non usa i
33+
codici di stato HTTP 4xx/5xx: la risposta è comunque `200 OK` e contiene
34+
`"stato": "errore"`. Vanno distinti dalla forma di successo leggendo il
35+
corpo.
36+
- **`utente` e `chiave` sono obbligatori ma ignorati.** Non sono credenziali
37+
di autenticazione: il servizio li richiede ma non li verifica. Vanno
38+
riempiti con qualsiasi valore segnaposto.
39+
- **Limite di 32000 coordinate per richiesta** (`maxCoord`). Job più grandi
40+
vanno spezzati in più richieste dal client.
41+
- **Le conversioni tra sistemi con lo stesso datum non sono supportate**
42+
(es. da `RDN2008 2D geo` a `RDN2008 / TM32`) e vengono rifiutate.
43+
- **Copertura della griglia: Italia e mari circostanti.** Coordinate fuori
44+
copertura vengono rifiutate dal motore PROJ sottostante.
45+
contact:
46+
name: IGM — Istituto Geografico Militare
47+
url: https://igmi.esercito.difesa.it/servizi/verto-online/
48+
license:
49+
name: Servizio pubblico e gratuito IGM
50+
url: https://igmi.esercito.difesa.it/servizi/verto-online/
51+
52+
servers:
53+
- url: https://igmi.esercito.difesa.it
54+
description: Endpoint di produzione IGM Verto Online
55+
56+
# Il servizio non richiede autenticazione: i campi utente/chiave sono segnaposto.
57+
security: []
58+
59+
paths:
60+
/porta-magna/wps/volapi:
61+
post:
62+
operationId: volapi
63+
summary: Endpoint unico (info o conversione)
64+
description: |
65+
Unico endpoint del servizio. L'operazione effettiva è determinata dal
66+
campo `richiesta` nel corpo:
67+
68+
- `richiesta: "info"` → elenco dei sistemi di riferimento supportati e
69+
numero massimo di coordinate per richiesta.
70+
- `richiesta: "conversione"` → trasformazione di un vettore di
71+
coordinate da `inEpsg` a `outEpsg`.
72+
73+
La risposta è sempre `200 OK`, anche in caso di errore applicativo:
74+
controllare il campo `stato` (presente nelle risposte di conversione) o
75+
la forma del corpo per distinguere successo ed errore.
76+
requestBody:
77+
required: true
78+
content:
79+
application/json:
80+
schema:
81+
oneOf:
82+
- $ref: "#/components/schemas/InfoRequest"
83+
- $ref: "#/components/schemas/ConversioneRequest"
84+
discriminator:
85+
propertyName: richiesta
86+
mapping:
87+
info: "#/components/schemas/InfoRequest"
88+
conversione: "#/components/schemas/ConversioneRequest"
89+
examples:
90+
info:
91+
summary: Richiesta dei sistemi supportati
92+
value:
93+
richiesta: info
94+
conversione:
95+
summary: Conversione Monte Mario (4265) → RDN2008 (6706)
96+
value:
97+
richiesta: conversione
98+
utente: openverto
99+
chiave: openverto
100+
inEpsg: 4265
101+
outEpsg: 6706
102+
coordinate:
103+
- { e: 7.000, n: 37.000 }
104+
- { e: 12.000, n: 42.000 }
105+
- { e: 16.000, n: 45.000 }
106+
responses:
107+
"200":
108+
description: |
109+
Risposta dell'operazione. La forma dipende dalla richiesta e
110+
dall'esito; **anche gli errori applicativi usano questo stato HTTP**.
111+
content:
112+
application/json:
113+
schema:
114+
oneOf:
115+
- $ref: "#/components/schemas/InfoResponse"
116+
- $ref: "#/components/schemas/ConversioneSuccessResponse"
117+
- $ref: "#/components/schemas/ErrorResponse"
118+
examples:
119+
info:
120+
summary: Risposta a una richiesta info
121+
value:
122+
maxCoord: 32000
123+
srsSupportati:
124+
- { epsg: 4265, descrizione: "Monte Mario" }
125+
- { epsg: 3003, descrizione: "Monte Mario / Italy zone 1" }
126+
- { epsg: 3004, descrizione: "Monte Mario / Italy zone 2" }
127+
- { epsg: 4230, descrizione: "ED50" }
128+
- { epsg: 23032, descrizione: "ED50 / UTM zone 32N" }
129+
- { epsg: 6706, descrizione: "RDN2008" }
130+
- { epsg: 7794, descrizione: "RDN2008 / Italy Zone EN" }
131+
conversione-successo:
132+
summary: Conversione riuscita
133+
value:
134+
stato: successo
135+
coordinate:
136+
- { e: 6.9996175526, n: 37.0006110152 }
137+
- { e: 11.9997804498, n: 42.0006477023 }
138+
- { e: 15.9999259776, n: 45.0006501430 }
139+
errore-campo-mancante:
140+
summary: Errore — manca un attributo della coordinata
141+
value:
142+
stato: errore
143+
dove: "coordinate, elemento n. 2"
144+
messaggio: "Manca l'elemento 'n'"
145+
errore-fuori-griglia:
146+
summary: Errore — coordinata fuori dalla copertura della griglia
147+
value:
148+
stato: errore
149+
dove: "Proj"
150+
messaggio: "Coordinate outside grid"
151+
152+
components:
153+
schemas:
154+
155+
InfoRequest:
156+
type: object
157+
description: Richiesta dell'elenco dei sistemi di riferimento supportati.
158+
required: [richiesta]
159+
properties:
160+
richiesta:
161+
type: string
162+
const: info
163+
description: Discriminatore dell'operazione. Per questa richiesta vale `info`.
164+
examples:
165+
- richiesta: info
166+
167+
ConversioneRequest:
168+
type: object
169+
description: |
170+
Richiesta di conversione di un vettore di coordinate da un sistema di
171+
riferimento a un altro.
172+
required: [richiesta, utente, chiave, inEpsg, outEpsg, coordinate]
173+
properties:
174+
richiesta:
175+
type: string
176+
const: conversione
177+
description: Discriminatore dell'operazione. Per questa richiesta vale `conversione`.
178+
utente:
179+
type: string
180+
description: |
181+
Obbligatorio ma **ignorato** dal servizio: non è un'autenticazione.
182+
Riempire con un valore segnaposto qualsiasi.
183+
example: openverto
184+
chiave:
185+
type: string
186+
description: |
187+
Obbligatorio ma **ignorato** dal servizio: non è una chiave di
188+
autenticazione. Riempire con un valore segnaposto qualsiasi.
189+
example: openverto
190+
inEpsg:
191+
type: integer
192+
description: Codice EPSG del sistema di riferimento di **origine**.
193+
example: 4265
194+
outEpsg:
195+
type: integer
196+
description: |
197+
Codice EPSG del sistema di riferimento di **destinazione**. Deve
198+
appartenere a un **datum diverso** da `inEpsg`: le conversioni tra
199+
sistemi con lo stesso datum non sono supportate.
200+
example: 6706
201+
coordinate:
202+
type: array
203+
description: |
204+
Vettore delle coordinate da convertire. Al massimo `maxCoord`
205+
(32000) elementi per richiesta.
206+
minItems: 1
207+
maxItems: 32000
208+
items:
209+
$ref: "#/components/schemas/Coordinate"
210+
211+
Coordinate:
212+
type: object
213+
description: |
214+
Una coppia di coordinate. `e` (est) per prima, `n` (nord) per seconda.
215+
Per i sistemi geografici `e` è la longitudine e `n` la latitudine, in
216+
gradi sessadecimali; per i sistemi proiettati sono easting e northing in
217+
metri.
218+
required: [e, n]
219+
properties:
220+
e:
221+
type: number
222+
description: Est — easting (m) oppure longitudine (gradi sessadecimali).
223+
example: 12.000
224+
n:
225+
type: number
226+
description: Nord — northing (m) oppure latitudine (gradi sessadecimali).
227+
example: 42.000
228+
229+
InfoResponse:
230+
type: object
231+
description: Risposta a una richiesta `info`.
232+
required: [maxCoord, srsSupportati]
233+
properties:
234+
maxCoord:
235+
type: integer
236+
description: Numero massimo di coordinate convertibili in una singola richiesta.
237+
example: 32000
238+
srsSupportati:
239+
type: array
240+
description: Elenco dei sistemi di riferimento supportati dal servizio.
241+
items:
242+
$ref: "#/components/schemas/Srs"
243+
244+
Srs:
245+
type: object
246+
description: Un sistema di riferimento supportato.
247+
required: [epsg, descrizione]
248+
properties:
249+
epsg:
250+
type: integer
251+
description: Codice EPSG del sistema di riferimento.
252+
example: 4265
253+
descrizione:
254+
type: string
255+
description: Descrizione testuale del sistema di riferimento.
256+
example: Monte Mario
257+
258+
ConversioneSuccessResponse:
259+
type: object
260+
description: |
261+
Risposta a una conversione riuscita. Il vettore `coordinate` ha la
262+
stessa lunghezza e lo stesso ordine di quello in ingresso.
263+
required: [stato, coordinate]
264+
properties:
265+
stato:
266+
type: string
267+
const: successo
268+
description: Esito dell'operazione. In caso di successo vale `successo`.
269+
coordinate:
270+
type: array
271+
description: Coordinate convertite nel sistema di destinazione, nello stesso ordine dell'input.
272+
items:
273+
$ref: "#/components/schemas/Coordinate"
274+
275+
ErrorResponse:
276+
type: object
277+
description: |
278+
Risposta di errore applicativo. **Restituita comunque con HTTP 200**:
279+
l'errore si riconosce dal campo `stato` uguale a `errore`.
280+
required: [stato, messaggio]
281+
properties:
282+
stato:
283+
type: string
284+
const: errore
285+
description: Esito dell'operazione. In caso di errore vale `errore`.
286+
dove:
287+
type: string
288+
description: |
289+
Indicazione testuale del punto in cui si è verificato l'errore.
290+
Esempi osservati: `coordinate, elemento n. 2` (problema su una
291+
coordinata specifica) e `Proj` (rifiuto dal motore PROJ, tipicamente
292+
una coordinata fuori dalla copertura della griglia).
293+
example: "Proj"
294+
messaggio:
295+
type: string
296+
description: Descrizione testuale dell'errore.
297+
example: "Coordinate outside grid"

0 commit comments

Comments
 (0)