# MobilityLens API v1

Copertura attuale: Città metropolitana di Torino, Piemonte. I filtri territoriali non possono ampliare questo perimetro. Il resto d’Italia non è incluso.

## Inizia in tre passi

1. Accedi alla piattaforma in /prodotti/accesso e controlla il saldo token.
2. Per usare l’explorer apri /prodotti/api. Per un’integrazione usa il token di accesso della tua sessione Supabase nell’header Authorization: Bearer ACCESS_TOKEN.
3. Chiama prima /api/v1/projects/facets per conoscere comuni e categorie, poi esegui la ricerca.

Non inserire password, credenziali database, service keys o email nella URL. Un access token è una credenziale di accesso; i token del saldo sono crediti di utilizzo e sono una cosa diversa. Un access token scaduto richiede il rinnovo della sessione tramite il client Supabase.

## Esempio

```bash
curl 'https://YOUR_PLATFORM_HOST/api/v1/projects?comune=Torino&limit=10' \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'X-Request-Id: torino-search-001'
```

Sostituisci YOUR_PLATFORM_HOST con l’origine della tua installazione (in locale http://localhost:3000). Nel browser della piattaforma viene usata la sessione automaticamente. Integrazioni esterne: chiamate server-to-server con HTTPS e Bearer; nessun CORS aperto a siti terzi.

## Endpoint

| Metodo e percorso | Uso | Costo |
| --- | --- | --- |
| GET /api/v1/projects | Cerca progetti | 1 credito per record restituito |
| GET /api/v1/projects/facets | Comuni, macrocategorie, microcategorie e stati | Gratis |
| GET /api/v1/funding | Finanziamenti, date e riepiloghi | 1 credito per record restituito |
| GET /api/v1/tokens | Il tuo saldo | Gratis |
| GET /api/v1/openapi | Specifica completa JSON | Pubblico e gratis |

PriceLens non è abilitato in questa versione Torino: il modello esistente usa riferimenti Milano/Roma. Nessuna stima viene addebitata dal nuovo endpoint. Le altre pagine PriceLens non fanno parte di questa migrazione.

## Filtri essenziali

Progetti: comune, macrocategory, normalized_project_category, project_status, keyword, limit, offset oppure cursor. region=Piemonte e province=Torino sono applicati dal server anche se omessi. Macrocategoria e microcategoria provengono dalla tassonomia dei progetti e sono in italiano; sono dedicate ai progetti. Area d’intervento e natura dell’investimento rimangono campi separati della fonte. Usa i valori restituiti da facets senza tradurli. Le categorie con virgole vanno passate ripetendo il parametro, non dividendo il testo.

Funding: stessi filtri, più start_date_from/start_date_to, finish_date_from/finish_date_to (YYYY-MM-DD), timeline_basis=start_date oppure finish_date, timeline_mode=all/funded/future. Sono disponibili anche bbox, cerchio e poligono: restano sempre intersecati con i dati Torino. data.records contiene la pagina; data.summary e data.series.by_date i riepiloghi della selezione.

Le opzioni complete, i limiti e i formati sono descritti nella specifica /api/v1/openapi.

## Risposta, pagine e download

Le ricerche restituiscono data, meta.pagination e usage. usage.chargedTokens è il costo della richiesta; usage.remainingTokens è il saldo aggiornato. meta.pagination.next_cursor permette di proseguire con gli stessi filtri. La dimensione normale è 10, massimo 250; un nuovo export con download_format ammette fino a 5000 record. Ogni nuova pagina o export è una richiesta a pagamento. Il risultato HTTP rimane un oggetto JSON: il browser converte data in CSV, JSON o GeoJSON. Gli export mantengono macro/microcategoria separate dai campi della fonte. GeoJSON conserva le geometrie disponibili e usa geometry=null per i progetti senza coordinate, senza scartare record.

Anche le risposte lette dalla cache del server consumano crediti. Salvare localmente risultati Funding già ricevuti non avvia un nuovo addebito. Un risultato vuoto costa zero. Non usare HEAD per interrogare endpoint a pagamento: restituisce 405 senza addebito.

## Errori e tentativi ripetuti

| Stato | Significato |
| --- | --- |
| 400 | Filtri errati, territorio non supportato o identità nella URL |
| 401 | Accedi o rinnova la sessione |
| 403 | Crediti insufficienti |
| 409 | X-Request-Id già elaborato; nessun ulteriore addebito, nessuna riproduzione della risposta precedente |
| 429 | Troppe richieste: attendi Retry-After |
| 503 / 504 | Servizio indisponibile / query troppo lenta |

Gli errori hanno forma {"error":{"code":"...","message":"..."}}. X-Request-Id è facoltativo, lungo 1–128 caratteri alfanumerici, trattini, underscore o due punti. Usa un identificatore nuovo per ogni operazione. Dopo una risposta incerta puoi riprovare con lo stesso identificatore: 409 significa che l’addebito risulta già registrato. Non generarne uno nuovo automaticamente: sarebbe una nuova richiesta a pagamento. Le risposte non vengono archiviate per replay.

Limite applicativo: 60 richieste al minuto per utente, condiviso fra questi endpoint e gli alias. Se KV è configurato il contatore è distribuito; altrimenti il limite è per processo. La contabilizzazione dei crediti resta atomica nel database.

## Migrazione

Usa /api/v1 e Bearer/sessione. Le vecchie URL widget dell’explorer restano alias protetti. /api/projects/{macrocategory} è ritirato: usa /api/v1/projects?macrocategory=VALORE_DA_FACETS. /api/tokens?email=... non è più supportato. Il vecchio download PDF generale ora restituisce questa guida Markdown aggiornata.
