-
Notifications
You must be signed in to change notification settings - Fork 3
Nuove API Trenitalia lefrecce.it
Pagina work in progress per documentare le nuove API lefrecce.it, quelle vecchie (o legacy ;) ) sono state dismesse quando Trenitalia ha unificato il sito mobile con quello desktop. Tutte le risposte dell'api sono in formato json, i campi di cui non sono riuscito a capire l'utilizzo sono stati omessi.
In tutte le richieste POST è necessario settare l'Header HTTP Content-Type: application/json
, se il client utilizzato non lo setta in maniera automatica.
Ho deciso di redarre questa wiki perchè, nonostante l'immensità di app non ufficiali sui treni italiani là fuori, quando ho dovuto svilupparne una io su internet non c'era uno straccio di indizio su dove partire. Spero così che se qualcuno si troverà in futuro nella mia stessa situazione non rifarà inutilmente lavoro che è stato già fatto da altri e parta direttamente dal contenuto di questa pagina. Se utilizzi i dati contenuti in questa pagina per sviluppare software per favore includi il link alla repo nei riconoscimenti, in modo che tutti quelli interessati possano usufruire di queste informazioni (e se ti va scrivimi una riga a s(punto)dassi(punto)pub(at)gmail(punto)com, oppure Say Thanks! , così almeno saprò che non è stato lavoro inutile).
Se ti interessa Italo, qui c'è una wiki equivalente
L'url per cercare soluzioni di viaggio è:
POST: https://www.lefrecce.it/Channels.Website.BFF.WEB/website/ticket/solutions
Il corpo della richiesta post è il seguente oggetto JSON:
{
"departureLocationId": (intero) Il codice della stazione di partenza, come restituito dall'autocompletamento stazione (vedi sotto)
"arrivalLocationId": (intero) Il codice della stazione di arrivo,
"departureTime": (stringa) La data/ora di partenza in formato ISO date,
"returnDepartureTime": (stringa, opzionale) Se specificato, ritorna soluzioni A/R con la data/ora di ritorno indicata, in formato ISO date,
"adults": (intero) Il numero di adulti per cui cercare il viaggio,
"children": (intero) Il numero di bambini per cui cercare il viaggio,
"criteria": {
"frecceOnly": (booleano) Se cercare solo soluzioni Alta Velocità,
"regionalOnly": (booleano) Se cercare solo soluzioni con regionali,
"noChanges": (booleano) Se cercare solo soluzioni in cui non sono previsti cambi,
"order": (stringa) Il criterio con cui ordinare l'array di soluzioni di risposta. Può valere "DEPARTURE_DATE", "ARRIVAL_DATE", "FASTEST", "CHEAPEST",
"limit": (intero) Massimo numero di soluzioni da ritornare. Di default è 10,
"offset": (intero, opzionale) Se specificato, ritorna le soluzioni a partire dalla n-esima trovata fino alla n+limit-esima. In pratica sposta in avanti di n soluzioni dopo la departure date la finestra di ricerca
},
"advancedSearchRequest": {
"bestFare": (booleano) A quanto ho capito, se true nasconde le soluzioni più costose e ritorna solo le più convenienti. La logica di filtraggio è un po' opaca', consiglio di lasciarlo a false.
}
}
Query d'esempio:
{
"departureLocationId": 830001700,
"arrivalLocationId": 830008409,
"departureTime": "2022-12-07T15:00:00.000+02:00",
"adults": 1,
"children": 0,
"criteria": {
"frecceOnly": false,
"regionalOnly": false,
"noChanges": false,
"order": "DEPARTURE_DATE",
"limit": 10,
"offset": 0
},
"advancedSearchRequest": {
"bestFare": false
}
}
Oggetto con i seguenti campi:
searchId: id univoco ricerca (da passare ad altre chiamate)
cartId: id univoco carrello (da passare ad altre chiamate)
solutions: array di oggetti, uno per ogni soluzione trovata
[
solution: oggetto che descrive la soluzione
(
id: (stringa) Identificatore univoco della soluzione di viaggio
origin: (stringa) Nome della stazione di partenza
destination: (stringa) Nome della stazione di arrivo
departureTime: (stringa) Ora di partenza alla stazione di origine, formato ISO date
arrivalTime: (stringa) Ora di arrivo alla stazione di destinazione, formato ISO date
duration: (stringa) durata del viaggio in formato human-readable
status: (stringa) vale "SALEABLE" se il biglietto è acquistabile, "INHIBITED" se sono finiti i posti, "NOT_SALEABLE" se non è acquistabile per altri motivi (e.g. la partenza è imminente e non è più possibile comprare il biglietto)
price: oggetto che descrive il prezzo della soluzione (è il prezzo più basso tra tutte le classi di servizio disponibili per la soluzione)
(
currency: (stringa) La valuta in cui è espresso il prezzo, "€" per Euro
amount: (float) Prezzo della soluzione
)
nodes: array di oggetti, uno per ogni treno nella soluzione
[
origin: (stringa) Stazione di partenza del singolo treno
destination: (stringa) Stazione di arrivo del singolo treno
departureTime: (stringa) Data/ora di partenza dalla stazione di cambio/destinazione singolo treno, formato ISO date
arrivalTime: (stringa) Data/ora di arrivo alla stazione di cambio/destinazione del singolo treno, formato ISO date
train: oggetto che descrive il treno che copre il segmento di soluzione
(
trainCategory: (stringa) categoria del treno (e.g. Frecciarossa, Frecciargento, Regionale..)
name: (stringa) Codice numerico del treno
acronym: (stringa) Tipologia del treno abbreviata (ex: FR per FRECCIAROSSA)
)
]
trains: array di oggetti, uno per ogni treno nella soluzione. E' la copia di tutti gli oggetti nodes[i].train, esposta a livello più alto nella gerarchia JSON. Il formato è quindi identico a train (vedi sopra)
)
messages: array oggetti che contengono avvertimenti per l'utente riguardo la soluzione. Per esempio, se il biglietto non è acquistabile, contiene il motivo di tale restrizione.
(
message: (stringa) Messaggio di avvertimento
status: (stringa) "Gravità" del messaggio, "INFO" o "WARNING"
)
grids: oggetto che contiene il dettaglio dei prezzi (vedi sezione apposita in questa pagina)
]
Questa query restituisce le stazioni il cui nome contiene la stringa passata come parametro
GET: https://www.lefrecce.it/Channels.Website.BFF.WEB/website/locations/search?name=[NAME]&limit=[LIMIT]
[NAME]: stringa con i caratteri della stazione, impostando nella chiamata i caratteri \\ verranno estrapolate tutte le stazioni
[LIMIT]: numero massimo di stazioni da ritornare. Di default è 10, se omesso ritorna TUTTE quelle che corrispondono alla ricerca
*Impostando come [NAME] i caratteri \\ e come [LIMIT] un numero molto alto come 100000 verranno estrapolate tutte le stazioni
Array di max. [LIMIT]
oggetti con i seguenti campi:
name: (stringa) Il nome completo della stazione,
id: (intero) L'id stazione, è quello che va usato per lanciare la query sovrastante
displayName: (stringa) Uguale a "name" (?),
centroidId: (intero) Entra in gioco se una città ha più stazioni, vedi sotto
Attenzione: Se una città ha più stazioni, si può scegliere di non specificare la stazione di partenza ma la città stessa. Ad esempio, una ricerca per "Milano" con questa query ritorna una stazione fittizia con "name" : "Milano (Tutte Le Stazioni)"
e poi le varie stazioni in città. Cercando soluzioni con l'id di Milano (Tutte Le Stazioni)
si otteranno soluzioni che partono da centrale, porta garibaldi, rogoredo, cadorna ecc.
Il campo centroidId
contiene sempre l'id della stazione fittizia della città. Vale null
se la città ha un'unica stazione.
Il dettaglio dei prezzi viene ritornato nella chiamata /solutions, ma essendo un argomento abbastanza esteso viene affrontato in questa sezione.
Ogni oggetto nell'array solutions
contiene il campo grids
, che a sua volta contiene proprio l'elenco dei biglietti acquistabili per la soluzione. Il concetto di grid deriva dal fatto che nella grafica del sito viene presentata una griglia di opzioni di acquisto disponibili, ad ogni colonna corrisponde una classe di servizio a bordo treno mentre ad ogni riga corrisponde un'offerta (standard, economy, young, senior..). In particolare, grids
è un array in cui ogni oggetto corrisponde a una tratta (treno) nella soluzione. Ogni oggetto è così composto:
selectedOfferId: (intero) codice dell'offerta selezionata di default
selectedServiceId: (intero) codice della classe di servizio selezionata di default (di solito è la più conveniente tra le disponibili rimaste acquistabili)
services: array di oggetti, uno per classe di servizio
(
id: (intero) codice del servizio
name: (stringa) nome del servizio
description: (stringa) descrizione testuale del servizio
minPrice: oggetto contenente il prezzo più basso tra le varie offerte per la classe di servizio
bestOfferId: (intero) codice dell'offerta più conveniente tra quelle nell'array offers
offers: array di offerte per la classe di servizio
[
offerId: (intero) codice dell'offerta
name: (stringa) nome dell'offerta
description: (stringa) descrizione testuale dell'offerta
serviceId: (intero) codice della classe di servizio (ovvero il campo id dell'oggetto padre)
serviceName: (stringa) nome della classe di servizio (ovvero il campo name dell'oggetto padre)
price: oggetto contente il prezzo dell'offerta. Vale null se non acquistabile
availableAmount: (intero) numero di biglietti rimasti acquistabili. Se i posti sul treno non sono numerati, vale 32767 (2^15 -1)
status: (stringa) "SALEABLE" se il biglietto è acquistabile, "SOLD_OUT" se i posti sono finiti
canRefund: (booleano) true se il biglietto è rimborsabile
]
)
I contenuti di questa repo sono a solo scopo informativo e frutto di studi personali, le informazioni fornite dal sito non sono pubblicamente accessibili.
Se sviluppate un'app con queste api non dimenticate di ricordare ai vostri utenti femminili che l'8 marzo avranno diritto a un'esclusiva caramella gelee al limone!