Reservation System
Seat Structure
Each connection consists of one to multiple (n) carriages. Carriages contain contingents, which are abstract blocks of seats or other elements. The type of contingent determines whether it is a mandatory seat reservation section or a capacity limit. Capacity is used for limited resources, such as animals, bicycles, etc., which can only be sold in limited quantities per carriage but do not have specific assigned seats.
A carriage is identified by its position in the train set and its description.
Connections operate on a route defined by type, connection number (LineNumber) , and, in the case of buses, a suffix. For example, R 1322 is a train on the Liberec - Ústí nad Labem route. Trains run multiple times a day on this route, with each specific connection having its own LineNumber (and possibly running on a different route). The combination of the line and date determines a unique trip of the connection.
Seat Reservation
Retrieving Input Data
To successfully reserve a seat, it is necessary to know the line, the departure and destination stations, and the travel date.
For stations, we use a reference list provided by the endpoint /v1/Constants/GetAllPlaces
. Since the list of stations is extensive, it should be stored locally to avoid excessive communication load from repeated requests.
Using this reference list, we assign specific identifiers to the departure and destination stations. Next, the endpoint /v1/Route/ExtSearch
, is called to retrieve the line number; in the case of transfers, multiple line numbers may be returned.
For example, let's say we want to travel on January 31, 2024, at 6:00 AM from Liberec to Česká Lípa. Liberec has ID=1453, and Česká Lípa has ID=2187. The search returns line "R 1322". If we search for a bus connection, we might receive a result such as "Bus 950157 1" for the Olomouc - Brno route, where 950157 is the line number, and 1 is the suffix. These details will be used in the next request.
Checking Available Capacity
At this point, we need to determine whether the selected connection has available capacity. This requires calling the endpoint /v1/Reservation/ExtGetFreeSeatsCount
with the following parameters (line is a structure derived from the search result):
{ "source": { "type": "sr70", "number": 542126 }, "target": { "type": "sr70", "number": 562090 }, "line": { "prefix": "R", "number": 1322, "suffix": "" }, "date": "2024-01-31T06:00:00.000Z" }
For a bus connection, the structure is as follows (the suffix represents the specific trip number within a given bus line and is mandatory):
{ "source": { "type": "idosbus", "number": 27878 }, "target": { "type": "idosbus", "number": 19053 }, "line": { "prefix": "Bus", "number": 950157, "suffix": "1" }, "date": "2024-01-31T06:00:00.000Z" }
For train connections, the SR70 reference list is used, while for bus connections, the IDOSBUS reference list is applied.
The result will be approximately as follows:
[ { "contingentTypeId": 1, "capacityResult": { "capacity": 63, "available": 54 } } , { "contingentTypeId": 3, "capacityResult": { "capacity": 10, "available": 8 } }, { "contingentTypeId": 4, "capacityResult": { "capacity": 20, "available": 17 } } ]
This means that this connection has one contingent of type 1, which corresponds to a mandatory seat reservation carriage. Its total capacity is 63 seats, with 54 seats remaining. Additionally, a total of 10 bicycle tickets (TypeId=3) can be sold, with 8 still available, and 20 dog tickets (TypeId=4), with 17 available.
List of Contingent Types
Id | ContingentType |
---|---|
1 | Reservation |
2 | Allocation |
3 | Bicycle |
4 | Dog / Animal |
5 | DisabledPerson |
List of Station Codes
Type | Číselník |
---|---|
arriva | Arriva |
uic | UIC |
sr70 | SR70 |
idosbus | idosbus |
Seat Reservation
Let's say we need one reserved seat. We call the endpoint /v1/Reservation/ExtMakeReservations
with the parameters:
{ "source": { "type": "sr70", "number": 542126 }, "target": { "type": "sr70", "number": 568097 }, "line": { "prefix": "R", "number": 1322, "suffix": "" }, "date": "2023-12-05T00:00:00.000Z", "count": 1 }
and we receive a response (returned as an array in case multiple seats were requested):
[ { "externalId": "e99d2d0a-4e40-42ea-bd95-33ccdf48e3eb", "traceFromName": "Liberec", "traceFromSequence": 1, "traceToName": "Česká Lípa hl.n.", "traceToSequence": 4, "expiresAt": "2025-02-18T10:03:11.2063966+01:00", "date": "2025-02-20T00:00:00", "lineNumber": "R 1322", "line": { "prefix": "R", "number": 1322, "suffix": "" }, "routeName": "R14B", "reservationStatus": "Temporary", "vehicleOrder": 1, "reservationType": "Reservation", "seat": { "isAvailable": false, "seatAttributes": [ "Window", "Forward", "V230" ], "isEnabled": false, "description": "41", "orientation": "Forward", "coordX": 0, "coordY": 12, "floor": 1, "vehicle": { "model": "845.P", "sequence": 1, "description": "A", "vehicleAttributes": [ "WiFi", "Silent", "V230" ], "vehicleType": 1, "seatMap": [], "contingents": [], "externalId": "af8f32f7-6d02-4288-8ff6-4816d260c70e", "shiftingExternalId": "791791cb-1ec5-4c13-aaf8-aaa057c8c154" } } } ]
Description of Key Values:
seat describes the selected seat, including its position in the carriage (coordX, coordY) and its attributes (seatAttributes), isAvailable - Is the seat available? isEnabled - For internal purposes.
vehicle provides carriage information. The model represents the carriage type. Important parameters include: sequence (the position of the carriage in the train set) and description, the designation of the carriage for passengers. If the carriage order changes (e.g., an additional carriage is inserted between two others), the sequence value updates, but the description must remain unchanged so passengers do not lose their reference point.
shiftingId is the carriage assignment identifier. How does carriage assignment work? The system has a limited number of carriages, stored as templates that define their layout, seat positions, etc. To include a carriage in a train set, a shifting record is created (shifting). This record links the carriage template with a specific trip (lineInstance) and its position in the train set. (sequence).
externalId is the value used to identify the reservation for future operations. The response also includes route information (traceFromId, traceFromName...), date specifies the travel date and lineNumber indicates the line number.
reservationStatus Temporary means the reservation is temporary and has an automatic expiration time (expiresAt). If not confirmed before expiration, the seat reservation ceases to exist.
Releasing a Temporary Reservation
If the purchase is canceled before confirmation, instead of confirming, the system calls /v1/Reservation/ExtReleaseReservations
with the following parameter:
{ "reservationsExternalIds": [ "193d04af-9dc8-4767-ad6f-9115886a85e6" ] }
This request returns only true/false. The reserved seat is then released for other passengers, without having to wait for the expiration time to pass.
Shortening the Route
Shortening the route of a valid reservation: /v1/Reservation/ShortenReservationRoute
. This is used when reservations are pre-generated to speed up check-in. It is primarily intended for buses. The new destination station must be located before the original destination station on the route. The reservation is modified; unlike seat changes, a new reservation is not generated.
"reservationExternalId": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"newStationToId": 0
}
Changing a Seat
If the automatically assigned seat is not suitable, it can be changed. First, the request /v1/Reservation/ExtGetVehicles
should be called with the following parameter:
{ "source": { "type": "sr70", "number": 542126 }, "target": { "type": "sr70", "number": 568097 }, "line": { "prefix": "R", "number": 1322, "suffix": "" }, "date": "2025-03-05T00:00:00.000Z" }
The response will include a list of ordered carriages, passive elements (items), and seats (seat).
[ { "model": "845.P", "sequence": 1, "description": "A", "vehicleAttributes": [], "seatMap": [ { "description": "Východ", "orientation": "Backward", "externalId": "8be67ae9-0d6e-45c9-ad12-2ba24e7433e9", "coordX": 0, "coordY": 0, "floor": 1, "availability": "Unknown", "itemType": "Exit", "seatAttributes": [] }, { "description": "Prázdný prostor", "orientation": "Backward", "externalId": "5fc6c8ab-edca-4b9f-9e68-a0f947b3050e", "coordX": 1, "coordY": 0, "floor": 1, "availability": "Unknown", "itemType": "Empty", "seatAttributes": [] }, /* .... */ { "description": "11", "orientation": "Backward", "externalId": "2bb66e74-d0de-429a-9d78-7ad01108992b", "coordX": 0, "coordY": 4, "floor": 1, "availability": "Sold", "itemType": "Seat", "seatAttributes": [] }, { "description": "13", "orientation": "Backward", "externalId": "70123deb-4e70-4ab3-a4ab-6f50da18c780", "coordX": 1, "coordY": 4, "floor": 1, "availability": "Available", "itemType": "Seat", "seatAttributes": [] }, { "description": "Ulička", "orientation": "Backward", "externalId": "2acf9a37-0e3e-43f7-a82f-6d9718931aa5", "coordX": 2, "coordY": 4, "floor": 1, "availability": "Unknown", "itemType": "Corridor", "seatAttributes": [] }, { "description": "17", "orientation": "Backward", "externalId": "394c4cfa-7de5-4edc-b890-94b9dc64428e", "coordX": 3, "coordY": 4, "floor": 1, "availability": "Available", "itemType": "Seat", "seatAttributes": [] }, { "description": "15", "orientation": "Backward", "externalId": "766cc612-0185-4ca5-9613-031d74d13fe0", "coordX": 4, "coordY": 4, "floor": 1, "availability": "Available", "itemType": "Seat", "seatAttributes": [] }, /* .... */ ], "contingents": [ { "capacity": 39, "available": 38, "contingentType": "Reservation" }, { "capacity": 24, "available": 24, "contingentType": "Reservation" }, { "capacity": 10, "available": 10, "contingentType": "Bicycle" }, { "capacity": 0, "available": 0, "contingentType": "Disabled" } ], "shiftingId": "29160129-c223-4022-b186-fba25b085377" } ]
The data is condensed. The most important information can be found in the section contingents, which describe what types of reservations the carriage offers (seat reservation, animal, bicycle, disabled passengers, etc.).
In the seatMap structure, the carriage is described, including the coordinates of passive elements (table, aisle, etc.) and, most importantly, the seats. A key attribute is availability, which indicates whether a seat can be occupied. The possible values for availability are: Unknown, Unavailable, Available, Sold and Blocked. Any status other than Available means the seat cannot be sold. (Blocked is used when the system administrator has prohibited seat sales.)
By calling /v1/Reservation/ChangeReservation
with parameters:
{ "reservationExternalId": "193d04af-9dc8-4767-ad6f-9115886a85e6", "seatExternalId": "766cc612-0185-4ca5-9613-031d74d13fe0", "shiftingExternalId": "29160129-c223-4022-b186-fba25b085377" }
where reservationExternalId is the reservation ID, seatExternalId is the requested seat ID, shiftingExternalId is the identifier for the carriage and its position in the train set, it is possible to change the assigned seat within a reservation. Seat changes can only be made for Temporary reservations; once a reservation is confirmed, it cannot be modified.
This function returns a new reservation. The original reservation is automatically released, but it is the client’s responsibility to update their internal reservation ID to the newly returned ID and continue using it.
[ { "seat": { "isAvailable": false, "seatAttributes": [], "isEnabled": false, "description": "15", "orientation": "Backward", "coordX": 4, "coordY": 4, "floor": 1, "vehicle": { "model": "845.P", "sequence": 1, "description": "1", "vehicleAttributes": [], "seatMap": [], "contingents": [], "shiftingId": "29160129-c223-4022-b186-fba25b085377" } }, "externalId": "e3e7abb2-15b1-4b75-bd9e-215eb8d49350", "traceFromId": 1453, "traceFromName": "Liberec", "traceToId": 2187, "traceFromSequence": 1, "traceToName": "Česká Lípa hl.n.", "traceToSequence": 4, "expiresAt": "2024-01-10T21:00:00", "date": "2023-12-05T00:00:00", "lineNumber": "R1322", "routeName": "R14B", "reservationStatus": "Temporary", "vehicleOrder": 1, "reservationType": "Reservation" } ]
Seat Allocation Without a Seat Reservation
This method is used when a limited resource needs to be allocated, but a specific seat is not reserved. Examples include: animals (a limited number of animals may be allowed in a carriage, or animal transport may be prohibited), bicycles (a carriage may have, e.g. 10 hooks for bicycles, meaning no more than 10 bicycle tickets can be sold, but passengers are not assigned a specific hook), non-reserved seat services (used for routes that do not require seat reservations), etc. In addition, it is used for routes without seat reservations.
This scenario applies when the GetFreeSeatsCount continget function returns a contingent of a type other than 1. In such cases, seat allocation is performed using the /v1/Reservation/ExtMakeAllocations
function with the appropriate parameters:
{ "contingentTypeId": 3, "source": { "type": "sr70", "number": 335356 }, "target": { "type": "sr70", "number": 336529 }, "line": { "prefix": "Os", "number": 23234, "suffix": "" }, "date": "2025-12-01T00:00:00.000Z", "count": 2 }
The returned data is similar to a regular reservation, except it does not include details of a specific seat.
[ { "contingentType": "Bicycle", "externalId": "0f717220-a32c-4b64-9932-1cff0444e88a", "traceFromId": 1453, "traceFromName": "Liberec", "traceToId": 2187, "traceFromSequence": 1, "traceToName": "Česká Lípa hl.n.", "traceToSequence": 4, "expiresAt": "2024-01-11T21:23:24.0744351+01:00", "date": "2023-12-05T00:00:00", "lineNumber": "R1322", "routeName": "R14B", "reservationStatus": "Temporary", "vehicleOrder": -1, "reservationType": "Allocation" } ]
The subsequent processing of the result is nearly identical to handling standard reservations. The key difference is that allocations are not tied to a specific seat but must still be released and, most importantly, confirmed just like a standard reserved seat.
Loading an Existing Reservation
To load an existing reservation, you can use the method /v1/Reservation/ExtGetReservation
. This allows you to verify the stored information or the reservation status — for example, whether it was successfully canceled.
Note: If only a temporary reservation has been released, it can no longer be retrieved. The same applies after the reservation period has expired.