-
Notifications
You must be signed in to change notification settings - Fork 6
API dell'app Trenitalia
Indice:
Autenticazione
Informazioni generali
Ricerca stazioni
Ricerca soluzioni di viaggio
Dettagli soluzione di viaggio
Recupero biglietti acquistati
Informazioni su un treno in tempo reale
Tabellone arrivi e partenze in stazione
Offerte in corso
Nota bene: in tutte le richieste presentate qui bisogna avere cura di sostituire AppVersion
con la versione dell'app che si sta usando e DeviceId
con un UUID univoco da utilizzare in tutte le richieste a partire dall'autenticazione.
Uno studio dettagliato sul processo di autenticazione può essere trovato nel post sul mio blog. Qui si riassume brevemente come procedere.
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
{
"challenges": {
"wl_antiXSRFRealm": {
"WL-Instance-Id": "e81721e39345450298539c176d"
},
"wl_deviceNoProvisioningRealm": {
"token": "5f1aa92653944e668d1f79df88"
}
}
}
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
WL-Instance-Id: e81721e39345450298539c176d
Authorization: {"wl_deviceNoProvisioningRealm":{"ID":{"token":"5f1aa92653944e668d1f79df88","app":{"id":"Trenitalia","version":"5.0.1.0004"},"device":{"id":"8d593fde-ea26-4191-a487-23ac82a7c36c","os":"6.0.1","model":"Nexus 5","environment":"android"},"custom":{}}}}
Nota: preservare i cookie impostati durante la prima richiesta.
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
WL-Instance-Id: e81721e39345450298539c176d
Nota: preservare i cookie impostati durante la prima richiesta.
Tutte le richieste dell'API sono POST al seguente endpoint:
https://gw71.mplat.trenitalia.it:444/Trenitalia50/apps/services/api/Trenitalia/android/query
Il corpo della richiesta richiede tre parametri: adapter
, procedure
e parameters
. Quest'ultimo è una stringa contenente dati in formato JSON. Le risposte sono file JSON puri o racchiusi in tag di tipo /*-secure-[payload]*/
con la seguente struttura:
{
"statusCode": 200,
"errors": [],
"isSuccessful": true,
"Envelope": {
"Body": {
"NOME_RISPOSTA": {
"Body": {
"CORPO_RISPOSTA"
},
"AdditionalInformation": {
"nil": "true"
}
}
},
"Header": {
"ResponseHeader": {
"MessageInfo": {
"nil": "true"
},
"mustUnderstand": "1",
"UnitOfWork": "101808532219417696"
}
}
},
"statusReason": "OK",
"responseHeaders": {
"Date": "Tue, 04 Sep 2018 15:56:23 GMT",
"Content-Length": "113306",
"Content-Type": "text\/xml; charset=utf-8",
"Server": "Microsoft-IIS\/7.5",
"X-Powered-By": "ASP.NET",
"x-SCR-APM": "09"
},
"warnings": [],
"responseTime": 211,
"totalTime": 215,
"info": []
}
La risposta in sé, quindi ciò che interessa, si trova in corrispondenza del placeholder "CORPO_RISPOSTA"
alla riga 9.
Notare che alcune chiavi identificano una lista oppure un dizionario a seconda delle necessità. Per esempio, quando si cerca un viaggio, le varie soluzioni vengono restituite sotto forma di lista di dizionari. Se però la soluzione trovata è una sola, viene restituito direttamente il dizionario di quella soluzione piuttosto che una lista con un solo elemento.
In caso di eccezione (per esempio se una ricerca non produce risultati, oppure se un treno è stato cancellato, ecc.) il parametro generale statusCode
è 500
e statusReason
spiega il motivo dell'errore, tuttavia il codice di risposta HTTP è sempre 200 OK
.
Le date sono in formato 1970-01-01T12:00:00+02:00
(nell'ordine: anno, mese, giorno, ora, minuto, secondo, offset rispetto a UTC in ore e minuti), oppure talvolta senza l'offset rispetto a UTC; tutte le durate sono in formato ISO 8601. Il valore null
in alcuni casi viene rappresentato come un dizionario {"nil": true}
. Molto spesso, ma non sempre, gli interi sono passati sotto forma di stringa. Prestate attenzione agli esempi.
-
adapter
:StationsAdapter
-
procedure
:GetStations
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"GetStationsRequest": {
"Body": {
"Name": "milano"
}
}
},
{
"extractOnlyItalianStations": false
}
]
-
Name
è il nome (anche parziale) della stazione da cercare; -
extractOnlyItalianStations
determina se i risultati devono essere solo stazioni italiane o meno.
{
"StationDetail": [
{
"name": "Milano Affori",
"longitude": "9.165794",
"stationcode": "830025005",
"latitude": "45.518497",
"favorite": 0,
"railwaycode": "83",
"zoomlevel": 1
}
]
}
-
adapter
:SearchAndBuyAdapter
-
procedure
:SearchTravels
-
paramters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"SearchTravelsRequest": {
"Body": {
"PagingCriteria": {
"StartIndex": 0,
"EndIndex": 9,
"SortDirection": null
},
"OriginStationId": "830008409",
"DestinationStationId": "830000219",
"DepartureDateTimeRange": {
"Start": "2018-09-05T05:00:00+02:00",
"End": null
},
"ArrivalDateTimeRange": null,
"ReturnDateTimeRange": null,
"ArrivalReturnDateTimeRange": null,
"IsReturn": false,
"Passengers": {
"PassengerQuantity": [
{
"Type": "Adult",
"Quantity": 1
},
{
"Type": "Child",
"Quantity": 0
}
]
},
"FidelityCardCode": null,
"PostSaleCriteria": null,
"TrainType": "All",
"MaxNumberOfChanges": "99",
"CompatibleFares": {
"OutwardSelectedFare": {
"ServiceId": "30005"
}
}
}
}
}
]
-
StartIndex
eEndIndex
indicano la porzione di soluzioni da mostrare. La prima ha indice 0; -
OriginStationId
è il codice della stazione di partenza; -
DestinationStationId
è il codice della stazione di arrivo; -
DepartureDateTimeRange
indica l'intervallo di date di partenza per cui mostrare soluzioni. Il parametroEnd
è semprenull
e viene ignorato; -
ArrivalDateTimeRange
indica l'intervallo di date di arrivo per cui mostrare soluzioni. Valgono le stesse considerazioni fatte sopra; -
ReturnDateTimeRange
: comeDepartureDateTimeRange
ma per il viaggio di ritorno; -
ArrivalReturnDateTimeRange
: comeArrivalDateTimeRange
ma per il viaggio di ritorno; -
IsReturn
indica se si sta cercando il viaggio di ritorno (come parte di un viaggio andata e ritorno); -
PassengerQuantity
indica la quantità di ogni tipologia di passeggero (adulti e bambini); -
TrainType
indica il tipo di treno da cercare; può esserenull
per tutti i tipi di treno,Frecce
, oRegional
per cercare solo treni regionali; -
MaxNumberOfChanges
indica il massimo numero di cambi. Se non si imposta un limite, l'app invia il valore di default"99"
; -
CompatibleFares
è presente solo se si sta cercando il viaggio di ritorno. Contiene il codice della soluzione selezionata per il viaggio di andata in modo da mostrare solo soluzioni compatibili (a livello tariffario).
{
"TravelSolution": [
{
"Changes": "0",
"DestinationStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"OriginStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"TotalJourneyTime": "PT4H5M",
"Type": "STANDARD",
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"PassengersCount": "0",
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"IsSaleable": true,
"SolutionId": "830008409,830000219,1809151500,549638,0,0,1809151411,830008409,830000219",
"Nodes": {
"SolutionNode": {
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"Train": {
"CategoryCode": "FR",
"CategoryName": "Frecciarossa",
"Number": "9638",
"Notifiable": true
},
"ArrivalStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"IsBER": false,
"DepartureStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"Id": "xb69a72a5-712c-4f35-99d2-343f80f7596c",
"JourneyDuration": "PT4H5M"
}
},
"MinLoyaltyPoints": "176.2",
"MinPrice": "98.00"
}
]
}
-
IsSaleable
indica se la soluzione è acquistabile; -
SolutionId
identifica univocamente la soluzione e può essere usato per ottenere ulteriori dettagli; -
Nodes
è la lista di treni che compongono la soluzione; -
MinLoyaltyPoints
è il numero minimo di punti che si accumulano sulla CartaFreccia se si acquista la soluzione; -
MinPrice
è il prezzo base della soluzione in euro.
-
adapter
:SearchAndBuyAdapter
-
procedure
:TravelSolutionDetails
-
parameters
:
[
{
"UnitOfWork": "214459924424663136",
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"TravelSolutionDetailsRequest": {
"Body": {
"SolutionId": "830008409,830000219,1809151500,549638,0,0,1809151411,830008409,830000219",
"IsRoundTrip": false,
"IsReturn": false,
"Passengers": {
"PassengerQuantity": [
{
"Type": "Adult",
"Quantity": 1
},
{
"Type": "Child",
"Quantity": 0
}
]
},
"CompatibleFares": null,
"FidelityCardCode": null,
"PostSaleCriteria": null,
"EvaluateAllOfferedService": false
}
}
}
]
I parametri sono analoghi a quelli per la ricerca delle soluzioni.
{
"TravelSolutionDetailsResponse": {
"Body": {
"Changes": "0",
"DestinationStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"OriginStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"TotalJourneyTime": "PT4H5M",
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"PassengersCount": "0",
"ParameterInfoList": {
"nil": true
},
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"IsSaleable": true,
"SolutionId": "xdfa36b90-09ee-4639-8c1e-29a23ac85ba2",
"OfferInfoList": {
"item": {
"offerInfo": {
"Name": "BASE",
"RequiresLoyaltyCardType": "1",
"TicketChangeAllowed": true,
"BookingChangeAllowed": true,
"TermsAndConditions": {
"TERMINI_E_CONDIZIONI": "DESCRIZIONE"
},
"Id": "1",
"ConcurLoyaltyPoints": true,
"RefundAllowed": true,
"RequiresLoyaltyCard": false
},
"offerId": "1"
}
},
"Nodes": {
"DetailedSolutionNode": {
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"Train": {
"CategoryCode": "FR",
"CategoryName": "Frecciarossa",
"Number": "9638",
"Notifiable": true
},
"Services": {
"ServiceBase": [
{
"Name": "STANDARD",
"Parameters": "",
"SeatMapEnable": true,
"BestPrice": true,
"Id": "30005",
"Capacity": {
"nil": true
},
"type": "Service",
"Offers": {
"Offer": {
"PassengerType": {
"nil": true
},
"Parameters": "",
"OfferId": "1",
"BestPrice": true,
"Availability": "Good",
"LoyaltyPoints": "176.20",
"Price": "98.00",
"MaterializedOnly": false,
"UndefinedPriceReason": {
"nil": true
}
}
}
}
]
},
"ArrivalStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"IsBER": false,
"DepartureStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"Id": "xe3a15637-6f56-4ee8-8925-5803f0c1bf5d",
"JourneyDuration": "PT4H5M"
}
},
"MinPrice": "98.00"
},
"AdditionalInformation": {
"nil": true
}
}
}
- Sono restituiti gli stessi parametri della ricerca di soluzioni con alcune informazioni aggiuntive;
-
OfferInfoList
è una lista delle offerte disponibili per il treno selezionato; -
TermsAndConditions
è un dizionario contenente diversi termini e condizioni riguardanti l'offerta, qui sono stati omessi per brevità; -
Nodes
è la lista di treni che compongono la soluzione, ma qui per ogni treno vengono mostrati i servizi disponibili (Services
); - per ogni servizio
type
èService
se si tratta di un singolo servizio,ServiceGroup
se si tratta di un gruppo di sottoservizi. In tal caso esisterà la chiaveSubServices
contenente la lista di sottoservizi. Per esempio, il servizio Business può avere i sottoservizi Area Silenzio e Salottino.
-
adapter
:PostSaleAdapter
-
procedure
:RecoveryTravel
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"RecoveryTravelRequest": {
"Body": {
"PNR": "ABCDEF",
"EntitlementId": null,
"Mail": "[email protected]",
"Name": "John",
"Surname": "Doe",
"RecoveryCode": "1234567890"
}
}
}
]
- Se il biglietto viene recuperato con PNR e indirizzo e-mail saranno popolati i campi
PNR
eMail
; - se il biglietto viene recuperato con nome, cognome e codice di recupero saranno popolati i campi
Name
,Surname
,RecoveryCode
; - i campi non popolati sono posti a
null
.
{
"Id": "1234567890",
"TravelSolutions": {
"PurchasedTravelSolution": [
{
"DestinationStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"TotalJourneyTime": "PT4H5M",
"SolutionId": "2",
"Changes": "0",
"Nodes": {
"PurchasedSolutionNode": {
"IsBER": false,
"Id": "1",
"DepartureStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"ArrivalStation": {
"Name": "TORINO PORTA NUOVA",
"Id": "219"
},
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"Train": {
"Notifiable": true,
"CategoryCode": "FR",
"Number": "9638",
"CategoryName": "Frecciarossa"
},
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"Price": "98.00",
"Tickets": {
"Ticket": [
{
"Coach": "1",
"EntitlementId": "123456789",
"MaterializedOnly": false,
"MachineReadableCode": "DATI_CODICE_AZTEC",
"type": "NationalTicket",
"Passenger": {
"Email": "[email protected]",
"BirthDate": "1970-01-01T00:00:00",
"IdPassenger": "123456789",
"FirstName": "John",
"Type": "Adult",
"LastName": "Doe",
"PhoneNumber": "3331234567",
"FidelityCardCode": {
"nil": true
}
},
"Seat": "1A",
"ticketPrice": "98.00",
"OfferId": "1",
"Service": {
"SeatMapEnable": true,
"Name": "01 BUSINESS",
"Id": "30002"
},
"PassengerNameRecord": "ABCDEF",
"ticketStatus": "ISSUED",
"LoyaltyPoints": "0",
"ReservationChangeCode": "123456"
}
]
},
"JourneyDuration": "PT4H5M"
}
},
"ArrivalDateTime": "2018-09-15T19:05:00+02:00",
"DepartureDateTime": "2018-09-15T15:00:00+02:00",
"AccountingDocument": {
"nil": true
},
"OriginStation": {
"Name": "ROMA TERMINI",
"Id": "8409"
},
"Price": "98.00",
"OfferInfoList": {
"item": {
"offerId": "1",
"offerInfo": {
"RequiresLoyaltyCardType": "0",
"TermsAndConditions": {
"TERMINI_E_CONDIZIONI": "DESCRIZIONE"
},
"Id": "1",
"RefundAllowed": {
"nil": true
},
"ConcurLoyaltyPoints": false,
"RequiresLoyaltyCard": false,
"Name": "BASE",
"TicketChangeAllowed": {
"nil": true
},
"BookingChangeAllowed": {
"nil": true
}
}
}
},
"PassengersCount": "1"
}
]
}
}
-
Id
corrisponde al codice di recupero della prenotazione fornito da Trenitalia; -
EntitlementId
è il codice del biglietto; -
MachineRedableCode
contiene i dati in base64 necessari per la generazione del codice Aztec; -
ReservationChangeCode
è il codice di cambio prenotazione; - gli altri parametri sono identici a quelli restituiti nella richiesta di dettagli di una soluzione.
-
adapter
:TrainRealtimeInfoAdapter
-
procedure
:TrainRealtimeInfo
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"TrainRealtimeInfoRequest": {
"Body": {
"Train": {
"Number": "9600",
"CategoryCode": null,
"CategoryName": null,
"Notifiable": null
},
"DepartureStationId": null,
"DepartureDate": null,
"ArrivalStationId": null
}
}
}
]
-
Number
è il numero del treno da cercare, come stringa; -
ArrivalStationId
è il codice della stazione di arrivo, facoltativo; -
DepartureStationId
è il codice della stazione di partenza, facoltativo; -
DepartureDate
è la data di partenza, facoltativa.
Gli altri parametri sembrano essere sempre ignorati.
{
"RealtimeTrainInfoWithStops": {
"ScheduledTrack": "9",
"Train": {
"CategoryCode": "FR",
"CategoryName": "FRECCIAROSSA",
"Number": "9600",
"Notifiable": true
},
"ActualTrack": "",
"DepartureStation": {
"Name": "ROMA TERMINI",
"Latitude": "41.900503",
"Longitude": "12.502027",
"Id": "8409"
},
"ScheduledArrival": "2018-09-05T10:05:00+02:00",
"LastReachedCheckPoint": "TORINO PORTA NUOVA",
"ScheduledDeparture": "2018-09-05T06:00:00+02:00",
"ScheduledDuration": "PT4H5M",
"Stops": {
"RealtimeTrainStop": [
{
"Station": {
"Name": "ROMA TERMINI",
"Latitude": "41.900503",
"Longitude": "12.502027",
"Id": "8409"
},
"Reached": true,
"StopType": "Departure",
"ActualInfo": {
"Departure": "2018-09-05T06:02:00+02:00",
"Arrival": {
"nil": true
},
"Track": ""
},
"ScheduledInfo": {
"Departure": "2018-09-05T06:00:00+02:00",
"Arrival": {
"nil": true
},
"Track": "9"
}
}
]
},
"ArrivalStation": {
"Name": "TORINO PORTA NUOVA",
"Latitude": "45.060971",
"Longitude": "7.677471",
"Id": "219"
},
"LastReachedCheckPointBase": {
"nil": true
},
"Delay": "PT12M",
"LastCheckPointTime": "2018-09-05T10:17:00",
"IsViaggiaTreno": true
}
}
- Le fermate possono essere di quattro tipi
Departure
,Arrival
,Stop
,Transit
. L'ultimo caso indica che il treno non ferma nella località in questione, ma ci transita solamente. Le fermate di tipoTransit
normalmente sono nascoste nell'interfaccia dell'applicazione.
-
adapter
:GetStationTimetables
-
procedure
:getStationTables
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c",
"StationId": "830001700",
"Type": "DEPARTURE"
},
null
]
-
StationId
è la stazione di cui si vuole ottenere il tabellone; -
Type
può essere"DEPARTURE"
o"ARRIVAL
.
Attenzione: per questa richiesta viene fornita la risposta integrale, che non include l'overhead descritto in Informazioni generali.
{
"trains": [
{
"scheduledTrack": "12",
"originId": "2593",
"departureTime": "11:50",
"number": "9728",
"destinationName": "Milano Centrale",
"actualTrack": "12",
"category": {
"name": "EUROSTAR ITALIA",
"code": "ES* FR"
},
"arrivalTime": "14:15",
"LastReachedCheckPointBase": "2018-09-15T14:20:00+02:00",
"destinationId": "1700",
"delay": "PT6M",
"originName": "Venezia S. Lucia",
"travelDuration": "2h 25m "
}
],
"isSuccessful": true
}
-
adapter
:PrecisionMarketingAdapter
-
procedure
:GetOffers
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": {
"UserId": null,
"Password": null,
"CustomerKey": ""
},
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"GetOffersRequest": {
"Body": {
"ContextPage": "HP",
"NumberOfChoices": null
}
}
}
]
- Questa richiesta riguarda le offerte che vengono mostrate sulla pagina principale dell'app.
{
"Offers": {
"PmOffer": {
"BenefitDuration": "0",
"ActionCode": {
"nil": "true"
},
"DescHowItWorks": {
"nil": "true"
},
"ChoiceDuration": {
"nil": "true"
},
"ChoiceId": "",
"Images": {
"PmImage": {
"Type": "HP",
"Image": "BLOB_IMMAGINE",
"Id": "DEFAULT"
}
},
"Title": {
"nil": "true"
},
"DescShort": {
"nil": "true"
},
"Priority": "0",
"EndDate": "0001-01-01T00:00:00",
"Url": "http://www.trenitalia.com/tcom/Offerte-e-servizi/Promo",
"ContextPage": "DEFAULT",
"ClusterActionCode": {
"nil": "true"
},
"AppActionCode": "DEFAULT",
"IsGeneric": "true",
"DescTermsOfUse": {
"nil": "true"
},
"DescLong": {
"nil": "true"
}
}
}
}
-
Image
contiene l'immagine da mostrare codificata in base64.