Migration Guide - Rail APIs v1 to v2
Table of contents
- AssignedTicketPrice in RefundOption made optional
- RefundedTicketsBalance in TransactionContract made optional
- Charges in TransactionContract made optional, additional charge type added
- PUT TravelDocuments
- GET TravelDocuments - new service
- GET Order - mandatory _links response element
- GET Order - added contact id and contacts list in order
- Flexibility in Transport Tariff made optional
- Flexibilities in Transport Tariff removed
- AssignedTicketsPrice in ExchangeOption made optional
- DiscountCriteria in PassengerCriteria and RailCardOwnerCriteria removed
- Discount added to PassengerCriteria and RailCardOwnerCriteria
- Loyalty cards and corporate discounts in NamedPassenger are replaced with generic discounts
- Changed ExchangeOfferCriteria to use SearchCriteriaForExchange instead of SearchCriteria
- Changed ExchangeOffers to use ExchangeSchedule instead of Schedule
- POST exchangeContracts - offer ID in request moved to offers array
- offerCriteria in POST /orders renamed to offers
- LocationId in PlaceInTime made optional
- In an Offer, seatReservationOptions might not be returned
- In a TransportProduct, priceBreakdown might not be returned
- In an Order, elements namedPassengers, journeys and orderItems might not be returned
- In an OrderItem, elements journeys and transportProducts might not be returned
- In a DictionaryDescriptionEntry, details might not be returned
- Dictionaries can be searched for entries with specific code
- ArrivalLocationId and DepartureLocationId removed
- Offers moved from OffersRsContent to OffersRsContent.Schedules.Journeys.Sections
- Journeys element removed from Offer
- Refundable and exchangeable in FlexibilityProperties made optional
- Moved PaymentCriteria from book to preBook
- Book request extended with bookingPaymentDetails
- PaymentCriteria
- PaymentForm
- PaymentDetails
- A list of journeys can be empty
- Notification response can contain notificationId
- Rail card code deprecated, replaced by railCardCodeText
- Add primaryPassenger to FulfillmentOptions
- NamedPassenger in Prebook can contain passengerTravelDocument, citizenShip, gender and middleName
- deliveryCode removed from OfferCriteria in PreBookRq
- orderSplit added in offers' FulfillmentOptions
- orderSplit added in PreBookRq
- viewSplit added in OrderLinks
- details added in ResourceLink
AssignedTicketPrice in RefundOption made optional
This element is now optional and might not appear in GET Order response. It will not be returned for Trainline reservations.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
"compatibleRefundOptions": [
{
"refundOptionId": "eyJvcmRlcklkIjoiM2I0NTc",
"orderItemIds": [
"op~U~aae95146-2198-4472-aa86-93bfb565bcfb"
],
"assignedTicketsPrice":{
"amount":"100",
"currency":"EUR"
}
}
]
RefundedTicketsBalance in TransactionContract made optional
This element is now optional and may not appear in responses. It will not be returned for Trainline refunds.
Impacted services:
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/refundContracts
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeContracts
Example:
"refundContractOptions": [
{
"transactionContractId": "5MZODHFA",
"transactionContractStatus": "ESTIMATED",
"refundedTicketsBalance": {
"price": {
"amount": "142.00",
"currencyCode": "EUR"
}
},
"paymentBalances": [
{
"transactionType": "CREDIT",
"amount": {
"amount": "142.00",
"currencyCode": "EUR"
}
}
]
}
]
Charges in TransactionContract made optional, additional charge type added
This element is now optional and may not appear in responses.
A charge with REFUND_FEE code will not be returned for Trainline
reservations.
A charge of ADMIN_FEE can appear if there are additional administration
fees.
Impacted services:
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/refundContracts
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeContracts
Example:
"refundContractOptions": [
{
"transactionContractId": "5MZODHFA",
"transactionContractStatus": "ESTIMATED",
"refundedTicketsBalance": {
"price": {
"amount": "142.00",
"currencyCode": "EUR"
}
},
"charges": [
{
"code": "ADMIN_FEE",
"price": {
"amount": "10.00",
"currencyCode": "EUR"
}
}
],
"paymentBalances": [
{
"transactionType": "CREDIT",
"amount": {
"amount": "132.00",
"currencyCode": "EUR"
}
}
]
}
]
PUT TravelDocuments
Impacted service:
PUT /orders/{{marketingCarrierCode}}/{{orderId}}/travelDocuments
Mandatory _links response element
The _links element is now mandatory and contains two properties:
-
sabreTicketsUrls - resource links for fetching tickets served by NGRP (e.g. for Trainline tickets)
-
publicTicketsUrls - resource links for fetching publicly available tickets (e.g. for SNCF tickets)
Trainline response example:
{
"response": {
"travelDocuments": [
{
"ticketDocumentNumbers": [
"deliverable-4d3f4a11-aaeb-40aa-90d5-5076346fe865"
],
"urls": [
"http://localhost:8080/v2/rail/orders/3Y/BJW672WH2/travelDocuments/f1fde5d9-fb01-41df-a7a9-df7c79bb9706"
]
}
],
"_links": {
"sabreTicketsUrls": [
{
"href": "http://localhost:8080/v2/rail/orders/3Y/BJW672WH2/travelDocuments/f1fde5d9-fb01-41df-a7a9-df7c79bb9706",
"method": "GET",
"type": "application/pdf"
}
],
"publicTicketsUrls": []
}
}
}
SNCF response example:
{
"response": {
"travelDocuments": [
{
"ticketDocumentNumbers": [
"062595282"
],
"urls": [
"https://recette.monbillet.sncf/e-billet?KEY=cbEWJ8hs0Wrz5_GTgo8ghm3QsyYQFyW7xzYyIdyz7LI2ME48_FsQE9HnLP3LfUBd7E5EbjYX&LANG=FR"
]
}
],
"_links": {
"sabreTicketsUrls": [],
"publicTicketsUrls": [
{
"href": "https://recette.monbillet.sncf/e-billet?KEY=cbEWJ8hs0Wrz5_GTgo8ghm3QsyYQFyW7xzYyIdyz7LI2ME48_FsQE9HnLP3LfUBd7E5EbjYX&LANG=FR",
"method": "GET"
}
]
}
}
}
Removed deliveryFormat, changed url string into urls string array
The deliveryFormat
element is now removed from both the request and
response.
The url
string element is now changed into urls
string array.
Applies to both Trainline and SNCF.
Trainline example request before:
{
"deliveryCriteria" : {
"orderItemIds" : {{orderItemIds}},
"deliveryFormat" : "HOMEPRINT"
}
}
Trainline example request after:
{
"deliveryCriteria" : {
"orderItemIds" : {{orderItemIds}}
}
}
Trainline example response before:
{
"response": {
"travelDocuments": [
{
"ticketDocumentNumbers": [
"deliverable-5db2a64f-4a7b-4aaa-b775-e71bdbb11c4d"
],
"deliveryFormat": "HOMEPRINT",
"url": "http://localhost:8080/v2/rail/orders/3Y/6CKXG6X9F/travelDocuments/6f1414f0-1bb3-458c-8522-8fce0019a50d"
}
],
"_links": {
"sabreTicketsUrls": [
{
"href": "http://localhost:8080/v2/rail/orders/3Y/6CKXG6X9F/travelDocuments/6f1414f0-1bb3-458c-8522-8fce0019a50d",
"method": "GET",
"type": "application/pdf"
}
],
"publicTicketsUrls": []
}
}
}
Trainline example response after:
{
"response": {
"travelDocuments": [
{
"ticketDocumentNumbers": [
"deliverable-5db2a64f-4a7b-4aaa-b775-e71bdbb11c4d"
],
"urls": [
"http://localhost:8080/v2/rail/orders/3Y/6CKXG6X9F/travelDocuments/6f1414f0-1bb3-458c-8522-8fce0019a50d"
]
}
],
"_links": {
"sabreTicketsUrls": [
{
"href": "http://localhost:8080/v2/rail/orders/3Y/6CKXG6X9F/travelDocuments/6f1414f0-1bb3-458c-8522-8fce0019a50d",
"method": "GET",
"type": "application/pdf"
}
],
"publicTicketsUrls": []
}
}
}
GET TravelDocuments - new service
This new service is used to fetch ticket in application/pdf format. Used only for Trainline marketing carrier.
Service path:
/orders/{{marketingCarrierCode}}/{{orderId}}/travelDocuments/{{rocketTicketKey}}
RocketTicketKey is generated during PUT TravelDocuments call and is internally associated with ticket url and tenant-id. Before fetching ticket pdf from vendor tenant-id is used to authorize client.
GET Order - mandatory _links response element
Order Read response contains new mandatory element - _links. This element indicates next available operations that can be done on order.
Example
{
"response": {
"order": {...},
"operations": [...],
"_links": {
"self": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1",
"method": "GET"
},
"sabrePnr": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/sabrePnr",
"method": "POST"
},
"travelDocuments": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/travelDocuments",
"method": "PUT"
},
"void": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/voidContract",
"method": "POST"
},
"refundEstimate": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/refundContracts",
"method": "POST"
},
"exchangeOffers": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/exchangeOffers",
"method": "POST"
},
"notification": {
"href": "http://localhost:8080/v2/rail/orders/2C/CR6CP1/travelDocuments/notification",
"method": "PUT"
}
}
}
}
GET Order - added contact id and contacts list in order
Order Read response has been extended with contact element in orderItem.delivery. Contact will contain its current counterpart - contactPerson and an ID. Additionally, all contacts will be returned in a collection on main level, in new element contacts
Example
"order":{
...
"contacts": [
{
"id ": "1",
"contactPerson": {
"firstName": "John",
"lastName": "Doe",
"contactInfo": {
"emails": [
"test@rail.sabre"
],
"phones": [
"1234567"
],
}
}
}
"orderItems":{
...
"delivery":{
...
"contact":{
"id ": "1",
"contactPerson": {
"firstName": "John",
"lastName": "Doe",
"contactInfo": {
"emails": [
"test@rail.sabre"
],
"phones": [
"1234567"
],
}
}
}
...
}
...
}
Flexibility in Transport Tariff made optional
This element is now optional and might not appear in GET Order response. It will not be returned for Trainline reservations.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
{
"tariffs": [
{
"fareCode": "FA22",
"fareName": "FLEX SECONDE",
"classOfService": "2",
"flexibility": {
"flexibilityCategory": "FULL_FLEX",
"refundable": true,
"exchangeable": true
},
"returnMandatory": false,
"remarks": [...],
"segmentIds": [...],
"passengers": [...]
}
]
}
Flexibilities in Transport Tariff removed
This element has been removed and will not appear in GET Order response.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
AssignedTicketsPrice in ExchangeOption made optional
This element is now optional and might not appear in GET Order response. It will not be returned for Trainline reservations.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
{
"exchangeOptions": [
{
"compatibleExchangeOptions": [
{
"exchangeOptionId": "eyJzIjpbIjEiXSwib2lJZCI6ImVjYzAzOGU5LTBhZWQtNDczZS1iY2IxLTBkMzY2YzhkMGYyZCJ9",
"journeyIds": [
"_:89aec013-9fab-4e19-8f55-8329466c69fc"
],
"assignedTicketsPrice": {
"amount": "17.2",
"currencyCode": "EUR"
}
}
]
}
]
}
DiscountCriteria in PassengerCriteria and RailCardOwnerCriteria removed
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/cards/{{marketingCarrierCode}}
-
POST /offers/cards/{{marketingCarrierCode}}/{{cardNumber}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Discount added to PassengerCriteria and RailCardOwnerCriteria
This element replaced DiscountCriteria. The card number now has to be provided already in POST /offers, not POST /orders.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/cards/{{marketingCarrierCode}}
-
POST /offers/cards/{{marketingCarrierCode}}/{{cardNumber}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Example:
{
"passengerCriteria": [
{
"dateOfBirth": "1985-01-20",
"discounts": [
{
"type": "RAIL_CARD",
"identifier": "ABC123",
"program": "FAMILY",
"provider": "SNCF"
}
]
}
]
}
Loyalty cards and corporate discounts in NamedPassenger are replaced with generic discounts
To unify various kinds of discounts, LoyaltyCard and CorporateDiscount elements in NamedPassenger are replaced by the new Discount element. Loyalty cards are now treated as generic rail cards.
Impacted services:
POST /orders/{{marketingCarrierCode}}
GET /orders/{{marketingCarrierCode}}/{{orderId}}
Before:
{
"passengerId": "428297cb-b9d7-4c6b-9b48-21fab1e515f4_p_1",
"lastName": "SKYWALKER",
"firstName: "LUKE",
"dateOfBirth: "1970-01-01",
"contactInfo": {
"emails": [
"LUKE.SKYWALKER@EXAMPLE.COM"
],
"phones": [
"1234567890"
]
},
"loyaltyCards": [
{
"number": "30840601000000139"
}
],
"corporateDiscounts": [
{
"number": "C000PV0",
"provider": "SNCF"
}
]
}
After:
{
"passengerId": "428297cb-b9d7-4c6b-9b48-21fab1e515f4_p_1",
"lastName": "SKYWALKER",
"firstName: "LUKE",
"dateOfBirth: "1970-01-01",
"contactInfo": {
"emails": [
"LUKE.SKYWALKER@EXAMPLE.COM"
],
"phones": [
"1234567890"
]
},
"discounts": [
{
"type": "RAIL_CARD",
"identifier": "30840601000000139"
},
{
"type": "CORPORATE_DISCOUNT",
"provider": "SNCF",
"identifier": "C000PV0"
}
]
}
Changed ExchangeOfferCriteria to use SearchCriteriaForExchange instead of SearchCriteria
The new SearchCriteriaForExchange type does not require providing passenger criteria, to accommodate situations such as basic exchange using Trainline without cards or passenger details.
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Changed ExchangeOffers to use ExchangeSchedule instead of Schedule
The new ExchangeSchedule uses SearchCriteriaForExchange instead of SearchCriteria for its field searchCriteria.
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
POST exchangeContracts - offer ID in request moved to offers array
Exchange estimate can now accept several offers (to enable exchanging tickets for a multi-section journey).
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeContracts
Before:
{
"exchangeCriteria":[
{
"deliveryCode":"ELECTRONIC_TICKET",
"exchangeOfferCriteria":{
"exchangeOptionId":"eyJvSWQiOiI2NjEzZGJiZi0zN2RmLTVlMDAtOGI5Yy1kMjI4MjlhNmEzOGQiLCJzSWQiOiJvcH5VfjkxNWMzYWRlLTJjNzQtNDI4Yi04NWE1LTRiN2IxMDc4NTg5OSIsImlkcyI6WyJjaGFuZ2VhYmxlLXVuaXQtNjlmODJhZDAtMDU0OC00ZGE3LWI1MzYtZGU5ZmEwNTUxNWFjIl19",
"reason":"CUSTOMER_REQUESTED",
"searchCriteria":{
"journeyCriteria":{
"arrival":{
"locationId":"10456"
},
"departure":{
"locationId":"8575",
"dateTime":"2021-03-13T05:53"
},
"directConnection":false
},
"passengerCriteria":[
{
"dateOfBirth":"2000-02-24",
"discounts":[]
}
]
}
},
"offerId":"eyJqSWQiOiJvcH5VfmIwMTk0OGRjLWU3MjAtNGExNS1hOTlmLTZmNDJlYjYyNTc1ZCIsInNOIjoxLCJzSWQiOiIxIiwiYUlkIjoiYWx0ZXJuYXRpdmUtOTlkNzliMmEtNTM3Zi00OWQ1LTk2OTMtMjJkM2I2MmMwNDc2IiwidHlwZSI6Ik8ifQ",
"ancillaryProductOfferCriteria":[],
"seatReservationCriteria":[]
}
]
}
After:
{
"exchangeCriteria":[
{
"deliveryCode":"ELECTRONIC_TICKET",
"exchangeOfferCriteria":{
"exchangeOptionId":"eyJvSWQiOiI2NjEzZGJiZi0zN2RmLTVlMDAtOGI5Yy1kMjI4MjlhNmEzOGQiLCJzSWQiOiJvcH5VfjkxNWMzYWRlLTJjNzQtNDI4Yi04NWE1LTRiN2IxMDc4NTg5OSIsImlkcyI6WyJjaGFuZ2VhYmxlLXVuaXQtNjlmODJhZDAtMDU0OC00ZGE3LWI1MzYtZGU5ZmEwNTUxNWFjIl19",
"reason":"CUSTOMER_REQUESTED",
"searchCriteria":{
"journeyCriteria":{
"arrival":{
"locationId":"10456"
},
"departure":{
"locationId":"8575",
"dateTime":"2021-03-13T05:53"
},
"directConnection":false
},
"passengerCriteria":[
{
"dateOfBirth":"2000-02-24",
"discounts":[]
}
]
}
},
"offers":[
{
"offerId":"eyJqSWQiOiJvcH5VfmIwMTk0OGRjLWU3MjAtNGExNS1hOTlmLTZmNDJlYjYyNTc1ZCIsInNOIjoxLCJzSWQiOiIxIiwiYUlkIjoiYWx0ZXJuYXRpdmUtOTlkNzliMmEtNTM3Zi00OWQ1LTk2OTMtMjJkM2I2MmMwNDc2IiwidHlwZSI6Ik8ifQ",
"ancillaryProductOfferCriteria":[],
"seatReservationCriteria":[]
}
]
}
]
}
offerCriteria in POST /orders renamed to offers
Element offerCriteria in POST /orders was renamed to offers
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}
LocationId in PlaceInTime made optional
The locationId element is not present in Trainline responses and will not appear in NGRP responses for that vendor.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
In an Offer, seatReservationOptions might not be returned
As seat reservations are not always available, the minimum number of returned items was reduced from 1 to 0.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
In a TransportProduct, priceBreakdown might not be returned
As price breakdown is not always available, the minimum number of returned items was reduced from 1 to 0.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
In an Order, elements namedPassengers, journeys and orderItems might not be returned
In some states of the order (e.g. after cancellation) information about passengers, journeys or order items might not be available.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
In an OrderItem, elements journeys and transportProducts might not be returned
For orders containing rail cards, transport products and journeys are not be available, even though the older schema claimed they were.
Impacted services:
GET /orders/{{marketingCarrierCode}}/{{orderId}}
In a DictionaryDescriptionEntry, details might not be returned
Since not all entries have applicable details, they might not be returned.
Impacted services:
GET /dictionaries/{marketingCarrierCode}/{dictionaryName}
Dictionaries can be searched for entries with specific code
Returned results will be a list of DictionaryDescriptionEntries with requested code.
Impacted services:
GET /dictionaries/{marketingCarrierCode}/{dictionaryName}/{code}
ArrivalLocationId and DepartureLocationId removed
The arrivalLocationId and departureLocationId were removed from Schedule and ExchangeSchedule. Instead of them, information from journeyCriteria should be used.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Offers moved from OffersRsContent to OffersRsContent.Schedules.Journeys.Sections
Each journey can now be split into few sections that combined create the whole journey. We can have one section per one vendor for Trainline multi-inventory trips while for SNCF there will always be only one section. Each section consists of one or more segments, the departure, arrival and offers. In case of the multi-inventory trips, one offer per each section has to be chosen.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Before:
{
"schedules": [{
"departureLocationId": "...",
"arrivalLocationId": "...",
"searchCriteria": {},
"journeys": [{
"id": "...",
"departure": {...},
"arrival": {...},
"duration": "...",
"segments": [...]
}]
}],
"passengerSpecifications": [...],
"paymentOptions": [...],
"fulfillmentOptions": [...],
"offers": [...]
}
After:
{
"schedules": [{
"departureLocationId": "...",
"arrivalLocationId": "...",
"searchCriteria": {},
"journeys": [{
"id": "...",
"departure": {...},
"arrival": {...},
"duration": "...",
"segments": [...],
"sections": [{
"departure": {...},
"arrival": {...},
"segments": [...],
"offers": [...]
}]
}]
}],
"passengerSpecifications": [...],
"paymentOptions": [...],
"fulfillmentOptions": [...]
}
Journeys element removed from Offer
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Before:
{
"id": "...",
"basePrice": {...},
"transportProducts": [...],
"deliveryCodes": [...],
"seatReservationOptions": [...],
"ancillaryProductOfferCategories": [],
"journeys": [...]
}
After:
{
"id": "...",
"basePrice": {...},
"transportProducts": [...],
"deliveryCodes": [...],
"seatReservationOptions": [...],
"ancillaryProductOfferCategories": []
}
Refundable and exchangeable in FlexibilityProperties made optional
Trainline does not provide enough information to show flexibility categorization, there’s no reliable source for refundable and exchangeable flag. These parameters exist in SNCF so are optional in offers response.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}
Before:
"tariffs": [
{
"fareName": "...",
"classOfService": "...",
"flexibility": {
"flexibilityCategory": "NON_FLEX",
"refundable": false,
"exchangeable": false
},
"returnMandatory": "...",
"remarks": [...],
"segmentIds": [...],
"passengers": [...]
}
]
After:
"tariffs": [
{
"fareName": "...",
"classOfService": "...",
"flexibility": {
"flexibilityCategory": "NON_FLEX"
},
"returnMandatory": "...",
"remarks": [...],
"segmentIds": [...],
"passengers": [...]
}
]
Moved PaymentCriteria from book to preBook
PaymentCriteria is now optional field at both requests, however it should be used in prebook. In case of sending book request with PaymentCriteria for Trainline there will be thrown error.
Impacted services:
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/salesContract
-
POST /orders/{{marketingCarrierCode}}
Prebook before:
{
"offers": [...],
"fulfillmentCriteria": {...}
}
Prebook after:
{
"offers": [...],
"fulfillmentCriteria": {...},
"paymentCriteria": {...}
}
Book before:
{
"paymentCriteria": {...}
}
Book after:
{ }
Book request extended with bookingPaymentDetails
Optional bookingPaymentDetails
element was added to BookRq
. It
consists of cvv
which in case of Amtrak is mandatory for unmanaged
agencies. An error is thrown if not provided.
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}/salesContract
Book before:
{ }
Book after:
{
"bookingPaymentDetails": {
"cvv": "123"
}
}
PaymentCriteria
Element contains information about payment. Consists of paymentForm
which is a required field and optionally paymentDetails
.
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
{
"paymentForm": {...},
"paymentDetails": {...}
}
PaymentForm
Element contains information about form of payment. Required field is
paymentCode
which can have one of the values: CASH
, CREDIT_CARD
or
UNKNOWN
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
{
"paymentCode": "CASH"
}
PaymentDetails
Element contains detailed information about credit card. Used optionally
in PaymentCriteria
.
Required fields in the request: cardHolderName
, cardNumber
,
expiryMonth
, expiryYear
, emailAddress
.
Optional fields in the request (see a note below) : cvv
,
billingAddress
Impacted services:
POST /orders/{{marketingCarrierCode}}/{{orderId}}
Example:
{
"cardHolderName": "Jane Doe",
"cardNumber": "4000000000000002",
"cvv": "123",
"expiryMonth": "3",
"expiryYear": "29",
"emailAddress": "email@domain.com",
"billingAddress": {...}
}
A list of journeys can be empty
Each schedule can have an empty list of journeys in situation when there are none for a particular connection as opposed to the previous version where at least one journey had to be present.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/outbound
-
POST /offers/journeys/{{marketingCarrierCode}}/roundTrip/inbound?outboundOfferId={{firstOutboundOfferId}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Notification response can contain notificationId
For Trainline, notification is not always processed during request.
In that case response contains notificationId and response status is
202.
Impacted services:
PUT /orders/{{marketingCarrierCode}}/{{orderId}}/travelDocuments/notification
Notification response example:
{
"response": {
"notificationId": "QZYL4QPT"
}
}
Rail card code deprecated, replaced by railCardCodeText
railCardCode field has been marked as deprecated. It is to be replaced by new optional field railCardCodeText.
Impacted services:
GET /railCards/{{marketingCarrierCode}}/{{cardNumber}}?dateOfBirth={{dateOfBirth}}
Rail cards response example:
{
"response": {
"number": "29090115460529965",
"railCardCode": "PASS_LIBERTE", // deprecated
"railCardCodeText": "PASS_LIBERTE",
"discountProgram": "PLIB",
"validityStartDate": "2022-01-14",
"validityEndDate": "2023-01-13",
"owner": {...},
"relatedRailCards": [...]
}
}
Add primaryPassenger to FulfillmentOptions
This field indicates whether the vendor supports and requires a primary
passenger. Primary passenger is assigned automatically when
"primaryPassenger": { "usage": "REQUIRED" }
, the first passenger on
the list becomes it.
Impacted services:
-
POST offers/journeys/{marketingCarrierCode}
-
POST offers/journeys/{marketingCarrierCode}/roundTrip/outbound
-
POST offers/journeys/{marketingCarrierCode}/roundTrip/inbound
-
POST orders/{marketingCarrierCode}/{orderId}/exchangeOffers
Example fulfillmentOptions:
{
"fulfillmentOptions" : [{
"deliveryCode" : "ELECTRONIC_TICKET",
"deliveryFormats" : [ "MOBILE", "HOMEPRINT" ],
"namedPassengerRequirements" : {
"usage" : "REQUIRED",
"lastName" : {...},
"firstName" : {...},
"dateOfBirth" : {...},
"contactInfo" : {...},
"loyaltyCard" : {...},
"primaryPassenger": {
"usage": "UNSUPPORTED"
}
},
"contactPersonRequirements" : {...},
"railCardHolderRequirements" : {...}
}]
}
NamedPassenger in Prebook can contain passengerTravelDocument, citizenShip, gender and middleName
These elements are optional, however it should only be used in prebook for Amtrak for cross-border travel. There is a limited choice of document types, for "ED" there is an additional need to specify the state.
In case of sending prebook request without passengerTravelDocument, citizenShip and gender an error will be thrown.
If middleName is provided only its first character will be sent to Amtrak.
Impacted services:
POST /orders/{{marketingCarrierCode}}
Example:
{
"namedPassengers": [
{
"passengerId": "1",
"firstName": "Doe",
"lastName": "Noonskawy",
"middleName": "Lucinda",
"dateOfBirth": "1990-01-01",
"contactInfo": {
"phones": [
"123456789"
],
"emails": [
"jan.doe@sabre.com"
]
},
"gender": "M",
"citizenShip": "US",
"passengerTravelDocument": {
"countryCode": "US",
"expiryDate": "2023-06-06",
"number": "US13467982",
"stateCode": "WA",
"type": "ED"
}
}
]
}
deliveryCode removed from OfferCriteria in PreBookRq
Element deliveryCode was removed from preBookRq.offerCriteria element. It was duplicated with devlieryCode in preBookRq.fulfilmentCriteria, now deliveryCode only needs to be provided in one place.
orderSplit added in offers' FulfillmentOptions
Element orderSplit was added to offersRs.response.fulfillmentOptions. Now it is possible to provide information whether order split will be possible or not.
Impacted services:
-
POST /offers/journeys/{{marketingCarrierCode}}
-
POST /offers/cards/{{marketingCarrierCode}}
-
POST /orders/{{marketingCarrierCode}}/{{orderId}}/exchangeOffers
Example:
{
"response": {
"fulfillmentOptions": [
{
"orderSplit": {
"usage": "OPTIONAL"
}
}
]
}
}
orderSplit added in PreBookRq
Element orderSplit was added in PreBookRq.fulfillmentCriteria. Now it is possible to split order by providing this argument and setting it to true. Usage is restricted only to SNCF vendor.
Impacted services:
POST /orders/{{marketingCarrierCode}}
Example:
{
"fulfillmentCriteria": {
"orderSplit": true
}
}
viewSplit added in OrderLinks
For split order inside viewSplit there are new links to read part of order. Usage is restricted only to SNCF vendor.
Impacted services:
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}/splitPart/{{splitId}}
Example:
{
"_links": {
"self": {...},
"sabrePnr": {...},
"book": {...},
"modify": {...},
"viewSplit": [
{
"href": "http://localhost:8080/v2/rail/orders/2C/CXM76B/splitPart/eyJiaXJ0aERhdGUiOiIxOTkyLTAxLTAxIiwiZmlyc3ROYW1lIjoiRE9FWCIsImxhc3ROYW1lIjoiTk9PTlNLQVdZWCJ9",
"method": "GET",
"details" : [
{
"property": "PASSENGER_NAME",
"passengerName": "DOE NOONSKAWY"
}
]
},
{
"href": "http://localhost:8080/v2/rail/orders/2C/CXM76B/splitPart/eyJiaXJ0aERhdGUiOiIxOTkwLTAxLTAxIiwiZmlyc3ROYW1lIjoiRE9FIiwibGFzdE5hbWUiOiJOT09OU0tBV1kifQ",
"method": "GET",
"details" : [
{
"property": "PASSENGER_NAME",
"passengerName": "JOHN SMITH"
}
]
}
]
}
}
details added in ResourceLink
For split order there is name and surname of passenger related with this part of order. Usage is restricted only to SNCF vendor.
Impacted services:
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}
-
GET /orders/{{marketingCarrierCode}}/{{orderId}}/splitPart/{{splitId}}
Example:
{
"viewSplit": [
{
"href": "http://localhost:8080/v2/rail/orders/2C/CXM76B/splitPart/eyJiaXJ0aERhdGUiOiIxOTkyLTAxLTAxIiwiZmlyc3ROYW1lIjoiRE9FWCIsImxhc3ROYW1lIjoiTk9PTlNLQVdZWCJ9",
"method": "GET",
"details" : [
{
"property": "PASSENGER_NAME",
"passengerName": "DOE NOONSKAWY"
}
]
},
{
"href": "http://localhost:8080/v2/rail/orders/2C/CXM76B/splitPart/eyJiaXJ0aERhdGUiOiIxOTkwLTAxLTAxIiwiZmlyc3ROYW1lIjoiRE9FIiwibGFzdE5hbWUiOiJOT09OU0tBV1kifQ",
"method": "GET",
"details" : [
{
"property": "PASSENGER_NAME",
"passengerName": "JOHN SMITH"
}
]
}
]
}