Skip Navigation

Migration Guide - Rail APIs v1 to v2

Table of contents

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"
                  }
          ]
      }
  ]
}