ASSIST | APIs | Reservations

Exposes the Reservations (RARS) API
Revision A: 2026-01-27 11:42:58
Image to be added

ASSIST Subject: RSPS5210: 'RARS Reservation Interface'

Version: v1

Notes: Reservations
Reservations API v1.jsonThu 29-Jan-2026 16:23:27

Home (Rev K)
Revision K: 2026-02-18 09:17:30

There will be three main categories of Reservation resources, supported by reference data:

  1. Query availability
  2. Make or amend a booking
  3. Retrieve coach details
  4. Reference data

Each of these categories may contain one or more resources as determined by the requirements and underlying RARS platform capabilities.


Query Availability

This resource allows consumers to request availability of products on services. Broadly equivalent of the Retail SOPI AQ message the availability resource allows for more granular availability queries, for example in relation constructing bundles for multiple passenger bookings, or by prioritising products


Make or amend a booking

This resource allows consumers to make a provisional booking. It enables consumers to supply customer, journey, product and optionally seat information in order to provisionally reserve a seat (or berth if applicable). Once provisionally reserved the seat will be held for that customer for a configurable period of time (currently 30 mins). Consumers have to confirm the booking (see below) within that time window otherwise the provisional booking will be automatically cancelled (expire).++

-- Last name and phone number must be provided for sleeper bookings

-- Passenger IDs must be sequential (e.g., passenger_1, passenger_2, etc.)

This resource allows consumers to recall a provisional or confirmed booking using the unique booking reference assigned to it by the reservations service

This resource allows consumers to update a booking's status. Possible options are:

-- Confirm - this will confirm a provisional booking (i.e. the booking will not expire and must be explicitly cancelled to be released)

-- Cancel - this will cancel a booking and can be used for either provisional or confirmed bookings

-- Revert - this will back out changes made to a confirmed booking

Note: It is best practice to cancel a provisional booking if it is known that it will not be taken up, rather than allowing it to expire, as this will free up the held seats for other passengers to potentially book.

This resource allows consumers to update a seat associated to a reservation, subject to availability. This can be done before or after a provisional booking is confirmed.

This resource allows consumers to manage a Customer's details, such as name, email address, phone number, etc. A Customer is the 'owner' of a booking as distinct from passengers which are those who are actually travelling. In the majority of cases the Customer will be one of the passenger's but this may not always be the case - for example a corporate booking may be made by a representative of a business (e.g. a PA) as the Customer, for one or more employees to travel as the Passengers. Because these details contain personably identifiable information they will be hidden/masked in certain circumstances for GDPR compliance purposes.

This resources allows consumers to manage passenger details, such as name, email address, phone number, etc. It also allows additional passengers to be added to an existing booking. Because these details contain personably identifiable information they will be hidden/masked in certain circumstances for GDPR compliance purposes.

This resource allows consumers to cancel (remove) one or more passengers from an existing booking To cancel passenger(s) the system requires the passenger identifier (uuid), which can be found in the booking: data->passengers->uuid

As part of this call, the system will blank out the requested passenger details following successful cancellation of the passenger and will be recorded as a change to the booking.

This resource allows consumers to add free text notes to a booking. These notes have no functional impact and can be used to record any reasonable information relating to a booking which can not be applied to an existing field. Because these notes may contain personably identifiable information they will be hidden/masked in certain circumstances for GDPR compliance purposes.

This resources allows consumers to add one or more legs and/or product items to an existing booking

This resources allows consumers to cancel (remove) one or more legs from an existing booking To cancel leg(s) the system requires the leg identifier (uuid), which can be found in the booking: data->outboundBookingTariffLegs->uuid data->inboundBookingTariffLegs->uuid

This resources allows consumers to cancel one or more seat product items from an existing booking To cancel product item(s) the system requires the product item identifier (itemRef), which can be found in the booking: data->outboundBookingTariffLegs->requiredProducts->itemRef data->inboundBookingTariffLegs->requiredProducts->itemRef (There is also an itemRef for additional products, however, additional products is intended for future use) data->outboundBookingTariffLegs->additionalProducts->itemRef data->inboundBookingTariffLegs->additionalProducts->itemRef

Although there is a uuid for a product item, the product item cancel resource requires the itemRef and not uuid, as specified above

These resources allow consumers to add or update the Unique Ticket Number or Retailer Ticket Reference. These can be added when creating a provisional booking, or by using these resources consumers can add or change them at a later time.

This resource allows consumers to change the booked service(s) and/or product(s) To perform a rebooking the system requires the product item identifier (uuid), which can be found in the booking: data->outboundBookingTariffLegs->requiredProducts->uuid data->inboundBookingTariffLegs->requiredProducts->uuid

Although there is an itemRef for a product item, the rebooking resource requires the uuid and not itemRef, as specified above

This resource allows consumers to recall a booking reference using a unique identifier assigned to it by the booking owner. Two different references can be used, subject to them being recorded against a booking:

-- Unique Ticket Reference (UTN) - this will allow consumers to recall a reservation using a barcode UTN.

-- Retailer Booking Reference (RBR) - this will allow consumers to recall a booking using a their own reference

This resource allows consumers to recall a booking reference applicable to a specified seat and calling points. This may be used, for example, to recall a booking reference for a Customer who knows which seat they are booked in but doesn't know their reference. A consumer would still need the usual permissions to recall or amend a booking once the reference has been retrieved.

This resource allows consumers to retrieve a ticket reference for a specified Service, Origin, Destination, Coach and Seat. This may be used to find a ticket reference number for a particular seat on a specified origin and destination to validate a booking. This also allows for the validation history of the booking to be returned.

This resource returns details such as boarding, alight location, and validations for a specific ticket for consumers to verify the current validation status of a ticket.

This resource allows the validation value of a reservation to be changed

This resources allows a booking validation to be reverted to it's previous value from a value of RELEASE_REQUESTED

This resource allows consumers to attempt a booking without first checking for availability. If the requested product is fully available a provisional booking will be made, and if it isn’t, an error message will be returned. Consumers can also optionally request for the provisional booking to be confirmed.

It is the equivalent of the consumer doing the below separate API requests:

POST /availability to check availability

POST /bookings to make a provisional booking (using tariff code from availability response)

optionally PUT /bookings/{bookingReference}/status to confirm booking (using bookingRef from make booking response)


Retrieve coach details

This resource provides the full details of a service, including; the number of coaches and their sequence order, what seats are on each coach and their properties (e.g. plug socket available), and the booking status of each seat. The response also includes an image for each of the coaches along with dimensions of both the coach and the position and dimensions of seats within each coach so that these can be plotted on a suitable display.

This resource is a subset of the coach layout resource; providing only the details, sequence and image of each coach on a service without the seat status or position/dimension information

This resource provides a list of passengers as well as seat reservation details on any given service for a particular train operating company


Reference data

This resource allows consumers to request the latest list of disability types supported by the reservations service. Disability types can be submitted in booking requests and will impact on what seats may be booked (e.g. allowing seats specifically for passengers with wheelchairs).

This resource has been added as it will be a requirement to record a season ticket number against any bookings with a season ticket. This information will be used for MI and fraud detection/reduction purposes. At the moment this data set has only one entry, but may be expanded in the future to include other forms of discounted travel.

This resource allows consumers to request the latest list of seat properties supported by the reservations service. Seat property codes can be submitted in certain requests and returned by others. This reference data provides details of seat property codes and their associated descriptions for different carriers and time periods.


Security

The resources will be protected by the following policies:

As shown in the examples, Bearer token must to be sent as part of the Authorization header which will be validated by JWT policy by communicating with the already configured identity provider.

Association logic (Rev B)
Revision B: 2024-10-29 17:10:31

In order to select the right Retail Service ID (rsid) and service origin date (serviceOriginDate) to submit in Reservation API requests, consumers have to apply some logic for trains which split or join en route (known as associations). Within the RARS platform trains which are impacted by a split or a join are 'expanded' during the import process, to create unique services with the full and correct calling patterns. This requires Reservation API users to be able to uniquely identify these services in order to query availability, retrieve coach information, or to make bookings

The data needed to do this is all available within the existing timetable data feed (RSPS5046). This page provides instructions on how that data can be used to supply the right retail service ID and service origin date in Reservation API requests.

General rules:

The logic for choosing the right retail service ID and service origin date for associated services can be simply expressed as:

Notes:

  1. Cases of 2 or more services splitting or joining at a calling point are supported by RARS (e.g. Caledonian sleeper at Edinburgh)
  2. Associations at multiple calling points are not currently supported in RARS

Join associations:

Using the below as an example of a join association:

Join

Here we have two services, one with a calling pattern A-B-C-D-E-F-G-H and the other with a calling pattern X-Y-Z-D, and a join association record for these two services at D. Upon import into the RARS platform the association will be expanded and these will be stored in RARS as

The A->H service has two RSIDs recorded in it's schedule. The first, XX123401, is in the BX record and the second, XX123403, is in a CR record at the join location D.

The X->H service only has one RSID, XX123402, published in the BX record of its schedule, but inherits XX123403 from the join.

Split associations:

Using the below as an example of a split association:

Split

Here we have two services, one with a calling pattern A-B-C-D-E-F-G-H and the other with a calling pattern E-X-Y-Z, and a split association record for these two services at E. Upon import into the RARS platform the association will be expanded and these will be stored in RARS as

The A->H service has two RSIDs recorded in it's schedule. The first, XX123403, is in the BX record and the second, XX123401, is in a CR record at the split location E.

The A->Z service only has one RSID, XX123402, published in the BX record of its schedule, but inherits XX123403 from the split.

Availability - Basic Usage (Rev A)

This page provides an example of the simplest type of availability searching. It is intended to be a starter example for people unfamiliar with availability and/or the reservation interface to understand the basic concepts before moving on to more complex, real-world, examples.

Below is an example availability request for one product (SVS, 00000) for one adult (000) passenger who is looking to travel on 9th March between Chelmsford (6836) and Manchester Piccadilly (2968). This journey has 3 legs (Chelmsford to London Liverpool Street, London Liverpool Street to London Euston and London Euston (EUS) to Manchester Piccadilly (MAN)) but only the final leg on an Avanti West Coast train (VT707000) allows reservations to be made.

Request:

{
   "salesFlowType": "SALES",
   "journeys": [
      {
         "id": "journey_1",
         "direction": "outbound",
         "journeyConditions": {
            "journeyOD": {
               "journeyOrigin": "6836",
               "journeyDestination": "2968"
            }
         },
         "legs": [
            {
               "id": "segment_1",
               "boardLocation": "EUS",
               "alightLocation": "MAN",
               "rsid": "VT123400",
               "serviceOriginDate": "2021-03-09"
            }
         ],
         "bundles": [
            {
               "id": "bundle_1",
               "products": [
                  {
                     "ticketTypeCode": "SVS",
                     "routeCode": "00000"
                  }
               ]
            }
         ]
      }
   ],
   "passengers": [
      {
         "id": "passenger_1",
         "statusCode": "000"
      }
   ]
}

Response, Example 1 - product is available:

This response to this request indicates that this product is available for this passenger (FULL_AVAILABILITY) on the requested service. In addition to confirming availability it also provides information about the requested service and product:

Information:

The response also includes data which the consumer will need if they move forward to make a booking:

{
   "salesFlowType": "SALES",
   "journeys": [
      {
         "journeyConditions": {
            "journeyOD": {
               "journeyDestination": "2968",
               "journeyOrigin": "6836"
            }
         },
         "bundles": [
            {
               "bundleOutcome": "FULL_AVAILABILITY",
               "products": [
                  {
                     "ticketTypeCode": "SVS",
                     "items": [
                        {
                           "inventoryClass": "2C",
                           "passengerIds": [
                              "passenger_1"
                           ],
                           "legId": "segment_1",
                           "tariffCode": "2O_SVS"
                        }
                     ],
                     "routeCode": "00000"
                  }
               ],
               "id": "bundle_1"
            }
         ],
         "direction": "outbound",
         "id": "journey_1",
         "legs": [
            {
               "arrivalDateTime": "2021-03-09T12:28:00+00:00",
               "departureDateTime": "2021-03-09T10:20:00+00:00",
               "alightLocation": "MAN",
               "boardLocation": "EUS",
               "id": "segment_1",
               "serviceOriginDate": "2021-03-09",
               "serviceIdentifier": "0:R|VT123400|TRAIN|2021-03-09",
               "rsid": "VT707000",
               "carrierCode": "VT"
            }
         ]
      }
   ],
   "passengers": [
      {
         "id": "passenger_1",
         "statusCode": "000"
      }
   ]
}

Response, Example 2 - product is NOT available:

This example shows how the response would look if the requested product isn't available for booking on the requested service. -

{
   "salesFlowType": "SALES",
   "journeys": [
      {
         "journeyConditions": {
            "journeyOD": {
               "journeyDestination": "2968",
               "journeyOrigin": "6836"
            }
         },
         "bundles": [
            {
               "bundleOutcome": "NO_AVAILABILITY",
               "id": "bundle_1"
            }
         ],
         "direction": "outbound",
         "id": "journey_1",
         "legs": [
            {
               "arrivalDateTime": "2021-03-09T12:28:00+00:00",
               "departureDateTime": "2021-03-09T10:20:00+00:00",
               "alightLocation": "MAN",
               "boardLocation": "EUS",
               "id": "segment_1",
               "serviceOriginDate": "2021-03-09",
               "serviceIdentifier": "0:R|VT123400|TRAIN|2021-03-09",
               "rsid": "VT707000",
               "carrierCode": "VT"
            }
         ]
      }
   ],
   "passengers": [
      {
         "id": "passenger_1",
         "statusCode": "000"
      }
   ]
}

Availability - Bundle Concepts (Rev B)
Revision B: 2023-06-27 11:37:23

The Basic Usage page introduced the concept of a bundle. A bundle is used by the reservation service to determine the best availability for one or more products. With the Basic Usage example a simple single product, single passenger bundle was provided, which means that the response provided availability just for that product, with no consideration or influence of other products or number of passengers travelling. This is a very simplistic question and response, providing the most basic information regarding availability. This type of query is useful if a single passenger is travelling and it is already known what product they wish to make a booking with. A good example of this may be a season ticket holder, who already holds a ticket and is looking to book a seat as part of their regular commute.

However, bundles can be expanded in multiple ways to allow the reservation service to provide much more useful information, either in terms of which products are available or in cases of multiple passengers travelling together - or of course any combination of the two. This page outlines some examples of how bundles can be constructed to provide the best and most accurate availability response for different combinations of products and passengers.

NOTE: The below isn't exhaustive, there are other examples which may be of relevance to different retailers depending on how their sales pipeline is set up. This page is intended to give an introduction to the most common usage patterns and consumers can engage with RDG on other patterns or combinations which they may wish to better understand.

Single Passenger Requests

Restating the most basic type of bundle, as seen in the Basic Usage example:

"bundles": [{"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000"}]}]

In this request, a single bundle is requested for SVS, 00000 and will apply to all passengers, The Basic Usage bundle checks for the availability of a single product. However, in many cases it is not known prior to the availability check which product a Customer will ultimately go on to buy so a common availability request will be searching for availability over multiple products. The availability search enables this type of request in a number of different ways.

Mono Product Bundles

A mono product bundle is the simplest extension of the Basic Usage example. This search pattern allows users to check for the availability of multiple products in one request, each in isolation from each other:

"bundles": [
    {"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000"}]},
    {"id": "bundle_2","products": [{"ticketTypeCode": "SDS", "routeCode": "00000"}]},
    {"id": "bundle_3","products": [{"ticketTypeCode": "2CS", "routeCode": "00720"}]},
    {"id": "bundle_4","products": [{"ticketTypeCode": "2DS", "routeCode": "00720"}]},
    ...
]

The availability response will indicate whether each individual product is available, or not, at the time of asking. However, it doesn't provide any information about whether two or more of these products are available at the same time. For example, with this type of search the response may indicate that both the SVS and SDS are available. However, what it doesn't confirm is that these products are both available at the same time. It may be that their respective availabilities both ultimately depend on the same seat, so if one is booked the other cannot be booked, and vice versa.

This type of request is ok when the querying system is trying to identify which products a single passenger may be able to book. It should not be used to infer any availability beyond that single passenger.

Multiple Product Bundles: Relative availability

The Basic Usage and Mono Product Bundles both take the approach of determining availability for products in isolation from each other. This has its place but it is often more useful to understand the availability of products in relation to each other. To do this consumers can specify multiple products in a single bundle, and when doing so their availability will be considered in conjunction with other products in that bundle. This has particular power in multi-passenger bookings (see below) but for the single passenger scenario a good example of where this can be used is when a passenger is looking to book both a bike and a seat. For this example the Mono Product Bundle example can be extended as follows:

"bundles": [
     {"id": "bundle_1","products": [
          {"ticketTypeCode": "SVS", "routeCode": "00000"}, {"ticketTypeCode": "BIK", "routeCode": "00000"}]},
     {"id": "bundle_2","products": [
          {"ticketTypeCode": "SDS", "routeCode": "00000"}, {"ticketTypeCode": "BIK", "routeCode": "00000"}]},
     {"id": "bundle_3","products": [
          {"ticketTypeCode": "2CS", "routeCode": "00000"}, {"ticketTypeCode": "BIK", "routeCode": "00000"}]},
     {"id": "bundle_4","products": [
          {"ticketTypeCode": "2DS", "routeCode": "00000"}, {"ticketTypeCode": "BIK", "routeCode": "00000"}]},
     ...
]

which for each bundle is asking the question whether the specified product AND a bike reservation are both available at the same time. If the answer is yes then the bundle outcome in the response for the respective bundle would be FULL_AVAILABILITY. If the answer is no (i.e. one or both the specified product and/or bike is not available) then the bundle outcome for that bundle will be NO_AVAILABILITY.

Multiple Product Bundles: Sequencing

The above example demonstrated how a bundle can be used to determine relative availability of 2 products, checking for when products A AND B are both available. But there is an alternative method of relative availability which is checking whether product A OR product B is available. This can be achieved using the Mono Product Bundle approach to ask for every products availability individually and then looking at the results. But this involves sending and receiving a long list of bundles, which is relatively inefficient and slow. The availability API offers the option of answering this 'OR' question with one bundle, by using priority 'sequencing'.

When constructing a bundle the consumer can choose to include a sequence number with each product. It is entirely up to the consumer how they choose a priority sequence, but an obvious example is by price; with the cheapest product in a range having the lowest sequence number and the most expensive the highest.

"bundles": [
     {"id": "bundle_1", "products": [
          {"ticketTypeCode": "W2A","routeCode": "00820", "sequenceNumber": 1},
          {"ticketTypeCode": "W2B","routeCode": "00820", "sequenceNumber": 2},
          {"ticketTypeCode": "W2C","routeCode": "00820", "sequenceNumber": 3},
          {"ticketTypeCode": "W2D","routeCode": "00820", "sequenceNumber": 4},
          ...
          {"ticketTypeCode": "W2Z","routeCode": "00820", "sequenceNumber": 26}
     ]}
]

The above example assumes a range of standard class advance products, with the cheapest priced as "W2A" and the most expensive priced as "W2Z". By specifying this range of products (which only differ by price) with a sequence the availability response will return only one product in the response, which will be the product with the lowest sequence number that is available.

"bundles": [{
     "bundleOutcome": "FULL_AVAILABILITY",
     "id": "bundle_1",
     "products": [{
          "routeCode": "00820",
          "ticketTypeCode": "W2F",
          "items": [{
               "tariffCode": "500-W2F-S01",
               "inventoryClass": "2S",
               "legId": "segment_1",
               "passengerIds": ["passenger_1"]
          }]
     }]
}]

Without sequencing the response would contain a bundle outcome for all 26 products in the request, with some showing as NO_AVAILABILITY and others as FULL_AVAILABILITY and the consumer would have to process all of these results to determine what to show to a Customer. By using sequencing this is handled for them and the result is much smaller and quicker to process.

Multi-Passenger Requests

The examples above all assume a single passenger. However, it is common to want to know availability for multiple passengers who are travelling together. The availability API allows users to specify multiple passengers within the passenger array:

"passengers": [
      {"id": "passenger_1", "statusCode": "000"},
      {"id": "passenger_2", "statusCode": "000"}
]

NOTE: It is important that requests are made with the _correct _number of passengers. The new reservations service has a completely new approach regarding excess capacity (see below) and supplying requests with more passengers than required is not a valid way to determine this.

Within each product in a bundle you can either:

If we assume 2 passengers have been included in the passenger array as illustrated above then the following:

"bundles": [{"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000"}]}]

Results in availability being checked for both passengers. By specifying one or more passengersIds with the product object it is possible to limit the check to just those passengers. For example:

"bundles": [{"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000", "passengerIds": ["passenger_1"]}]}]

Results in the availability being checked for the specified passenger only.

As seen above in Multiple Product Bundles: Relative availability, it is possible to specify multiple products within a bundle. This becomes more powerful when multiple passengers are introduced into the equation as it becomes possible to check the availability of different passenger/product combinations. For example:

"bundles": [{"id": "bundle_1","products": [
    {"ticketTypeCode": "SVS", "routeCode": "00000", "passengerIds": ["passenger_1"]}, 
    {"ticketTypeCode": "S0S", "routeCode": "00000", "passengerIds": ["passenger_2"]}
]}]

Checks for the concurrent availability of the SVS product for passenger 1 and the SOS product for passenger 2.

To check if both products are available for both passengers would need a Mono Product Bundles style request:

"bundles": [
    {"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000"}]},
    {"id": "bundle_2","products": [{"ticketTypeCode": "SOS", "routeCode": "00000"}]}
]

In this case there is no need to specify passengerIds as this is done by default.

To determine the best option between two products (e.g. assuming SVS is cheaper than SOS) then as shown above sequencing can be added to the bundle, for example:

"bundles": [{"id": "bundle_1","products": [
    {"ticketTypeCode": "SVS", "routeCode": "00000", "sequenceNumber": 1}, 
    {"ticketTypeCode": "S0S", "routeCode": "00000", "sequenceNumber": 2}
]}]

which in this case would return the SVS product with a bundle outcome of FULL_AVAILABILITY if it is available for both passengers. If the SVS isn't available for both passengers but the SOS product is then the SOS product would be returned with the FULL_AVAILABILITY bundle outcome. And if neither product was available for both passengers you would get the following returned:

"bundles": [{
    "bundle_outcome": "NO_TARIFF",
    "ref_id": "bundle_1"
}]

Excess Capacity

One of the common practices with the Retail SOPI was to request more passengers than needed in availability requests to get a view on what excess capacity may be available for a given product (up to a user's configured limit, usually 9). As mentioned above, if a similar approach was taken with the new interface then incorrect or misleading information would be returned in terms of product availability. Instead a new feature has been added to bundle responses to automatically communicate excess capacity.

If we look again at two passengers, a request may be submitted with:

"passengers": [{"id": "passenger_1", "statusCode": "000"},{"id": "passenger_2", "statusCode": "000"}]
...
"bundles": [{"id": "bundle_1","products": [{"ticketTypeCode": "SVS", "routeCode": "00000"}]}]

which may generate a response like:

"bundles": [{
      "bundleOutcome": "FULL_AVAILABILITY",
      "id": "bundle_1",
      "products": [{
           "routeCode": "00000",
           "ticketTypeCode": "SVS",
           "items": [{
                "tariffCode": "500-SVS-S01",
                "inventoryClass": "2S",
                "legId": "segment_1",
                "passengerIds": ["passenger_1", "passenger_2"],
                "cappedAvailability": 5
           }]
      }]
}]

Note that with this example a cappedAvailability value has been added to the response. This capped availability tells the consumer that there is a total of 5 of these products currently available for this type of passenger on this service, including the two requested. From this it is possible to determine the excess capacity is 3.

If a cappedAvailability value is not returned then the number of available products is in excess of the maximum number the consumer is permitted to know (usually 9). So a FULL_AVAILABILITY bundle outcome with no cappedAvailability value means that there are 9 or more of these products currently available on this service to this type of passenger.

Bundle Outcome

The below table provides a description of what each Bundle Outcome means:

|Bundle Outcome|Description| | -------- | -------- | -------- | |FULL_AVAILABILITY|The bundle is available for the whole journey| |PARTIAL_AVAILABILITY|There are available seats for the requested Ticket Type, but not enough for all passengers - i.e. the group is larger than the number of tickets available.| |NO_AVAILABILITY|The service is not full, but it's not offering availability. The train may have physical capacity, but the operator is choosing not to offer any availability for that Ticket Type| |NO_TARIFF| There is no valid tariff offered for this customer/product/journey combination. Usually caused when the operator does not have a offering for the requested Ticket Type. e.g. asking for a sleeper Ticket Type on a non-sleeper service.| |SERVICE_FULL|The service is completely full for the requested inventory class, but there may be space in other inventory classes.|

Availability - Tariff Codes (Rev A)

Tariff codes are returned in availability responses when a requested product is available to be booked. The TOCs set the tariff codes based on a number of different conditions and unlike ticket type codes tariff codes may vary at any time dependant on those conditions. Tariff codes may also be changed to reflect different yield management strategies so it is also possible for identical availability requests to return different tariff codes if they are submitted at different times (e.g. on subsequent days).

It is therefore important for reservation interface consumers to submit an availability request immediately prior to making a booking to ensure they have the latest tariff code (and service identifier for the same reason). Failure to retrieve the latest tariff code may result in a failure to complete a booking.

Availability - Status Codes (Rev B)
Revision B: 2023-04-17 11:07:40

When requesting availability the same passenger may have a different status code applicable to them depending on when they are travelling and/or on what products they are looking to purchase. For example, a passenger holding a 16-25 railcard would be associated with a status code of 003 when they are travelling on an off-peak service in standard class, but when travelling on a peak service or with a first class fare the applicable status code for them would be 000 (standard adult) as the 16-25 discount doesn't apply to this service and/or product.

The recommeded way to request availability information for a passenger whose associated status code may vary is:

When submitting the booking, use the status code associated to a product's FULL_AVAILABILITY response. So in the above example, if status code 000 renders a FULL AVAILABILITY response with a tariff code for a product, use that status code and tariff code when doing the booking. However, if status code 003 was used to get a FULL_AVAILABILITY response and tariff code for a product then use that status code and tariff code when making the booking.

Booking - Confirmation (Rev A)
Revision A: 2022-07-05 16:43:21

The reservations interface exposes the underlying service's concept of provisional and its related concept of confirmed, which applies to bookings and to any subsequent booking updates (often referred to as 'after sales'). Understanding and correctly using the provisional and confirmed statuses is critical to correctly using the new reservations service.

Provisional versus Confirmed Unlike NRS, the new reservation service works on the assumption that new data isn't applied until it has been explicitly confirmed as being valid. This provisional -> confirmed concept derives from real-world ticket sales processes, where there are usually several steps between a Customer selecting the ticket and reservation and them completing the purchase. The provisional status represents the selection stage of this process, whereas the confirmed status represents the completion of the purchase.

In more technical terms, the standard CRUD (Create/Read/Update/Delete) operations can be categorised as follows:

Action S3 Passenger term/concept Need confirmation? If not confirmed?
Create Create provisional booking Yes whole booking cancelled
Read Recall booking N/A N/A
Update After Sales Yes* Booking reverted to last confirmed state
Delete Cancel booking No N/A


i.e. whenever a new booking is created, or a confirmed booking is updated*, it has to be explicitly confirmed otherwise the reservation service will automatically remove or revert the booking.

Impact on resources The following shows which of the reservation resources requires confirmation in order to be applied.

Resource CRUD Operation Need confirmation?
/availability Read No
/bookings Create Yes
/bookings/{bookingReference} Read No
/bookings/{bookingReference}/status - > Confirm N/A This is the confirm action
/bookings/{bookingReference}/status - > Cancel Delete No
/bookings/{bookingReference}/status - > Revert N/A Undo unconfirmed updates
/bookings/{bookingReference}/seats Update Yes
/bookings/{bookingReference}/customer Update Yes
/bookings/{bookingReference}/passengers Update Yes
/bookings/{bookingReference}/passengers/cancel Update Yes
/bookings/{bookingReference}/legs Update Yes
/bookings/{bookingReference}/legs/cancel Update Yes
/bookings/{bookingReference}/legs/productItems/cancel Update Yes
/bookings/{bookingReference}/rebooking Update Yes
/bookings/{bookingReference}/utn Update No*
/bookings/{bookingReference}/rbr Update No*
/bookings/{bookingReference}/notes Update No*
/bookings/references Read No
/bookings/{rsid}/{serviceOriginDate}/{boardLocation}/{alightLocation}/{coachId}/{seatId} Read No
/service/{rsid}/coaches Read No
/service/{rsid}/coaches/images Read No
/refdata/disabilityTypes Read No
/refdata/discountedOrSeasonCardTypes Read No
/refdata/seatProperties Read No


* Note: Whilst these actions fall under the Update category the fields do not affect the validity of the booking and are considered to be metadata by the underlying service, and as such are applied immediately without needing to be confirmed.

Booking - Journey Conditions (Rev A)
Revision A: 2023-08-18 11:20:45

Journey Conditions

When making a booking it is important to always include the same Journey Conditions as were used to determine the availability. Journey Conditions tell the reservation service the overall journey that a passenger is making which in turn could impact on the seat allocated to them. For example, TOCs may choose to set up their inventory so that certain seats are prioritised for 'local' journeys whereas others are prioritised for connecting passengers.

Adjusting seat allocations based on overall journey is entirely optional and in many cases TOCs will not implement such rules. However, retailers have no way of knowing when such rules are in place so the only way to ensure that a correct seat is offered is by including the Journey Conditions in all relevant requests.

Compression (Rev A)
Revision A: 2023-07-07 09:45:34

From July 2023 RDG have enabled support for compression within the reservations API. Prior to this date if a consumer of the API advertised in their request that they could consume a compressed response (by including 'Accept-Encoding: gzip' within the request header) this was ignored by the API and content was always returned in its native, uncompressed, form. From July 2023, if the request includes this header then content will be compressed before being returned.

Example headers in a request

POST https://api.nationalrail.co.uk/reservations/api/v1/availability HTTP/1.1
Accept-Encoding: gzip
Authorization: Bearer {{token}} 
Connection: Keep-Alive
Content-Length: 2783
Content-Type: application/json
Host: api.nationalrail.co.uk
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)

Response headers prior to July 2023:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Length: 3288
Content-Type: application/json; charset=UTF-8
Date: Thu, 06 Jul 2023 15:33:32 GMT
Strict-Transport-Security: max-age=31536000; includeSubdomains;
x-ssl-client-verify: NONE
x-correlation-id: 76af19c0-1c12-11ee-885e-06ff204a1d13
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

These headers indicate that the content is being returned without any compression

Response headers after July 2023:

HTTP/1.1 200 OK
Connection: keep-alive
Content-Encoding: gzip
Content-Type: application/json; charset=UTF-8
Date: Thu, 06 Jul 2023 15:36:56 GMT
Strict-Transport-Security: max-age=31536000; includeSubdomains;
Transfer-Encoding: chunked
x-ssl-client-verify: NONE
x-correlation-id: f047cb10-1c12-11ee-885e-06ff204a1d13
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-XSS-Protection: 1; mode=block

The headers after July 2023 now indicate that the response content has been compressed (content-encoding: gzip).

Compressing the response content makes minimal difference to small responses, but for bigger responses it can improve the response time by as much as 50%. Most HTTP modules natively handle compressed responses, so whilst requesting them is optional RDG recommend doing so wherever possible. If your systems cannot handle compressed content in the response then do not include the 'Accept-Encoding: gzip' header in the request.

Error handling (Rev H)
Revision H: 2026-02-04 09:29:56

Whilst every effort will be made to capture all errors which may be returned for these API resources on this page, consumers are advised that as RDG are using a common service (frequently known as Software as a Service or SaaS) for the underlying technology within the reservation service, additional error cases may be added to the product at any time. If you are returned an error not recorded here, please provide details to RDG, including the request which generated the error and the error message itself, and we will investigate and add to this page.


Platform Error Format

The Developer Portal will return an error if submitted requests do not comply with one or more of an API's policies. A common example of this is the security policy, which requires a valid JWT in every request. If the request doesn't include a valid JWT then the Portal will reject the request immediately and make no attempt to process it. Rejected requests of this nature will result in a platform error, which has the following simple format (See Platform Error Object data type):

{
    "error" : "error message"
}

RDG Error format

If a request passes the policy checks it will be submitted to the relevant RDG API which may then result in an RDG specific error as opposed to a generic platform error. APIs on the RDG Developer Portal use the following common error format to contain and return these errors to consumers (See RDG Error Object data type):

{
    "errors": [
        {
            "code": "error_code",
            "message": "error message",
            "timestamp": "YYYY-MM-DDTHH:MM:SS",
            "context":  
                    {
                        "{key}": "value"
                    }
        }
    ]
}

The context object is an unspecified list of key value pairs, allowing new context information to be provided without requiring a schema change.

Reservations specific error handling

For the reservations service, the below list represents the known context keys which may be returned by the source service. This list is not within RDG control and is subject to change at any time. Please report any context keys which are not in the list below to cci-support@raildeliverygroup.com and RDG will review and update this page to include them.

Field name keys:

There may also be context items which are not field names, such as:

Known Error Cases

General

Code Message Comment
GBR-AUTH-2000 Security Error When RDG fails to process request due to client side or server side security failure
GBR-AUTH-2001 Unauthorised User When user’s token is invalid
GBR-AUTH-2002 Security validation: precondition failed -
GBR-AUTH-2003 Security validation: Bad request When request payload has failed to process
GBR_EXCEPTION_0000 Unknown Error Catch all for any unknown errors
GBR_EXCEPTION_0001 Undefined error by 3rd party system Unknown error from 3rd party APIs
GBR_EXCEPTION_3000 Invalid schema/ Invalid payload Bad request due to payload not conforming to the json/xml schema definition
GBR_EXCEPTION_3001 Internal Error Unable to complete operation
GBR_EXCEPTION_3006 Resource not found When API resource request is not found or not defined in the specification
GBR_EXCEPTION_3007 Method not allowed When API resource request doesn’t conform to the API specfication e.g. method GET is expected for a resource but POST or PUT call is made
GBR_EXCEPTION_3009 Unsupported media type When API resource request media type (e.g. application/json) doesn’t conform to the expected media type
GBR_EXCEPTION_3010 HTTP too many requests Rate-limit exceeded
GBR_EXCEPTION_3011 AWS S3 bad request error When AWS S3 throws error due to processing error of the request
GBR_EXCEPTION_3012 Invalid schema/ Invalid payload Bad request due to payload not conforming to the json/xml schema definition
GBR_EXCEPTION_3013 Invalid schema/ Invalid payload Bad request due to payload not conforming to the json/xml schema definition
GBR_EXCEPTION_3014 Forbidden Error When source system doesn’t allow access to a particular resource for a specfic client
GBR_EXCEPTION_3015 Validation Error [Email is valid] The structural conformation of email is checked and throws error if doesn’t match the built in REGEX pattern
GBR_EXCEPTION_3063 Expression error When any form of REGEX failed to excute due to incorrect inputs
GBR_EXCEPTION_3065 Retry exhausted, Redelivery Exhausted Retry component reaches the threshold number with respect to HTTP requests made
GBR_EXCEPTION_3066 Connectivity issue or service is not available When cannot reach the resource URL or underneath service doesn’t respond
GBR_EXCEPTION_3067 HTTP time out When the HTTP request gets timed out
RAML_ERROR Invalid schema/ Invalid payload Bad request due to payload not conforming to the json/xml schema definition

Availability

Code Message Comment
could_not_find_disability_type n/a A requested disability type is invalid
could_not_find_passenger_type n/a A requested status code is invalid
could_not_find_product n/a A requested product is invalid
could_not_find_station n/a A requested station could not be found or is invalid
could_not_find_tariff_group n/a A requested route code is invalid
invalid_field n/a An invalid value has been specified within a restricted field
over_max_booking_size n/a Number of passengers greater than permitted
sales_restriction n/a Reservations cannot be made on a requested service
service_not_in_roster n/a A requested service could not be found
value_not_unique n/a Returned if the same identifier is used more than once

Booking

Code Message Comment
4 Request does not conform to specification The request included invalid data which cannot be accepted
14 Invalid JSON Request - the request is not valid according to the schema A request does not conform to the schema
503 until-successful retries exhausted. failed: service unavailable (503) -
3016 Could not find a booking with the given bookingNumber {bookingRef} Requested booking could not be found
3034 No logical or physical availability Requested tariff is unavailable
3036 Booking is cancelled -
3084 Tariff {tariff} for item(s) with id(s) REF: {uuid} is/are not bookable due to breaking tariff conditions Not authorised to book this tariff
3165 Booking: Could not allocate seat Requested seat does not exist or is not available
13055 Item in the request not found in the booking Cannot find requested item (e.g. seat) to amend
13058 service {rsid} not found on {date} The requested service could not be found
13068 Tariff {tariff} not configured for specified Tariff Group {route code} -
13080 Sales restriction found for {rsid} Reservations cannot be made on the requested service
13084 Reset seat is not allowed on confirmed items -
13140 Cancel items request requires at least one valid reference id to be passed Cannot find requested item (e.g. seat) to cancel
13208 Could not find a seat from the request in the booking -
13213 Different carriage numbers not allowed when no items have a seat number -
GBR_RARS_6000 Unable to perform this update on a Booking not created by the Reservation Interface & [nature of the error as to why the failure occurred e.g. timeout] -
GBR_RARS_6300 Unknown carrierCode -
GBR_RARS_6301 No inventory configured for Service -
GBR_RARS_6400 Booking updated successfully but final Booking retrieval failed -
GBR_RARS_6401 Unable to perform this update on a Booking not created by the Reservation Interface -
GBR_RARS_6402 Passenger not found [requested passenger uuid] -
GBR_RARS_6403 Unable to blank passenger details -
GBR_RARS_6404 Leg not found [requested leg id] -
GBR_RARS_6405 Successfully cancelled items -
GBR_RARS_6406 Could not find booking with given Service and Seat -
GBR_RARS_6412 Unable to make booking due to Tariff {{tariff}} not configured for specified Tariff Group {{routeCode}} -

Services (Coach)

Code Message Comment
7001 Requested service could not be found The requested service could not be found
7002 Requested station not found on requested service The boardLocation and/or alightLocation are not on this service
7004 Departure station sequence should be before arrival station sequence boardLocation is after the alightLocation in the service's schedule
8002 No schedule found for this service The requested service could not be found
GBR_RARS_6300 Unknown carrierCode -
GBR_RARS_6301 No inventory configured for Service -
GBR_RARS_6302 No Bookings made for Service The service has inventory available but no bookings have yet been made on it
GBR_RARS_6409 No Bookings made for Service Unable to perform booking as all requested products are not fully available
no_record_found error The requested service could not be found

Onboarding and Contact (Rev C)
Revision C: 2025-11-13 13:51:25

To request access to this API, please log a ticket with the Reservations Service Desk via portal or email

Service Desk Support Team Information:

Providing details of your organisation, the API you are requesting access to and the reason for your requested access.

Your request will then be assessed to ensure you have sufficient justification and need to access and use this API.