Koleo Agent API
Documentation describes basic KOLEO API methods responsible for the sale of a train ticket. All requests have to be sent via HTTPS protocol with VERIFY_PEER option.
Last update: 19-08-2022 Version: 2.0
Changelog
✓ - already implemented
| Date | Version | Done | Description |
|---|---|---|---|
| 2024-04-04 | 2.0 | Add passengers param to GET /connections/{id}/options, GET /connections/{id}/price and POST /connections/{id}/reservation |
|
| 2024-02-23 | 2.0 | ✓ | Add GET /orders/{id}/corrective_notes/{corrective_note_id} |
| 2024-02-20 | 2.0 | ✓ | Add deprecation warning for age param to GET /discount_cards{?age} |
| 2024-01-24 | 2.0 | Add GET /station_announcements, /station_announcements/{station_id}/{type} |
|
| 2022-08-19 | 2.0 | ✓ | Add response to /payments PATCH |
| 2022-08-04 | 2.0 | Add ticket_numbers to order |
|
| 2020-05-13 | 2.0 | ✓ | Add /orders/{id}/details endpoint |
| 2020-04-21 | 2.0 | ✓ | Add is_delayed flag and delay_message to payment |
| 2020-04-01 | 2.0 | ✓ | Add ticket_owners to order |
| 2020-03-10 | 2.0 | ✓ | Add travel_time to train |
| 2020-01-22 | 2.0 | ✓ | Add can_be_exchanged to order |
| 2020-01-16 | 2.0 | Add train_place_types |
|
| 2020-01-16 | 2.0 | Add seat_reservation_status |
|
| 2019-11-20 | 2.0 | ✓ | Add is_two_way to price |
| 2019-11-20 | 2.0 | ✓ | Add is_seat_booking to price |
| 2019-11-20 | 2.0 | ✓ | Add is_seat_booking to order reservation |
| 2019-11-20 | 2.0 | ✓ | Add is_return_booking_available to order |
| 2019-11-20 | 2.0 | ✓ | Add is_booking_after_purchase_available to price |
| 2019-06-11 | 2.0 | ✓ | Update order states info |
| 2018-08-06 | 2.0 | ✓ | Add bus_info to orders/{id} |
| 2018-07-12 | 2.0 | ✓ | Add bike_info to orders/{id} |
| 2018-05-24 | 2.0 | ✓ | Add partial_update to user update |
| 2018-05-24 | 2.0 | ✓ | Add document_notice to ticket |
| 2018-04-11 | 2.0 | ✓ | Add via_stations[] param to connection search |
| 2018-04-03 | 2.0 | ✓ | Add seat reservation documentation |
| 2018-03-30 | 2.0 | ✓ | Add affiliate_code to /user |
| 2018-02-20 | 2.0 | ✓ | Add bookable to /connections |
| 2018-01-31 | 2.0 | ✓ | Add payment_id and is_season to /orders/{id} |
| 2017-12-15 | 2.0 | ✓ | Rename endpoint from /firebase_id to /firebase_token |
| 2017-11-16 | 2.0 | ✓ | Rename endpoint from /firebase_id to /firebase_token |
| 2017-10-30 | 2.0 | ✓ | Change luggages to luggage in every request. |
| 2017-10-05 | 2.0 | ✓ | Add API version control. |
| 2017-09-26 | 2.0 | ✓ | Rename /terms to /user POST. |
| 2017-09-26 | 2.0 | ✓ | Change document_type to document_type_id in /terms and in /user GET and PATCH. |
| 2017-09-24 | 2.0 | ✓ | Add validity_text to prices. |
| 2017-09-19 | 2.0 | ✓ | Remove tariff_names_en and tariff_names_de in /connections/{id}/prices. Use Accept-Language from I18n instead. |
| 2017-09-14 | 2.0 | ✓ | Add /unregistered_price endpoint |
| 2017-08-28 | 2.0 | Rename id in /stations |
|
| 2017-08-28 | 2.0 | ✓ | Change passengers in response. Change time_for_payment to timestamp called payment_deadline. Add relation to extras. |
| 2017-08-28 | 2.0 | ✓ | Change train_types to brand_ids in paginated orders. |
| 2017-08-27 | 2.0 | ✓ | Change request to extras and options only. Change passengers in response. Change time_for_payment to payment_deadline timestamp. Add relation to extras. Change stations to ids, train_types to brand_ids, update validity_limits and tos_dict. |
| 2017-08-27 | 2.0 | ✓ | Remove price from response, add price type (main is old price, alternative is second best offer). Add 404 when offer is special. Change request. |
| 2017-08-27 | 2.0 | ✓ | Change response to options and extras in /connections/{id}/options |
| 2017-08-27 | 2.0 | ✓ | Add start_station_id and end_station_id, deprature and arrival both to connection and to trains. Remove station_name from stops. |
| 2017-08-27 | 2.0 | ✓ | Change change_time in /connections to minutes. Add start_station_id and end_station_id, deprature and arrival both to connection and to trains. Remove station_name from stops. |
| 2017-08-27 | 2.0 | ✓ | Change passengers in /orders/{id}. Change time_for_payment to timestamp called payment_deadline. Add relation to extras. |
| 2017-08-27 | 2.0 | ✓ | Add carrier_id to /brands. |
| 2017-08-27 | 2.0 | ✓ | Add City, region, and country to /stations. |
| 2017-08-19 | 2.0 | ✓ | Change carriers in /connections to brand_ids. Change carrier_name to carrier_id. Change brand_name to brand_id. |
| 2017-08-19 | 2.0 | ✓ | Change train_types in /orders to brand_ids. |
| 2017-08-19 | 2.0 | ✓ | Remove dependent from /discounts and set [] for empty dependent_on_ids. |
| 2017-08-19 | 2.0 | ✓ | Add I18n |
| 2017-08-18 | 2.0 | ✓ | Change train_attributes in connection to train_attribute_ids, and extract special_options to different field. |
| 2017-08-18 | 2.0 | ✓ | Add /carriers, /brands, and /train_attributes. |
I18n
You can specify language of all messages in API by using Accept-Language header. Possible values are pl-PL and en-GB.
Changes from v1
New feature.
-
Request - Example header:
Accept-Language: en-GB,pl-PL -
Response - Example header:
Content-Language: pl-PL
Version Control
You need to declare KOLEO version by using X-KOLEO-Version header, set to the current KOLEO version used in API. In case of major changes in KOLEO your KOLEO version will not match current KOLEO version and you will be asked to update it to comply with latest changes.
You can also declare your client version by using (optional) X-KOLEO-Client header, set to the current client version. In case of major changes in KOLEO your client version may not match current client version in KOLEO and you will be asked to update it to comply with latest changes.
Changes from v1
New feature.
-
Request - Example headers:
X-KOLEO-Version: 3, X-KOLEO-Client: Amadeus-12 (optional) -
Response 426 - when your KOLEO version or KOLEO client version does not match current KOLEO version or current client version::
{ "status": "error", "message": "Upgrade to the latest API version" }
Koleo API [https://koleo.pl/api/v2/agent]
Authentication ¶
Authentication (OAuth 2)
Koleo uses OAuth2 (https://oauth.net/2) specification. You need to add below information for all methods marked with + user_auth:
-
{ "user_auth_id": 123456 }
Which means sending request in selected user’s context. You need to store information about user_id in corresponding user resource in your system.
-
Response 403 (application/json) - invalid user_auth_id provided
{ "status": "error", "message": "Zły user_auth_id" }
Token ¶
TokenPOST/oauth/token
For all methods marked with Authenticated you need to send current Bearer {access_token} in Authorization header.
Example URI
Access Token via passwordHeaders
Content-Type: application/x-www-form-urlencodedBody
{
"grant_type": "client_credentials",
"client_id": "6dca5ab742139339cef374bd6d0c8d5b784972e27205c7bdd073ae8abcb6d473",
"client_secret": "8nksd092jnkfasiofsio230klnaf0923nlfadsio"
}Schema
{
"type": "object",
"properties": {
"grant_type": {
"type": "string"
},
"client_id": {
"type": "string"
},
"client_secret": {
"type": "string"
}
},
"$schema": "http://json-schema.org/draft-04/schema#"
}200Headers
Content-Type: application/jsonBody
{
"access_token": "a61301507558e42330cce431fda6eb75",
"token_type": "Bearer",
"expires_in": 7200,
"refresh_token": "b2accb0da2b89eb1a4b62f5531e939e6"
}Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"access_token": {
"type": "string"
},
"token_type": {
"type": "string"
},
"expires_in": {
"type": "number",
"description": "Time stamp"
},
"refresh_token": {
"type": "string"
}
}
}Revoke an access token ¶
Dictionaries ¶
Stations ¶
- Authenticated
Getting station listGET/stations
city, region, and country may be translated, but please note translation may not always be possible.
hits value represents the popularity rank for the station. The higher the value, the more often the station is searched for.
localized_name represents the translated (optional) name of the station’s official name if it is a foreign station. Please note translated value may not always be present.
Changes from v1
city, region, country, localised_name added.
Example URI
200Headers
Content-Type: application/json
Cache-Control: "max-age=604800, private"Body
[
{
"id": 109,
"name": "Szczecin Port Centralny",
"name_slug": "szczecin-port-centralny",
"latitude": 53.4132263010721,
"longitude": 14.5666745182879,
"hits": 2557,
"ibnr": 8388,
"city": "Szczecin",
"region": "zachodniopomorskie",
"country": "Polska",
"localised_name": null
},
{
"id": 208,
"name": "Szczecin Gumieńce",
"name_slug": "szczecin-gumience",
"latitude": 53.3982221130443,
"longitude": 14.4951734934338,
"hits": 704,
"ibnr": 8381,
"city": "Szczecin",
"region": "zachodniopomorskie",
"country": "Polska",
"localised_name": null
},
{
"id": 273,
"name": "Szczecin Główny",
"name_slug": "szczecin-glowny",
"latitude": 53.4188652228435,
"longitude": 14.5500426972305,
"hits": 2660,
"ibnr": 201,
"city": "Szczecin",
"region": "zachodniopomorskie",
"country": "Polska",
"localised_name": null
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty stations list"
}Discounts ¶
- Authenticated
Getting discount listGET/discounts
Parameter dependent_on_ids means that a passenger with given dependent discount must be selected in order to make it possible to choose this discount.
Parameter rank represents popularity of discount. The lower the value, the more popular the discount is.
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"id": 22,
"passenger_percentage": 0,
"display_passenger_percentage": 0,
"flyer_second_class_percentage": 0,
"flyer_first_class_percentage": 0,
"express_second_class_percentage": 0,
"express_first_class_percentage": 0,
"dependent_on_ids": [],
"name": "Bilet normalny",
"rank": 0,
"season_passenger_percentage": 0,
"displayable": true,
"is_company": false
},
{
"id": 13,
"passenger_percentage": 51,
"display_passenger_percentage": 51,
"flyer_second_class_percentage": 51,
"flyer_first_class_percentage": 0,
"express_second_class_percentage": 51,
"express_first_class_percentage": 0,
"dependent_on_ids": [],
"name": "Doktorant (do 35 lat)",
"rank": 1,
"season_passenger_percentage": 51,
"displayable": true,
"is_company": false
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty discounts list"
}Discount cards ¶
Getting discount card listGET/discount_cards{?age}
Example URI
- age
integer(optional)this parameter is deprecated and should not be sent
200Headers
Content-Type: application/jsonBody
[
{
"id": 1,
"name": "REGIOkarta"
},
{
"id": 2,
"name": "Karta Seniora"
}
]Identity document types ¶
Getting list of types of identity documentsGET/identity_document_types
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"id": 1,
"name": "Dowód osobisty"
},
{
"id": 2,
"name": "Paszport"
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty identity document types list"
}Carriers ¶
Getting carriers listGET/carriers
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"id": 4,
"name": "POLREGIO",
"short_name": "PR",
"slug": "polregio-przewozy-regionalne",
"legal_name": "Przewozy Regionalne"
},
{
"id": 11,
"name": "Szybka Kolej Miejska w Warszawie",
"short_name": "SKM",
"slug": "skm-warszawa",
"legal_name": "Szybka Kolej Miejska w Warszawie"
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty carriers list"
}Brands ¶
Getting brands listGET/brands
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"id": 35,
"name": "Multiregion",
"display_name": "ARRIVARP",
"logo_text": "MR",
"color": "#ADB3B3",
"carrier_id": 1
},
{
"id": 29,
"name": "EIP",
"display_name": "EIP",
"logo_text": "EIP",
"color": "#102C76",
"carrier_id": 2
},
{
"id": 28,
"name": "IC",
"display_name": "IC",
"logo_text": "IC",
"color": "#EF7F0B",
"carrier_id": 2
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty brands list"
}Train Attributes ¶
Getting train_attributes listGET/train_attributes
Rank can be from value 0 to 10. It is priority, so attributes with lower rank should be displayed first. Warning means very important informations (like bus replacement service). In KOLEO we change icon color to yellow for such attributes.
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"id": 201,
"name": "rezerwacja obowiązkowa w 1 klasie",
"short_name": "rezerwacja obowiązkowa w 1 klasie",
"rank": 10,
"warning": false
},
{
"id": 218,
"name": "W pociągu dostępny jest przewijak dla niemowląt",
"short_name": "Przewijak",
"rank": 4,
"warning": false
},
{
"id": 66,
"name": "Zmiana strefy czasowej",
"short_name": "Zmiana strefy czasowej",
"rank": 10,
"warning": true
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty train attributes list"
}Getting single train attributeGET/train_attributes/{id}
Example URI
- id
integer(required)train attribute id
200Headers
Content-Type: application/jsonBody
{
"id": 201,
"name": "rezerwacja obowiązkowa w 1 klasie",
"short_name": "rezerwacja obowiązkowa w 1 klasie",
"rank": 10,
"warning": false
}404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Unknown attribute"
}Station announcements ¶
Getting all available station announcements (restricted access)GET/station_announcements
Example URI
200Headers
Content-Type: application/jsonBody
[
{
"title": "Attention! Communication difficulties for Kraków Główny and Kraków Płaszów stations",
"short_text": "In connection with the modernisation of the Krakow railway junction some trains PKP Intercity bypass the Kraków Główny or Kraków Płaszów station "
"long_text": "Modernisation of the Kraków railway junction some PKP Intercity trains bypass Kraków Główny station and they travel from Kraków Płaszów station. In case you are unable to find a connection you are looking for please, try to enter from Kraków Płaszów station. You will find more information on the website www.intercity.pl and the check-in counters."
"station_id": 1234,
'type": "End",
},
{
"title": "Attention! Communication difficulties for Kraków Główny and Kraków Płaszów stations",
"short_text": "In connection with the modernisation of the Krakow railway junction some trains PKP Intercity bypass the Kraków Główny or Kraków Płaszów station "
"long_text": "Modernisation of the Kraków railway junction some PKP Intercity trains bypass Kraków Główny station and they travel from Kraków Płaszów station. In case you are unable to find a connection you are looking for please, try to enter from Kraków Płaszów station. You will find more information on the website www.intercity.pl and the check-in counters."
"station_id": 4321,
"type": "Start",
}
]404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Empty station announcements list"
}403Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Additional permissions required"
}User & Profile ¶
User ¶
-
Authenticated
-
user_auth
RegistrationPOST/user
This request is used to denote that the user has agreed to the terms of use of KOLEO. The user will be registered with provided parameters.
Parameter document_type_id has a value taken from the appropriate method (/identity_document_types). Birthday field is used to determine discounts depending on age.
Changes from v1
Registration used to be /terms it was changed because we are creating user here. Change document_type to document_type_id.
Example URI
JSON MessageHeaders
Content-Type: application/jsonBody
{
"agreed_to_terms": true,
"email": "test@example.com",
"name": "AAAA",
"surname": "BBBBBB",
"document_number": "AZX123456",
"document_type_id": 1,
"birthday": "1990-01-01",
"discount_id": null,
"discount_card_ids": [
1,
2
],
"password": "LubięPlacki"
}201Headers
Content-Type: application/jsonBody
{
"status": "created",
"user_id": 1234567
}200Headers
Content-Type: application/jsonBody
{
"status": "existed",
"user_id": 1234567
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Email already taken"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Undetermined error"
}Getting dataGET/user
Changes from v1
Change document_type to document_type_id. affiliate_code added.
Example URI
202Headers
Content-Type: application/jsonBody
{
"agreed_to_terms": true,
"privacy_accepted": true,
"email": "example11@example.com",
"name": "Anna",
"surname": "Beta",
"document_number": "AZX123456",
"document_type_id": 1,
"birthday": "1990-01-01",
"discount_id": 22,
"discount_card_ids": [],
"affiliate_code": null
}Updating dataPATCH/user
Changes from v1
Change document_type to document_type_id.
Parameter partial_update is optional and when set to true partial user update is possible: you can send a request with incomplete parameter set.
Example URI
JSON MessageHeaders
Content-Type: application/jsonBody
{
"agreed_to_terms": true,
"name": 'AAAA',
"surname": 'BBBBBB',
"document_number": 'AZX123456',
"document_type_id": 1,
"birthday": '1990-01-01',
"discount_id": null,
"discount_card_ids": [1],
"partial_update": true // optional
}202Headers
Content-Type: application/jsonBody
{
"status": "changed",
"user_id": 1234567
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Undetermined error"
}Company ¶
-
Authenticated
-
user_auth
Getting dataGET/user/company
Returns user’s company needed for invoice
Example URI
200Headers
Content-Type: application/jsonBody
{
"company": {
"name": "Astarium sp. z o.o.",
"nip": "1132854509",
"street": "Rondo ONZ 1",
"postal_code": "00-124",
"city": "Warszawa"
}
}Create companyPOST/user/company
Create company for user to get invoice
Example URI
JSON MessageHeaders
Content-Type: application/jsonBody
{
"name": "Astarium sp. z o.o.",
"nip": "1132854509",
"street": "Rondo ONZ 1",
"postal_code": "00-124",
"city": "Warszawa"
}200Headers
Content-Type: application/jsonBody
{
"company": {
"name": "Astarium sp. z o.o.",
"nip": "1132854509",
"street": "Rondo ONZ 1",
"postal_code": "00-124",
"city": "Warszawa"
}
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Saving company data failed"
}Update companyPATCH/user/company
Updates user’s company
Example URI
JSON MessageHeaders
Content-Type: application/jsonBody
{
"name": "TEST sp. z o.o.",
"nip": "1132854509",
"street": "Rondo ONZ 1",
"postal_code": "00-124",
"city": "Warszawa"
}200Headers
Content-Type: application/jsonBody
{
"company": {
"name": "TEST sp. z o.o.",
"nip": "1132854509",
"street": "Rondo ONZ 1",
"postal_code": "00-124",
"city": "Warszawa"
}
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Saving company data failed"
}Delete companyDELETE/user/company
Delete user’s company
Example URI
200Headers
Content-Type: application/jsonBody
{
"message": "company was successfully deleted"
}500Headers
Content-Type: application/jsonBody
{
"error": "company was not deleted"
}Orders ¶
-
user_auth
-
Authenticated
Order can be in one of the possible states:
-
created- it was created by user and can be eitherpaid,cancelledorabandonednext -
payment_verified- the payment was verified, but tickets are not yet generated -
paid- it was paid by user, PDF tickets were generated and sent by email -
finished- journey associated with order has finished more than 3 hours from now (order’s connection’sstart_dateis older than now - 3 hours); if order contains season tickets, it becomes finished after the validity period of such ticket ends -
rated- user rated quality of ordered journey (KOLEO allows user to rate a finished order in all of the following criteria - comfort, cleanliness and punctuality) -
refunded- a previouslypaidorder was returned by user and all of the order’sreturnable_pricewas already refunded -
carrier_refunded- it was returned by KOLEO customer care employee, possibly ommiting carrier’s cancellation fee -
auto_refunded- it was automatically returned by KOLEO system when system failed to issue a ticket -
being_exchanged- the exchange process was started by user, from now on order’s exchange can be either cancelled and return order topaidstate or finished and transition order toexchangedstate -
being_refunded- the refund process was started by user, customer care employee has to finalize or cancel refund -
exchanged- it was exchanged to another order (newly created order has anexchanged_order_idfilled with this orderid) -
abandoned- user did not pay for order before it was possible (5 minutes before journey starts) -
cancelled- user decided not to buy this order
Get list of user ordersGET/orders{?carrier_id}
Status field will have one of the above state values.
returnable_price is an amount that should be refunded to user in case of a return process. It is usually smaller than the ticket price, thus the user should always be notified before finishing the return that each carrier sets its individual cancellation fee in the Carriage Terms and Conditions and it will be deducted from the initial ticket price.
is_return_booking_available means that searching for return journey should be enabled for the same day with a shortcut. It is false for most orders, true only for LKA Sprinter two way orders with seat booking.
Changes from v1
Changed train_types to brand_ids. Changed station_from and station_to to start_station_id and end_station_id. Change season to is_season flag.
Example URI
- carrier_id
integer(optional)only orders with specified carrier ID
200Headers
Content-Type: application/jsonBody
[
{
"id": 1234,
"start_station_id": 33605,
"end_station_id": 80416,
"start_datetime": "2016-03-29T15:40:00.000+02:00",
"end_datetime": "2016-03-29T15:40:00.000+02:00",
"can_be_returned": true,
"can_be_exchanged": false,
"brand_ids": [
1,
2,
4
],
"changes": 2,
"price": "12.36",
"returnable_price": "11.12",
"status": "paid",
"connection_id": 123456,
"payment_id": 1233,
"is_season": false,
"is_zonal": false,
"is_network": false,
"seats_reservations": [
{
"train_nr": "19100",
"seats": [
{
"carriage_nr": 1,
"seat_nr": 41
},
{
"carriage_nr": 1,
"seat_nr": 42
}
]
}
],
"name": "Ozorków - Zgierz",
"valid_from": "2020-11-09T18:38:00.000+01:00",
"valid_to": "2020-11-09T23:59:00.000+01:00",
"is_renewable": false,
"is_return_booking_available": false,
"is_travel_plan_available": true,
"ticket_owners": [
"Luke Skywalker",
"Han Solo"
],
"ticket_numbers": [
61540055,
61540050
],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}
]Get list of user ordersGET/orders/{filters}{?carrier_id}
Filter orders with following paths: /orders/active, /orders/inactive, /orders/season, /orders/active/season, /orders/inactive/season, orders/season/active, orders/season/inactive
active gets only orders with status fields:
“created”, “paid”, “being_exchanged”, “payment_verified”, “being_refunded”
inactive gets only orders with status fields:
“rated”, “cancelled”, “refunded”, “carrier_refunded”, “auto_refunded”, “exchanged”, “finished”, “abandoned”
If no active or inactive filter orders with one of following status fields:
‘created’, ‘payment_verified’, ‘paid’, ‘finished’, ‘rated’, ‘refunded’, ‘carrier_refunded’, ‘auto_refunded’, ‘exchanged’, ‘being_exchanged’, ‘being_refunded’
is_season gets only orders where tariff has season = true. If no season filter: only orders where tariff has season = false or orders with no tariff
is_return_booking_available means that searching for return journey should be enabled for the same day with a shortcut. It is false for most orders, true only for LKA Sprinter two way orders with seat booking.
Changes from v1
Changed train_types to brand_ids. Changed station_from and station_to to start_station_id and end_station_id. Change season to is_season flag.
Example URI
- filters
string(required)filters as described above
- carrier_id
integer(optional)only orders with specified carrier ID
200Headers
Content-Type: application/jsonBody
[
{
"id": 1234,
"start_station_id": 33605,
"end_station_id": 80416,
"start_datetime": "2016-03-29T15:40:00.000+02:00",
"end_datetime": "2016-03-29T15:40:00.000+02:00",
"can_be_returned": true,
"can_be_exchanged": false,
"brand_ids": [
1,
2,
4
],
"changes": 2,
"price": "12.36",
"returnable_price": "11.12",
"status": "paid",
"connection_id": 123456,
"payment_id": 1233,
"is_season": false,
"is_zonal": false,
"is_network": false,
"seats_reservations": [
{
"train_nr": "19100",
"seats": [
{
"carriage_nr": 1,
"seat_nr": 41
},
{
"carriage_nr": 1,
"seat_nr": 42
}
]
}
],
"name": "Ozorków - Zgierz",
"valid_from": "2020-11-09T18:38:00.000+01:00",
"valid_to": "2020-11-09T23:59:00.000+01:00",
"is_renewable": false,
"is_return_booking_available": false,
"is_travel_plan_available": true,
"ticket_owners": [
"Luke Skywalker",
"Han Solo"
],
"ticket_numbers": [
61540055,
61540050
],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}
]Get list of user orders paginatedGET/paginated_orders{?carrier_id,page,per_page}
Orders paginated
Status field will have one of the following values: ‘created’, ‘payment_verified’, ‘paid’, ‘finished’, ‘rated’, ‘refunded’, ‘carrier_refunded’, ‘auto_refunded’, ‘exchanged’, ‘being_exchanged’, ‘being_refunded’
Changes from v1
Changed train_types to brand_ids. Changed station_from and station_to to start_station_id and end_station_id. Change season to is_season flag.
Example URI
- carrier_id
integer(optional)only orders with specified carrier ID
- page
integer(optional)which page, default: 1
- per_page
integer(optional)how many records per page, default: 30
200Headers
Content-Type: application/jsonBody
{
"current_page": 1,
"per_page": 30,
"total_results": 22,
"orders": [
{
"id": 1234,
"start_station_id": 33605,
"end_station_id": 80416,
"start_datetime": "2016-03-29T15:40:00.000+02:00",
"end_datetime": "2016-03-29T15:40:00.000+02:00",
"can_be_returned": true,
"can_be_exchanged": false,
"brand_ids": [
1,
2,
4
],
"changes": 2,
"price": "12.36",
"returnable_price": "11.12",
"status": "paid",
"connection_id": 123456,
"payment_id": 1233,
"is_season": false,
"is_zonal": false,
"is_network": false,
"seats_reservations": [
{
"train_nr": "19100",
"seats": [
{
"carriage_nr": 1,
"seat_nr": 41
},
{
"carriage_nr": 1,
"seat_nr": 42
}
]
}
],
"name": "Ozorków - Zgierz",
"valid_from": "2020-11-09T18:38:00.000+01:00",
"valid_to": "2020-11-09T23:59:00.000+01:00",
"is_renewable": false,
"is_return_booking_available": false,
"is_travel_plan_available": true,
"ticket_owners": [
"Luke Skywalker",
"Han Solo"
],
"ticket_numbers": [
61540055,
61540050
],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}
]
}Get list of user orders paginatedGET/paginated_orders/{filters}{?carrier_id}{?page}{?per_page}
Apply rules from above orders paginated and filtered orders (active / inactive / season)
Changes from v1
Changed train_types to brand_ids. Changed station_from and station_to to start_station_id and end_station_id. Change season to is_season flag.
Example URI
- filters
string(required)filters as described above
- carrier_id
integer(optional)only orders with specified carrier ID
- page
integer(optional)which page, default: 1
- per_page
integer(optional)how many records per page, default: 30
200Headers
Content-Type: application/jsonBody
{
"current_page": 1,
"per_page": 30,
"total_results": 22,
"orders": [
{
"id": 1234,
"start_station_id": 33605,
"end_station_id": 80416,
"start_datetime": "2016-03-29T15:40:00.000+02:00",
"end_datetime": "2016-03-29T15:40:00.000+02:00",
"can_be_returned": true,
"can_be_exchanged": false,
"brand_ids": [
1,
2,
4
],
"changes": 2,
"price": "12.36",
"returnable_price": "11.12",
"status": "paid",
"connection_id": 123456,
"payment_id": 1233,
"is_season": false,
"is_zonal": false,
"is_network": false,
"seats_reservations": [
{
"train_nr": "19100",
"seats": [
{
"carriage_nr": 1,
"seat_nr": 41
},
{
"carriage_nr": 1,
"seat_nr": 42
}
]
}
],
"name": "Ozorków - Zgierz",
"valid_from": "2020-11-09T18:38:00.000+01:00",
"valid_to": "2020-11-09T23:59:00.000+01:00",
"is_renewable": false,
"is_return_booking_available": false,
"is_travel_plan_available": true,
"ticket_owners": [
"Luke Skywalker",
"Han Solo"
],
"ticket_numbers": [
61540055,
61540050
],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}
]
}Order ¶
-
user_auth
-
Authenticated
Get order (pdf)GET/orders/{id}{?carrier_id}
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- carrier_id
integer(optional)carrier ID whose order we want to get
PDFHeaders
Content-Type: application/pdf200The response is a ticket in the PDF format.
Headers
Content-Type: application/pdf403Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Ticket cannot be printed"
}Get detailsGET/orders/{id}/details
-
user_auth
-
Authenticated
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
200Headers
Content-Type: application/jsonBody
{
"id": 1234,
"start_station_id": 33605,
"end_station_id": 80416,
"start_datetime": "2016-03-29T15:40:00.000+02:00",
"end_datetime": "2016-03-29T15:40:00.000+02:00",
"can_be_returned": true,
"can_be_exchanged": false,
"brand_ids": [
1,
2,
4
],
"changes": 2,
"price": "12.36",
"returnable_price": "11.12",
"status": "paid",
"connection_id": 123456,
"payment_id": 1233,
"is_season": false,
"is_zonal": false,
"is_network": false,
"seats_reservations": [
{
"train_nr": "19100",
"seats": [
{
"carriage_nr": 1,
"seat_nr": 41
},
{
"carriage_nr": 1,
"seat_nr": 42
}
]
}
],
"name": "Ozorków - Zgierz",
"valid_from": "2020-11-09T18:38:00.000+01:00",
"valid_to": "2020-11-09T23:59:00.000+01:00",
"is_renewable": false,
"is_return_booking_available": false,
"is_travel_plan_available": true,
"ticket_owners": [
"Luke Skywalker",
"Han Solo"
],
"ticket_numbers": [
61540055,
61540050
],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}403Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Ticket cannot be displayed"
}Refund orderDELETE/orders/{id}{?carrier_id}
After this request the ticket will be returned, and appropriate resources will be refunded to KOLEO account.
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- carrier_id
integer(optional)carrier ID whose order we want to get
200Headers
Content-Type: application/jsonBody
{
"refunded_amount": "11.30"
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Order cannot be refunded"
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "The order is in the process of being returned. Refresh the view in a few seconds"
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Carrier is having a technical break, so it is impossible to refund the ticket at the moment."
}500Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Ticket refund error, try again"
}Get invoicesGET/orders/{id}/invoices{?carrier_id}
Depending on tickes issued for provided order, appropriate invoices assigned to each carrier would be provided, so one order can have multiple invoices Corrective invoices are generated after tickets refund, if any invoices were issued before refund process.
‘carrier_id’ - id associated with the carrier that is issuer of the invoice.
‘name’ - name associated with the invoice.
is_corrective - means this is corrective invoice.
‘downloaded_at’ - the date and time the invoice was downloaded - nil if it hasn’t been downloaded yet.
‘corrective_notes’ - corrective notes associated with the invoice - [] if no corrective notes exist.
For example order with pr and kd tickets will have two invoices (files); one with carrier_id equal to 4 (4 stands for PR), another one with carried_id equal to 6 (6 stands for KD). If corrective invoice will be generated, it will have total 6 documents:
-
Inovoice PR - with ‘carrier_id’ equal to 6
-
Invoice KD - with ‘carrier_id’ equal to 4
-
Corrective Invoice PR - with
is_correctiveflag and ‘carrier_id’ as 4 -
Corrective Invoice KD - with
is_correctiveflag and ‘carrier_id’ as 6 -
Corrective Note - corrective note associated with Corrective Invoice PR with ‘id’ 1231
-
Corrective Note - corrective note associated with Corrective Invoice KD with ‘id’ 1232
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- carrier_id
integer(optional)carrier ID whose order we want to get
200Headers
Content-Type: application/jsonBody
[
{
"number": "KOLEO/1/123123123/PR",
"id": 123,
"carrier_id": 4,
"is_corrective": false,
"downloaded_at": "2024-02-23T13:44:25.024+01:00",
"name": "Faktura PR",
"corrective_notes": []
},
{
"number": "KOR/123123123/PR",
"id": 1234,
"carrier_id": 4,
"is_corrective": true,
"downloaded_at": "2024-02-23T14:30:06.773+01:00",
"name": "Faktura korygująca PR",
"corrective_notes": [
{
"id": 143,
"name": "Nota księgowa PR",
"downloaded_at": "2024-02-23T14:50:30.002+01:00"
}
]
}
]Get invoiceGET/orders/{id}/invoices/{invoice_id}{?carrier_id}
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- invoice_id
integer(required)invoice ID (returned by the Get invoices)
- carrier_id
integer(optional)carrier ID whose order we want to get
200Headers
Content-Type: application/pdfBody
The response is a invoice in pdf formatCreate invoicePOST/orders/{id}/invoices?{carrier_id}
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- carrier_id
integer(optional)carrier ID whose order we want to get
200Headers
Content-Type: application/jsonBody
{
"invoice_ids": [
1268
]
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Invoice could not be created"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Unfortunately, an invoice can only be generated until the 15th of the month following the month of purchase"
}Get corrective noteGET/orders/{id}/corrective_notes/{corrective_note_id}
Example URI
- id
integer(required)order ID (returned by the payment confirmation or order list)
- corrective_note_id
string(required)corrective note ID (returned by invoices list when correctvie invoice has a corrective note)
200Headers
Content-Type: application/pdfBody
The response is a corrective note in pdf formatSearch & Booking Flow ¶
Connections ¶
GET/connections
-
user_auth
-
Authenticated
This method is used to search connections (6 max) for given parameters in query object. The response is an array of connection objects.
Request accepts 3 optional filtering parameters -
-
only_direct-truewill result in connections with no changes unless you providevia_stations- in this case your results could include connections with changes -
only_purchasable-truewill result in connections possible to purchase through KOLEO (those withpurchasabletrue) -
carrier_ids- you can narrow down a list of carriers to only desired ones -
brand_ids- you can narrow down a list of brands to only desired ones. If used, carrier_ids will be ignored
Trains will be returned in the correct order inside trains array. Stops contain all the train stops. If we want to select only those from current travel we have to use parameter in_path.
In stops, fields train_nr and brand_name mean that this is the first stop of the train after changing number. Field next_day with true value means that the train arrives at the stop after midnight.
In train array, the field train_attributes contains information about train attributes:
class_available if we can choose train class, carriage_types_available if we can choose carriage type, extras_available if we can pay extra for bigger luggage or dog, bikes_available if we can pay extra for a bike.
travel_time in connection and train is provided in minutes.
Changes from v1
Change carriers in /connections to brand_ids.
Remove carrier_id from trains as carriers are associated with brands. Change brand_name to brand_id. Change train_attributes in trains to train_attribute_ids and extract special_options to different endpoint. Add start_station_id, end_station_id, deprature and arrival both to connection and to trains.
Remove station_name from stops and add exit_only, entry_only, platform and track.
Change change_time and travel_time in /connections to minutes.
Example URI
JSON MessageHeaders
Content-Type: application/jsonBody
{
"query":
{
"start_station": "warszawa-centralna", (String) - name_slug from the list of station
"end_station": "krakow-glowny", (String) - name_slug from the list of station
"date": "29-03-2016T12:30:00",
"only_direct": true,
"only_purchasable": false,
"carrier_ids": [1, 2, 3],
"via_stations": ["elk", "bialystok"]
}
}200Headers
Content-Type: application/jsonBody
{
"connections":
[
{
"id": 1234,
"distance": 290,
"purchasable": false,
"purchasable_errors": [
{
"type": "non_purchasable_carrier",
"value": "Nie sprzedajemy jeszcze biletów na połączenia tego przewoźnika."
}
],
"bookable": true,
"travel_time": 33,
"changes": 1,
"needs_document": false,
"brand_ids": [
3,
3
],
"departure": "2016-03-29T15:47:00.000+02:00",
"arrival": "2016-03-29T16:20:00.000+02:00",
"special_event_slug": null,
"is_advanced_travel_options": false,
"is_child_birthday_required": false,
"max_passengers_count": 6,
"constriction_info": []
"trains":
[
{
"id": 265277,
"train_nr": 8300,
"train_name": 8300,
"train_full_name": "90943",
"run_desc": "29.III-31.III;",
"change_time": null,
"train_id": 6044420,
"brand_id": 1,
"train_attribute_ids": [1, 32, 201],
"start_station_id": 33605,
"end_station_id": 80416,
"bookable": true,
"departure": "2016-03-29T15:47:00.000+02:00",
"arrival": "2016-03-29T16:20:00.000+02:00",
"stops":
[
{
"arrival": "2016-03-29T13:55:00.000+02:00",
"departure": "2016-03-29T13:56:00.000+02:00",
"distance": 0,
"in_path": false,
"station_id": 33605,
"next_day": false,
"position": 1,
"train_nr": null,
"brand_id": null,
"exit_only": false,
"entry_only": false,
"platform": "IV",
"track": 3
},
{
"arrival": "2016-03-29T15:32:00.000+02:00",
"departure": "2016-03-29T15:34:00.000+02:00",
"distance": 344861,
"in_path": false,
"train_id": true,
"station_id": 33506,
"next_day": false,
"position": 2,
"train_nr": null,
"brand_id": 3,
"exit_only": false,
"entry_only": false,
"platform": "I",
"track": 1
}
],
"carriages":
[
{
"nr": 1,
"bookable": true,
"carriage_type_id": 1
},
{
"nr": 2,
"bookable": true,
"carriage_type_id": 1
},
{
"nr": 3,
"bookable": false,
"carriage_type_id": 1
}
],
"direction": "left",
"travel_time": 30,
"fixed_carriage_composition": true,
"is_option_groups_available": false
}
]
}
]
}422Body
{
"status": "error",
"message": "Take a walk :)"
}404Body
{
"status": "error",
"message": "Cannot find connection"
}Connection ¶
-
user_auth
-
Authenticated
Checking the options for connectionGET/connections/{id}/options
Returns available options for connection, including prices for dogs, luggage etc.
train_classes are deprecated and will no longer be calculated.
[Deprecated] If you only want to get options for main user, you can simply omit the body, and if you want to get options also for fellow passengers, please add body to the request. Those rules applies only for deprecated structure of passengers.
Options included in response depends on number of provided passengers.
Recommended structure of provided passengers requires including all passengers. Using new data structure and passing no passengers will result with an error.
Changes from v1
Change response to options and extras. Change luggages to luggage.
-
user_auth
-
Authenticated
Example URI
- id
integer(required)connection ID (returned by the search method)
JSON MessageHeaders
Content-Type: application/jsonBody
// Deprecated
{
"normal_passengers": [
"Angela Abar"
],
"reduced_passengers":
{
20:
[
"Jon Osterman"
]
}
}
// Recommended
{
"passengers": [
{
"name": "Angela Abar",
"discount_id": 20,
"discount_card_ids": [ // optional
2,
1
],
"ticket_owner": true
},
{
"name": "Jon Osterman",
"discount_id": 21,
"discount_card_ids": [ // optional
1
],
"ticket_owner": false
}
]
}200Headers
Content-Type: application/jsonBody
{
"extras": [
{
"type": "bikes",
"values": [
{
"id": 0,
"name": "Bez roweru",
"price": "0"
},
{
"id": 1,
"name": "1 rower",
"price": "7.0"
},
{
"id": 2,
"name": "2 rowery",
"price": "14.0"
},
{
"id": 3,
"name": "3 rowery",
"price": "21.0"
}
]
},
{
"type": "luggage",
"values": [
{
"id": 0,
"type": "Bez bagażu",
"price": "0"
},
{
"id": 1,
"name": "1 bagaż",
"price": "3.0"
},
{
"id": 2,
"name": "2 bagaże",
"price": "6.0"
},
{
"id": 3,
"name": "3 bagaże",
"price": "9.0"
}
]
}
],
"options": [
{
"type": "train_classes",
"values": [
{
"id": 1,
"name": "1 klasa",
"price": "0",
"selected": true
},
{
"id": 2,
"name": "2 klasa",
"price": "-23.0",
"selected": false
}
]
},
{
"type": "carriages",
"values": [
{
"id": 1,
"name": "bezprzedziałowy",
"price": 0,
"selected": false
},
{
"id": 2,
"name": "bezprzedziałowy przy większym stoliku",
"price": 0,
"selected": false
},
{
"id": 3,
"name": "przedziałowy",
"price": 0,
"selected": false
}
]
},
{
"type": "seats",
"values": [
{
"id": 1,
"name": "okno",
"selected": true
},
{
"id": 2,
"name": "korytarz",
"selected": false
}
]
}
]
}400Body
{
"status": "error",
"message": "Invalid discount set selected"
}404Body
{
"status": "error",
"message": "Cannot find connection"
}Checking for prices for connectionsGET/connections/{id}/price{?normal_passengers,reduced_passengers,options}
Returns the price in the form of 12.35 for connection with given ID and optional extras and options. By default it will use selected user’s passengers.
Parameter uncertain means that price may change after reservation (e.g. offer is contingent and we don’t know the exact price before purchase) - the price may be different than the one obtained from /reservation request.
Note: Seats selection is valid only when buying a single ticket.
is_seat_booking informs if the price is for seat booking (0 zł) - if so it requires different call to action buttons, for example “book seat” instead of “buy ticket”.
is_booking_after_purchase_available informs that seat booking for the return part of the journey will be available after the purchase. It’s true only for prices in two way tariffs.
Lack of price with type alternative means that there is no alternative offer.
For standard price you can simply omit the body, if you want price with extras or options please add body to the request.
For deprecated passengers structure: If you don’t specify any passenger in the request, you’ll get price for main passenger.
Example: normal_passengers[]=Angela Abar&normal_passengers[]=Adrian Veidt&reduced_passengers[20][]=Jon Osterman&reduces_passengers[21][]=Walter Kovacs&reduced_passengers[21][]=Laurie Juspeczyk&options[dogs]=3&options[bikes]=1&options[class]=2&options[seats]=2&options[luggages]=3
For recommended passengers structure: If you don’t specify any passenger in the request, you’ll get an error.
Note that only one passenger is permitted to have param ticket_owner set to true
Changes from v1
Remove price from response, add price type (main is old price, alternative is second best offer). Add 404 when offer is special. Change request. Remove tariff_names_en and tariff_names_de in /prices. Use Accept-Language from I18n instead. Add validity_text to prices. Change luggages to luggage.
Example URI
- id
integer(required)connection ID (returned by the search method)
- normal_passengers
string(required)normal_passengers[] name and surnames of normal passengers
- reduced_passengers
string(required)reduced_passengers[{discount_id}][] name and surnames of passengers with disocunt with id
discount_id- options
string(required)options[{option_name}] additional options
JSON MessageHeaders
Content-Type: application/jsonBody
{
// Deprecated
"normal_passengers": [
"Angela Abar",
"Adrian Veidt"
],
"reduced_passengers":
{
20:
[
"Jon Osterman"
],
21:
[
"Walter Kovacs",
"Laurie Juspeczyk"
]
},
// Recommended
"passengers": [
{
"name": "Angela Abar",
"discount_id": 20,
"discount_card_ids": [ // optional
2,
1
],
"ticket_owner": true
},
{
"name": "Jon Osterman",
"discount_id": 21,
"discount_card_ids": [ // optional
1
],
"ticket_owner": false
}
]
"extras": [
{
"type": "bikes",
"id": 1
},
{
"type": "luggage",
"id": 1
}
],
"options": [
{
"type": "seats",
"id": 1
}
]
}200When no second best price is available there is only one price in “prices”.
Headers
Content-Type: application/jsonBody
{
"prices":
[
{
"value": 12.35,
"tariff_names": ["STREFOWY JEDNORAZOWY"],
"tariff_ids": [2],
"validity": [
{
"tariff_id": 2,
"tariff_name": "STREFOWY JEDNORAZOWY",
"valid_from": "2016-03-29T15:34:00.000+02:00",
"valid_to": "2016-03-29T18:34:00.000+02:00"
}
],
"validity_text": "Valid 3 horus from 15:34",
"area_extract": nil,
"document_required": false,
"changes_allowed": false,
"uncertain": false,
"season": false,
"extras_available": true,
"return_tariff": false,
"valid_price": true,
"errors": [],
"requires_main_ticket_nr": false,
"main_ticket_nr_info": "",
"is_seat_booking": false,
"is_booking_after_purchase_available": false,
"is_two_way": false,
"is_options_reload_required": true,
"type": "main"
},
{
"value": 12.35,
"tariff_names": ["CZASOWY"],
"tariff_ids": [3],
"validity": [
{
"tariff_id": 3,
"tariff_name": "CZASOWY",
"valid_from": "2016-03-29T00:00:00.000+02:00",
"valid_to": "2016-03-29T23:59:59.000+02:00"
}
],
"validity_text": "Valid 2016-03-29",
"area_extract": nil,
"document_required": false,
"changes_allowed": false,
"uncertain": false,
"season": false,
"extras_available": true,
"return_tariff": false,
"valid_price": true,
"errors": [],
"requires_main_ticket_nr": false,
"main_ticket_nr_info": "",
"is_seat_booking": false,
"is_booking_after_purchase_available": false,
"is_two_way": false,
"is_options_reload_required": true,
"type": "main"
}
]
}404When offer is special and price is unavailable.
Body
{
"status": "error",
"message": "Cena niedostępna"
}Places types for train in connectionPOST/train_place_types/{connection_id}(?/{train_nr})
This enpoint should be used on traveloptions. After selecting tariff for connection client should ask for available places types.
Place types are recursive, so each place can have place_types (and corresponding place_types_label, which should be shown to user). If place_type has no place_types it’s final type, and should be passed to /booking and /connections/{connection_id}/reservation methods.
The highest level place type is a kind of wrapper, which has dynamic attributes (price, bookable, available, selected) taken from level below, and static attributes (name, unavailable_help_text, uncertain) set to null.
The only attribute of the wrapper is the place_types_label. The reason of wraper is to have label over first level choice.
Main places types are:
-
seated Car - most of the times it has 1st, and 2nd class as place types (in PKP Intercity), or Business, Economy and Premium in LEO Express.
-
couchette Car - have different people capacity as place types
-
sleeping Car - have different people capacity as place_types, and can be male, or female only.
In regional trains only one seat_type is available: seatedCar with 2nd class. If only one place type is available it shouldn’t be shown to an user.
It is possible to ask only for place type for one train nr by specyfing train_nr. Otherwise place type for whole connection will be shown.
| Field | Description |
|---|---|
| id | Id |
| name | Localised name, show this to the user. |
| available | Can this place type be selected? Some places types can already be booked or unavailable in selected tariff. |
| unavailable_help_text | Localised message why this filed is unavialable |
| selected | Preselected field by backend. There may, or may not be some place type selected |
| price | Price for this place type |
| uncertain | If set to yes, price may be higher, we should show “Price from XX.xx” |
| bookable | Does this place type requires booking of place? |
| place_types_label | Show this to a user over place types selection |
| place_types | If this table is not empty, it’s not a final choice, and user should select type from provided array. |
Example URI
- connection_id
integer(required)connection ID (returned by the search method)
- train_nr
string(required)
JSON MessageHeaders
Content-Type: application/jsonBody
{
tariff_ids: [665, 432]
}200Headers
Content-Type: application/jsonBody
[
{
"train_nr": "15432",
"place_type":
{
"id": 11,
"name": "",
"available": true,
"unavailable_help_text": "",
"selected": true,
"price": "232.6",
"uncertain": true,
"bookable": true,
"place_types_label": "Wybierz rodzaj miejsca",
"place_types": [
{
"id": 1,
"name": "miejsce siedzące"
"available": true,
"unavailable_help_text": "",
"selected": true,
"price": 24.55,
"uncertain": true,
"bookable": true,
"place_types_label": "Wybierz klasę podróży",
"place_types": [
{
"id": 30,
"name": "Druga klasa bez gwarancji miejsca",
"available": "true,
"unavailable_help_text": "",
"selected": true,
"price": 24.55,
"uncertain": false,
"bookable": false,
"place_types": []
},
{
"id": 32,
"name": "Druga klasa",
"available": "true ,
"unavailable_help_text": "",
"selected": true,
"price": 24.55,
"uncertain": false,
"bookable": true,
"place_types": []
},
{
"id": 31,
"name": "Pierwsza klasa",
"available": "true,
"unavailable_help_text": "",
"selected": false,
"price": 54.00,
"uncertain": false,
"bookable": true,
"place_types": []
},
]
},
{
"id": 2,
"name": "Miejsce w wagonie do leżenie",
"place_types": [
{
"id": 32,
"name": "4 osobowa",
"available": true
"unavailable_help_text": "",
"selected": true,
"price": 76.00,
"uncertain": false,
"bookable": true,
"place_types_label": "Wybierz rodzaj przedziału.",
"place_types": [
{
"id": 41,
"name": "Przedział żeński",
"available": true,
"unavailable_help_text": "",
"selected": false,
"price": 76.00,
"uncertain": false,
"bookable": true,
"place_types_label": "",
"place_types": []
},
{
"id": 42,
"name": "Przedział męski",
"available": true,
"unavailable_help_text": "",
"selected": false,
"price": 76.00,
"uncertain": false,
"bookable": true,
"place_types_label": "",
"place_types": []
},
{
"id": 43,
"name": "Przedział mieszany",
"available": false,
"unavailable_help_text": "There are no free places anymore",
"selected": false,
"price": 76.00,
"uncertain": false,
"bookable": true,
"place_types_label": "",
"place_types": []
},
]
},
{
"id": 33,
"name": "6 osobowa",
"available": "true,
"unavailable_help_text": "",
"selected": false,
"price": 56.00,
"uncertain": false,
"bookable": true,
"place_types_label": "",
"place_types": []
}
]
}
]
}
}
]404Body
{
"status": "error",
"message": "IC tickets not available"
}Seat reservation statusGET/bookings/{connection_id}/{train_nr}/{place_type_id}
Returns list of available seats for train with nr train_nr
Example URI
- connection_id
integer(required)connection ID (returned by the search method)
- train_nr
string(required)- place_type_id
id(required)id of place type selected from
/train_place_types
JSON MessageHeaders
Content-Type: application/json200Headers
Content-Type: application/jsonBody
[
{
"carriage_nr": 1,
"seats": [
{
"nr": 14
},
{
"nr": 16
},
{
"nr": 22
}
]
},
{
"carriage_nr": 2,
"seats": [
{
"nr": 24
},
{
"nr": 25
},
{
"nr": 26
},
{
"nr": 27
}
]
},
{
"carriage_nr": 3,
"seats": []
}
]422Body
{
"status": "error",
"message": ""
}Connection reservationPOST/connections/{id}/reservation
After booking, customer has a limited time for pay, this time will be returned in response (time_for_payment in seconds).
Discount parameters should correspond to discount codes obtained from appropriate KOLEO API method. Note: Your request can’t include informations about the app owner. According to our system design we will always sell ticket for the app owner anyway - regardless of the passengers in request.
In this moment your client should get information about payment. Payment process should be performed by your application.
Example request is to book connection with given ID with three normal passengers (including the app owner), one reduced passenger with discount ID “20”, two reduced passengers with discount ID “21”, three dogs and one bike. Seats options will be ignored (more than one passenger).
Parameter payment_id is an optional payment parameter to which we can link to the new order. In the absence of this parameter a new payment will be created. Payment is an option to pay for a number of orders at the same time. If payment_id will be incorrect (not existing, belonging to another user or an already paid payment), the server will respond with error 404.
Specyfying optional field alternative with a true value (when an alternative offer is available) means that connection will be booked with an alternative offer.
options parameter is mandatory, and minimal request should have { "options": {}} as a request body.
For deprecated passengers structure: Without specified passenger booking will be made for main passenger only.
For recommended passengers structure: If you don’t specify any passenger in the request, and passengers params would be provided, you’ll get an error.
Note that only one passenger is permitted to have param ticket_owner set to true
Example URI
- id
integer(required)connection ID (returned by the search method)
JSON MessageHeaders
Content-Type: application/jsonBody
{
// Deprecated
"normal_passengers": [
"Angela Abar",
"Adrian Veidt"
],
"reduced_passengers":
{
20:
[
"Jon Osterman"
],
21:
[
"Walter Kovacs",
"Laurie Juspeczyk"
]
},
// Recommended
"passengers": [
{
"name": "Angela Abar",
"discount_id": 20,
"discount_card_ids": [ // optional
2,
1
],
"ticket_owner": true
},
{
"name": "Jon Osterman",
"discount_id": 21,
"discount_card_ids": [ // optional
1
],
"ticket_owner": false
}
]
"extras" : [
{
"type": "bikes",
"id": 0
},
{
"type": "luggage",
"id": 1
}
],
"options": [
{
"type": "train_classes",
"id": 2
},
{
"type": "seats",
"id": 1
}
],
"seats_reservations": [
{
"train_nr": "19100",
"seats":[
{
"carriage_nr": 1,
"seat_nr":41
},
{
"carriage_nr":1,
"seat_nr":42
}
],
"preferences": [
{
"type": "placement",
"id": 1
},
{
"type": "compartment_type",
"id": 1
}
]
}
],
"payment_id": 123,
"tariff_ids": [656]
}201Headers
Content-Type: application/jsonBody
{
"price": 12.35,
"passengers": [
{
"name": "Angela Abar",
"discount_id": 22,
"discount_card_ids": []
},
{
"name": "Jon Osterman",
"discount_id": 20,
"discount_card_ids": []
}
],
"payment_deadline": "2017-01-01 12:00:00+0200",
"reservation_id": 123456,
"payment_id": 123,
"connection_id": 1234,
"places":
[
{
"carriage": 7,
"seat": 17
},
{
"carriage": 7,
"seat": 18
}
],
"extras":
[
{
"type": "dogs",
"relations":
[
{
"relation": "Warszawa Centralna - Kraków Główny",
"value": 2
},
{
"relation": "Kraków Główny - Zakopane",
"value": 2
}
]
},
{
"type": "bikes",
"relations":
[
{
"relation": "Warszawa Centralna - Kraków Główny",
"value": 1
},
{
"relation": "Kraków Główny - Zakopane",
"value": 0
},
]
},
{
"type": "train_class",
"relations":
[
{
"relation": "Warszawa Centralna - Kraków Główny",
"value": 2
},
{
"relation": "Kraków Główny - Zakopane",
"value": 2
}
]
},
{
"type": "luggage",
"relations":
[
{
"relation": "Warszawa Centralna - Kraków Główny",
"value": 2
},
{
"relation": "Kraków Główny - Zakopane",
"value": 2
}
]
}
],
"requested_bikes_count": 0,
"available_bikes_count": 0,
"start_station_id": 20456,
"end_station_id": 45623,
"brand_ids": [1],
"start_datetime": "2017-08-30T19:16:00.000+02:00",
"end_datetime": "2017-08-30T19:34:00.000+02:00",
"status": "created",
"tariff_names": ["STREFOWY JEDNORAZOWY"],
"validity_limits": [
{
"content": "na odcinku Łódź Kaliska – Łódź Widzew bilet obowiązuje 2 godziny"
}
],
"tos_dict": [
{
"name": "KOLEO-PR",
"url" :"https://pomoc.koleo.pl/wp-content/uploads/2017/03/Regulamin-KOLEO_PR.pdf"
}
],
"can_create_invoice": false,
"coupon_available": false,
"combined_info": [
{
"content": "Bilet wystawiony zgodnie z warunkami oferty Taryfa Małopolska."
}
],
"is_network": false,
"is_refundable": false,
"is_season": false,
"is_return": false,
"is_zonal": true,
"is_special_event": false,
"seats_reservations": [
{
"train_nr": "19100",
"booking_nr": "1002",
"seats": [
{
"seat_nr": 41,
"carriage_nr": 1
},
{
"seat_nr": 42,
"carriage_nr": 1
}
]
}
],
"valid_from": "2020-11-29T14:02:00.000+01:00",
"valid_to": "2020-11-29T23:59:59.999+01:00",
"is_seat_booking": false,
"order_id": 41169570,
"ticket_owners": ["Ju Ro"],
"tariff_rules": [],
"remote_order_info": [],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "No available seats for this connection"
}404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Cannot book selected seats"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Invalid connection date"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "PKP Intercity sales system error occurred, please, try again later"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Selected passenger does not have appropriate discount set for this offer"
}Payments ¶
Available payment states are: created, processed, paid, declined.
created - payment has been created but not yet processed
processed - the funds have been transfered (user paid for order) but tickets are not yet generated: user should not be able to make another payment attempt for these orders. In rare cases of malfunction of internal or external ticket issuing systems the tickets could be generated with a delay or automatically refunded
paid - the funds have beed tranfered and tickets have been generated properly
declined - the payment has been declined, another payment attempt is advised
is_delayed flag means that payment processing time is longer than usual. User should be displayed delay_message and redirected to order list view to wait for a push with tickets or automatic refund info.
PaymentsGET/payments{?carrier_id}
-
user_auth
-
Authenticated
Example URI
- carrier_id
integer(optional)carrier ID whose payments we want to get
200Headers
Content-Type: application/jsonBody
[
{
"id": 1234,
"created_at": 2016-07-11T18:54:51.042+02:00,
"paid_at": null,
"status": "created",
"sum": 0.12,
"order_ids": [1234567, 12345],
"can_be_paid": true,
"coupon_available": true,
"payment_decline_reason": "",
"is_delayed": true,
"delay_message": "Otrzymaliśmy płatność jednak wystawianie biletu trwa dłużej niż zwykle"
},
{
"id": 1235,
"created_at": 2016-07-12T18:54:51.042+02:00,
"paid_at": null,
"status": "created",
"sum": 0.22,
"order_ids": [1234568, 12346],
"can_be_paid": true,
"coupon_available": true,
"payment_decline_reason": "",
"is_delayed": false,
"delay_message": ""
}
]Payment ¶
-
user_auth
-
Authenticated
Payment previewGET/payments/{id}{?carrier_id}
Example URI
- id
integer(required)payment ID (returned by /reservation method)
- carrier_id
integer(optional)carrier ID whose payment we want to get
200Headers
Content-Type: application/jsonBody
{
"id": 13117195,
"created_at": "2017-06-01T15:26:15.084+02:00",
"paid_at": null,
"status": "created",
"sum": "436.67",
"order_ids": [
9290331
],
"can_be_paid": true,
"coupon_available": true,
"payment_decline_reason": "",
"is_delayed": false,
"delay_message": ""
}404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Resource not found"
}PaymentPATCH/payments/{id}{?carrier_id}
Sending this request implies that user paid for ticket in your application. In response, you get an order_id array, which allows you to download specific tickets in PDF format or you get an error if your KOLEO account balance is insufficient.
Example URI
- id
integer(required)payment ID (returned by /reservation method)
- carrier_id
integer(optional)carrier ID whose payment we want to get
JSON MessageHeaders
Content-Type: application/jsonBody
{
"paid_amount": "436.67"
}200Headers
Content-Type: application/jsonBody
{
"order_ids": [
9290331
]
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Paid price is not equal to order's price"
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Insufficient funds in the agent's account"
}400Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Undetermined error"
}Orders in payment ¶
Orders previewGET/payments/{id}/payment_orders{?carrier_id}
-
user_auth
-
Authenticated
Example URI
- id
integer(required)ID (returned by /reservation)
- carrier_id
integer(optional)optional ID of a carrier
200Headers
Content-Type: application/jsonBody
{
"order_ids": [
1234567,
12345
]
}Order in payments ¶
Order previewGET/payments/{id}/payment_orders/{order_id}{?carrier_id}
-
user_auth
-
Authenticated
Example URI
- id
integer(required)ID (returned by /reservation)
- order_id
integer(required)ID of an order
- carrier_id
integer(required)optional ID of a carrier
200Headers
Content-Type: application/jsonBody
{
"price": "20.52",
"passengers": [
{
"name": "Ju Ro",
"discount_id": 54,
"discount_card_ids": [],
"price_details": null
}
],
"payment_deadline": "2020-11-29T14:04:40.733+01:00",
"reservation_id": 41169570,
"payment_id": 83492817,
"connection_id": 60151003,
"places": [],
"extras": [
{
"type": "bikes",
"relations": [
{
"relation": "Olsztyn Gł. - Ełk Szyba Wsch.",
"value": 0
}
]
},
{
"type": "dogs",
"relations": [
{
"relation": "Olsztyn Gł. - Ełk Szyba Wsch.",
"value": 0
}
]
},
{
"type": "luggage",
"relations": [
{
"relation": "Olsztyn Gł. - Ełk Szyba Wsch.",
"value": 1
}
]
},
{
"type": "train_class",
"relations": [
{
"relation": "Olsztyn Gł. - Ełk Szyba Wsch.",
"value": 2
}
]
}
],
"requested_bikes_count": 0,
"available_bikes_count": 0,
"start_station_id": 9209,
"end_station_id": 12237,
"brand_ids": [
3
],
"start_datetime": "2020-11-29T14:02:00.000+01:00",
"end_datetime": "2020-11-29T17:04:00.000+01:00",
"status": "payment_verified",
"tariff_names": [
"PRZEJAZD TAM"
],
"validity_limits": [
{
"content": "on section Olsztyn Gł. – Ełk Szyba Wsch. the ticket is valid 9 godzin 57 minut"
}
],
"tos_dict": [
{
"name": "mPOLREGIO",
"url": "https://polregio.pl/pl/dla-podroznych/pomoc/przepisy-taryfy/"
}
],
"can_create_invoice": false,
"coupon_available": false,
"combined_info": [],
"is_network": false,
"is_refundable": false,
"is_season": false,
"is_return": false,
"is_zonal": false,
"is_special_event": false,
"seats_reservations": [],
"valid_from": "2020-11-29T14:02:00.000+01:00",
"valid_to": "2020-11-29T23:59:59.999+01:00",
"is_seat_booking": false,
"order_id": 41169570,
"ticket_owners": [
"Ju Ro"
],
"tariff_rules": [],
"remote_order_info": [],
"refund_info": "Each carrier sets its individual cancellation fee in the Carriage Terms and Conditions, i.e. an amount which will be deducted from the initial ticket price if the ticket is returned.",
"is_refund_amount_unknown": false
}404Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Resource not found"
}Delete order from payment (shopping cart)DELETE/payments/{id}/payment_orders/{order_id}{?carrier_id}
-
user_auth
-
Authenticated
Example URI
- id
integer(required)ID (returned by /reservation)
- order_id
integer(required)ID of an order
- carrier_id
integer(required)optional ID of a carrier
200Headers
Content-Type: application/json422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Cannot delete last order from shopping cart"
}422Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Cannot delete this order from shopping cart"
}Station Announcements ¶
Station announcements flow
-
/station_announcements- get a list of station announcements, its already defined in Dictionary group, -
/station_announcements/{station_id}/{type}- get a list of station announcements of the specified type for the selected station
Station announcements ¶
Get list of station announcements for a particular station (restricted access)GET/station_announcements/{station_id}/{type}
Example URI
- station_id
integer(required)station ID
- type
string(required)station announcement type:
-
“Start”, if it is for start station,
-
“End”, if its for for end station
-
200Headers
Content-Type: application/jsonBody
[
{
"title": "Attention! Communication difficulties for Kraków Główny and Kraków Płaszów stations",
"short_text": "In connection with the modernisation of the Krakow railway junction some trains PKP Intercity bypass the Kraków Główny or Kraków Płaszów station",
"long_text": "Modernisation of the Kraków railway junction some PKP Intercity trains bypass Kraków Główny station and they travel from Kraków Płaszów station. In case you are unable to find a connection you are looking for please, try to enter from Kraków Płaszów station. You will find more information on the website www.intercity.pl and the check-in counters.",
"station_id": 1234,
"type": "Start"
},
{
"title": "Attention! Another station announcement. Communication difficulties for Kraków Główny and Kraków Płaszów stations",
"short_text": "In connection with the modernisation of the Krakow railway junction some trains PKP Intercity bypass the Kraków Główny or Kraków Płaszów station",
"long_text": "Another modernisation of the Kraków railway junction some PKP Intercity trains bypass Kraków Główny station and they travel from Kraków Płaszów station. In case you are unable to find a connection you are looking for please, try to enter from Kraków Płaszów station. You will find more information on the website www.intercity.pl and the check-in counters.",
"station_id": 1234,
"type": "Start"
}
]403Headers
Content-Type: application/jsonBody
{
"status": "error",
"message": "Additional permissions required"
}