This is the E2E documentation for the ZVS-Distribution API which describes the concepts, services, booking flow, access, authorization and error handling.

The services are described briefly from the business perspective. The technical details of the services (methods, request, responses, mandatory parameters etc) and a service mock are available on the Swagger UI page:

20 Swagger UI Integration (Preview of upcoming features)

1. Registration

The B2P web service is secured by an API Management Platform. To get access to the services you need to register as a developer on the SBB developer portal. There is also an integration developer portal that may be used for testing purposes. Please first register for the integration environment.

Before you will get access to the production environment you need to successfully integrate the services on the integration environment to show compliance with the rules.

For logging into the developer portal you need to have an account at one of the following provides:

  • Azure (only for internal use)

  • Swisspass

  • GitHub

  • Google

  • Microsoft

When logging in with one of these identity provides you will be asked to share a minimum of information like your e-mail address. Once registered you will find the B2P API as following:

3scale b2p

As a first step you need to choose a plan. The plan defines usage limits and which services you are allowed to call. All plans need SBB approval. The plans can be changed later (needing additional approval).

3scale b2p plans

When registering your Client, you will be asked for a name and description. Those values can be chosen freely, but we recommend you to use something descriptive. Once you finished the registration process your client should be in a Pending state until it gets activated by the SBB. Even though it is not activated yet you can already see your login credentials. Since the B2P web service uses the OAuth 2 client credentials flow you will get a Client ID and Client Secret and there is no need to provide a Redirect URL.

3scale b2p client

Before you can start using the web services you need to contact SBB to get your personal contract ID that has to be send with every request.

Please note that the Swagger UI within the developer portals are for documentation purposes only. When expecting mocked responses one should use the 20 sandbox environment.

2. Authorization

The B2P web service is secured using OAuth 2. Therefore, you need to obtain a token before sending requests to one of the services. All auth tokens are valid for 30 minutes and should be reused for subsequent requests. We recommend you to use existing libraries for your implementation, but to validate your credentials and to do some initial tests you can use a tool like Postman or Curl. The first step is to obtain a token (JWT) and to set it as a header in your actual request. For obtaining a token you need your Client ID and Client Secret (see Registration). Depending on the environment you can obtain the token from:

Refresh tokens are deprecated on our end and should no longer be used to extend sessions.
production environment
https://sso.sbb.ch/auth/realms/SBB_Public/protocol/openid-connect/token
integration environment
https://sso-int.sbb.ch/auth/realms/SBB_Public/protocol/openid-connect/token
Example: Obtain Token
curl -X POST \
 'https://sso.sbb.ch/auth/realms/SBB_Public/protocol/openid-connect/token' \
 -d 'grant_type=client_credentials&client_id=$clientId&client_secret=$clientSecret'

The token is encapsulated within the result as an access_token and needs to be set as a Bearer token in the Authorization-HTTP-Header as following:

Example: Location Request with token
 curl -X GET \
  'https://b2p.api.sbb.ch/api/locations?name=Bern' \
  -H 'Authorization: Bearer $accessToken' \
  -H 'Cache-Control: no-cache' \
  -H 'Accept: application/json' \
  -H 'X-Contract-Id: ABC1234' \
  -H 'X-Conversation-Id: e5eeb775-1e0e-4f89-923d-afa780ef844b'
The URL for the B2P production environment is https://b2p.api.sbb.ch whereas the integration environment is available under https://b2p-int.api.sbb.ch.

2.1. Refresh Token

The refresh token will no longer extend the session, therefore we do not recommend using it. Instead, a new token should be issued before the old one expires.

3. General Concepts

3.1. Web Service

The B2P web service is a RESTful web service that uses HTTP methods for accessing resources.

The following parameters must be set in the HTTP Header with every request:

  • The Conversation-ID (X-Conversation-Id) to identify the current sales process

  • The partner’s contract ID (X-Contract-Id) to identify the partner, permissions and preferences

Example: Mandatory X-Contract-Id and X-Conversation-Id parameters set in HTTP Header
curl -X GET \
 'https://b2p.app.sbb.ch/api/locations?name=Bern'
 -H 'Accept: application/json' \
 -H 'Accept-Language: en' \
 -H 'X-Conversation-Id: cafebabe-0815-4711-1234-ffffdeadbeef' \
 -H 'X-Contract-Id: ABC1234'

3.2. Conversation-ID

The Conversation-ID is an unique identifier of a sales process. Every step (get offers, booking, get tickets, etc.) within one sales process must share the same Conversation-ID.

The Conversation-ID is a mandatory parameter and must be send in the HTTP header as X-Conversation-Id with every request.

The Conversation-ID must match the UUID format.
For example: cafebabe-0815-4711-1234-ffffdeadbeef.

It is crucial that a new Conversation-ID is used when a new sales process begins. Some steps will fail if the Conversation-ID is reused (e.g. payment).

If however the user requests multiple offers and multiple prebookings the Conversation-ID should be reused, as he is still in the same sales process.

3.3. Versioning

The services are versioned and the service version can bee seen in the URL. No visible version means it’s V1. Example:

The services are versioned independently of each other. It’s unproblematic for example to use Prebooking V1 together with Booking V2.

Service versions that aren’t published on the production environment but only on the integration environment are subject to change. As soon as a version is available on the production environment there won’t be any breaking changes. However, it’s possible that optional request or response parameters will be added.

The general rule is that there may be a new version every 3 weeks and old version may be removed from the API after 9 weeks.

Most services return links to guide you through the booking flow and tell you which services can be called next. Here is an extract from a trip-offers response.

Link section of the trip-offers response
"links":
[
    {
        "rel": "prebook", (1)
        "version": 2, (2)
        "href": "https://b2p.api.sbb.ch/api/v2/prebookings", (3)
        "method": "POST", (4)
        "contentTypes": [
            "application/json" (5)
        ]
    },
    {
        "rel": "online-offers",
        "version": null,
        "href": "https://www.sbb.ch/de/kaufen/pages/fahrplan/fahrplan.xhtml?[...]", (6)
        "method": "GET",
        "contentTypes": [
            "text/html"
        ]
    }
]
1 Name of the service.
2 Version - if the service is versioned.
3 Service URL.
4 HTTP Method.
5 Returned media type.
6 This link redirects the user to the SBB webshop to perform the next steps.

Placeholders

Links may contain placeholders that must be filled in. Below is an example of a trip response.

Link section of trip response
{
  "rel": "prices",
  "version": null,
  "href": "https://b2p.app.sbb.ch/api/prices?tripIds=VCUyNEElM0QxJTQwTyUzREJlcm4lNDBYJTNENzQzOTEyMiU0MFklM0Q0Njk0ODgyNSU0MEwlM0Q4NTA3MDAwJTQwYSUzRDEyOCU0MCUyNEElM0QxJTQwTyUzRFolQzMlQkNyaWNoK0hCJTQwWCUzRDg1NDAxOTMlNDBZJTNENDczNzgxNzclNDBMJTNEODUwMzAwMCU0MGElM0QxMjglNDAlMjQyMDE4MDgyMzEwMzIlMjQyMDE4MDgyMzExMjglMjRJQysxKysrKyUyNCUyNDElMjQlQzIlQjZLQyVDMiVCNiUyNTIzVkUlMjUyMzAlMjUyM0NGJTI1MjMxMDAlMjUyM0NBJTI1MjMwJTI1MjNDTSUyNTIzMCUyNTIzU0lDVCUyNTIzMSUyNTIzJUMyJUI2S0NDJUMyJUI2JTI1MjNWRSUyNTIzMCUyNTIzRVJHJTI1MjMxJTI1MjNISU4lMjUyMzAlMjUyM0VDSyUyNTIzMzcyMTUyJTI1N0MzNzIxNTIlMjU3QzM3MjIwOCUyNTdDMzcyMjA4JTI1N0MwJTI1N0MwJTI1N0M4NSUyNTdDMzcyMTQyJTI1N0MxJTI1N0MtMjE0NzQ3OTUzNCUyNTdDMCUyNTIz&passengers=${passengerInfos}",(1)
  "method": "GET",
  "contentTypes": [
    "application/json"
  ]
},
{
  "rel": "online-offers",
  "version": null,
  "href": "https://www.sbb.ch/de/kaufen/pages/fahrplan/fahrplan.xhtml?recon=VCUyNEElM0QxJTQwTyUzREJlcm4lNDBYJTNENzQzOTEyMiU0MFklM0Q0Njk0ODgyNSU0MEwlM0Q4NTA3MDAwJTQwYSUzRDEyOCU0MCUyNEElM0QxJTQwTyUzRFolQzMlQkNyaWNoK0hCJTQwWCUzRDg1NDAxOTMlNDBZJTNENDczNzgxNzclNDBMJTNEODUwMzAwMCU0MGElM0QxMjglNDAlMjQyMDE4MDgyMzEwMzIlMjQyMDE4MDgyMzExMjglMjRJQysxKysrKyUyNCUyNDElMjQlQzIlQjZLQyVDMiVCNiUyNTIzVkUlMjUyMzAlMjUyM0NGJTI1MjMxMDAlMjUyM0NBJTI1MjMwJTI1MjNDTSUyNTIzMCUyNTIzU0lDVCUyNTIzMSUyNTIzJUMyJUI2S0NDJUMyJUI2JTI1MjNWRSUyNTIzMCUyNTIzRVJHJTI1MjMxJTI1MjNISU4lMjUyMzAlMjUyM0VDSyUyNTIzMzcyMTUyJTI1N0MzNzIxNTIlMjU3QzM3MjIwOCUyNTdDMzcyMjA4JTI1N0MwJTI1N0MwJTI1N0M4NSUyNTdDMzcyMTQyJTI1N0MxJTI1N0MtMjE0NzQ3OTUzNCUyNTdDMCUyNTIz&datum=2018-08-23&zeit=1032",(2)
  "method": "GET",
  "contentTypes": [
    "text/html"
  ]
}
1 Link with the ${passengerInfos} placeholder that must be filled in with passenger information.
2 URL without placeholders. The link points to the www.sbb.ch website, where the passenger information will be entered by the user.

Message Body and optional parameters

Neither the body of a POST request nor the optional parameters are shown in the links. The body structure and the optional parameters can be seen in the Swagger UI.

Example: Prices request with filled in placeholders and added qualityOfService as an optional parameter
 curl -X GET \
  'https:/b2p.app.sbb.ch/api/v2/prices?tripIds=VCUyNEElM0QxJTQwTyUzREJlcm4lNDBYJTNENzQzOTEyMiU0MFklM0Q0Njk0ODgyNSU0MEwlM0Q4NTA3MDAwJTQwYSUzRDEyOCU0MCUyNEElM0QxJTQwTyUzRFolQzMlQkNyaWNoK0hCJTQwWCUzRDg1NDAxOTMlNDBZJTNENDczNzgxNzclNDBMJTNEODUwMzAwMCU0MGElM0QxMjglNDAlMjQyMDE4MDgyMzEwMzIlMjQyMDE4MDgyMzExMjglMjRJQysxKysrKyUyNCUyNDElMjQlQzIlQjZLQyVDMiVCNiUyNTIzVkUlMjUyMzAlMjUyM0NGJTI1MjMxMDAlMjUyM0NBJTI1MjMwJTI1MjNDTSUyNTIzMCUyNTIzU0lDVCUyNTIzMSUyNTIzJUMyJUI2S0NDJUMyJUI2JTI1MjNWRSUyNTIzMCUyNTIzRVJHJTI1MjMxJTI1MjNISU4lMjUyMzAlMjUyM0VDSyUyNTIzMzcyMTUyJTI1N0MzNzIxNTIlMjU3QzM3MjIwOCUyNTdDMzcyMjA4JTI1N0MwJTI1N0MwJTI1N0M4NSUyNTdDMzcyMTQyJTI1N0MxJTI1N0MtMjE0NzQ3OTUzNCUyNTdDMCUyNTIz&passengers=paxa%3B42%3Bhalf-fare&qualityOfService=1' \
  -H 'Accept: application/json' \
  -H 'X-Conversation-Id: cafebabe-0815-4711-1234-ffffdeadbeef' \
  -H 'X-Contract-Id: ABC1234'

3.5. Swagger documentation & Service Mock

The services are described in detail using Swagger. The Swagger UIs are available here:

20 Swagger UI Integration (Preview of upcoming features)

Swagger describes every service, it’s request and response parameters and possible errors.

In addition, we have implemented a service mock. It does not call the real backend but returns a predefined response. You can click Try it out! in the Swagger UI to play around with the services and get an idea how they work.

4. Sales process

The sales process is a sequence of steps in the booking flow as shown in the figure below.

Sales Process Diagram
Figure 1. Sales Process

The sales process typically begins with the offer requests, however there may be some previous steps needed to perform the offer request depending on the offer request type.

There are three offer request types that initiate a sales process:

Route based

Offers for a specific origin and destination will be returned. See Route Offers for details.

Trip based

Offer for a specific trip (i.e. train connection) will be returned. See also Trip Offers for details.

Product based

Offers for a specific product will be returned. See Product Offers for details.

Payment step can be omitted by all non retailers. See Payment for details.

4.1. Offers

Common Concepts
Offer Container

Offers are linked to offer containers. These containers indicate which offers have to be prebooked in one transaction in order to fulfil the client’s request. The following principles are respected when building offer containers:

  • All offers have the same Class of Service

  • All passengers are eligible to travel on the same route

  • Total price corresponds to the total price of all contained offers

Validity

B2P Offers are valid for prebooking for 30 minutes only. However, it cannot be guaranteed and may be shorter in times in case of a heavy system load (Eviction policy).

Please be aware that the price is not guaranteed within this period. This guarantee is only subject to prebooking.
Please respect this limitation in the offer process.
IP Extension tickets

If you are requesting an offer for a trip which is part of an international journey, ipExtensionTicket must be set to true. We offer two specific products for connection tickets. The fare and behavior is the same as regular tickets (125) and saver tickets (4004). By setting true only those two products are returned.

This function will be activated soon.
Passenger

The passenger id cannot be longer than 50 characters.

Trip Offers

The B2P Service operation to retrieve offers based on a given tripId.

Please use the B2P trips service operation to get the required tripId.

The system calculates and returns only the best offers (in terms of service and price) that match the traveler wish.

The returned offer may be different for each traveler depending on its age or reduction card. For example, a request with two travelers, one adult and one child, may result in an offer container with two offers; city ticket for the adult and a day pass for the child.

See 20 trip-offers-controller for details.

Affiliate

As an affiliate partner you can use the B2P web service trip offers responses to publish deep links into the SBB Webshop to potential customers.

Example for webshop affiliate deep link:
"links": [
      {
        "rel": "online-offers",
        "version": null,
        "href": "https://www.sbb.ch/de/kaufen/pages/fahrplan/fahrplan.xhtml?recon=VCUyNEElM0QxJTQwTyUzREJlcm4lNDBYJTNENzQzOTEyMiU0MFklM0Q0Njk0ODgyNSU0MEwlM0Q4NTA3MDAwJTQwYSUzRDEyOCU0MCUyNEElM0QxJTQwTyUzREx1emVybiU0MFglM0Q4MzEwMTY4JTQwWSUzRDQ3MDUwMTcwJTQwTCUzRDg1MDUwMDAlNDBhJTNEMTI4JTQwJTI0MjAxODA4MjgxMDM2JTI0MjAxODA4MjgxMjAzJTI0UkUrNDM2NyslMjQlMjQxJTI0JUMyJUE3VCUyNEElM0QxJTQwTyUzREx1emVybiU0MFglM0Q4MzEwMTY4JTQwWSUzRDQ3MDUwMTcwJTQwTCUzRDg1MDUwMDAlNDBhJTNEMTI4JTQwJTI0QSUzRDElNDBPJTNEWiVDMyVCQ3JpY2grSEIlNDBYJTNEODU0MDE5MyU0MFklM0Q0NzM3ODE3NyU0MEwlM0Q4NTAzMDAwJTQwYSUzRDEyOCU0MCUyNDIwMTgwODI4MTIxMCUyNDIwMTgwODI4MTI1NiUyNElSKzcwKysrJTI0JTI0MSUyNCVDMiVCNktDJUMyJUI2JTI1MjNWRSUyNTIzMCUyNTIzQ0YlMjUyMzEwMCUyNTIzQ0ElMjUyMzAlMjUyM0NNJTI1MjMwJTI1MjNTSUNUJTI1MjMxJTI1MjMlQzIlQjZLQ0MlQzIlQjYlMjUyM1ZFJTI1MjMwJTI1MjNFUkclMjUyMzQ1MDU4JTI1MjNISU4lMjUyMzAlMjUyM0VDSyUyNTIzMzc5MzgwJTI1N0MzNzkzNTYlMjU3QzM3OTQ5NiUyNTdDMzc5NDk2JTI1N0MwJTI1N0MwJTI1N0MxNjUlMjU3QzM3OTM0MiUyNTdDMSUyNTdDLTIxNDc0ODM2MzIlMjU3QzAlMjUyMw==&datum=2018-08-28&zeit=1036",
        "method": "GET",
        "contentTypes": [
          "text/html"
        ]

If you are subscribed to the B2P affiliation program you have to include your affiliate ID as an URL parameter (see swagger documentation for details).

Special Cases:

You will be able to sell 1 day travelpasses. These passes can be returned as an offer at trip-offers in the case a 1 day travelpass is cheaper than a regular ticket. In case you offer you client to search for return trips be aware of this:

Example: March 15 Zurich – Geneva, regular fare CHF 100.00 March 15 Geneva – Zurich, regular fare CHF 100.00

1 day travelpass CHF 80.00 You have to ensure that you don’t sell a daypass per way!

Not for every journey it is possible to sell a regular ticket (productID 125). For journey within a network (association) you have to sell a “network fare”. Nor regular tickets will be offered via our API. There exists separate products per network (for ex. productID 1560 for unireso network). The logic of the sales process is exactly the same as for the regular ticket but the validity of these tickets are different.

In some cases there will be information on trip conditions. For example in case of construction work.

Product Offers

Some offers do not require a trip. These can be sold using the product-offers service operation. The product-offer request requires a productId and returns only offers with the requested product. The productId for a specific product can be obtained via the B2P products service.

Some Products do not need a passenger to be provided at the offer step (e.g. dog day-pass, bicycle day-pass). Those products can be identified easily, as there is no customer segment with the travellerType person defined. However, at the prebooking step the passenger has to be provided.

See 20 product-offers-controller for details.

Route Offers

The route offer request is similar to the trip offer but does not require a tripId. Instead the UIC code of the origin, destination (and via) must be provided. The UIC codes can be obtained from the location service.

Note that supersaver tickets are never returned for the route offer request, because supersaver tickets are bound to a specific train (and so to a tripId).

See 20 route-offers-controller for details.

Offer Options

There are several flags for controlling the way how offers are bundled and filtered in the backend. Those flags do not appear on the API documentation, as they are not part of the business requirements but only exposed for special purposes. At the moment the following options can be set as HTTP headers when requesting offers (if not set the default behaviour is used):

  • X-Offer-Options-Disable-Business-Filters [TRUE/FALSE]: This options force disables the offer filter logic of the backend. By default unuseful offers are dropped and not send in the B2P response e.g. as they may be too pricy for the requested journey. By setting this option to TRUE no offers will be dropped by the backend.

  • X-Offer-Options-IP-Extension-Ticket [TRUE/FALSE]: This option can be set when requesting specifically for international connection tickets. Please note that this behaviour has to be enabled per contract.

4.2. Prebookings

Offer prebookings

The offers-prebooking service makes an 'exclusive reservation' of an offer for the user until he finishes the booking process. It is especially important for limited offers such as supersaver tickets and seat reservations (not yet available via web services).

Common concepts
Offer container

All offerId’s from one offer-container must be prebooked together in one transaction.

Validity

The prebooked offer is valid for 30 minutes. After that it will be automatically discarded.

Integrity

A preBookingId will be returned for each prebooked offer. In case of an error the whole request will be invalidated. In other words, if the offer A and the offer B is prebooked in one request it is guaranteed that either two preBookingIds will be returned or an error.

The preBookingId is later used in the sales and booking processes.

The message body structure for the prebooking can be seen in the 20 prebookings-controller.

Note that the id of the passenger in prebooking request, must be identical to the passenger id in the offer request:

Sample offer request message payload
{
  "passengers": [
    "PaxId1;33;half-fare" (1)
  ],
  "validFromDate": [
    "2021-05-21"
  ],
  "validFromTime": [
    "14:52"
  ]
}
Sample PreBooking message payload
[{
  "offerPrebookings": [{
    "offerId": 6575552
  }],
  "passenger": {
    "id": "PaxId1", (1)
    "firstname": "John",(2)
    "lastname": "Doe",(2)
    "dateOfBirth": "1988-05-18"
  }
}]
1 The passenger id cannot change between offer request and prebooking request and is limited to 50 characters.
2 The firstname and lastname are limited to 30 characters.

4.3. Payment

Prior to booking, the payment step prepares the payment of one or more prebooking ids. This step is mandatory for all retailers.

The B2P web service currently supports two kinds of payments:

  • Invoice payment (is the payment method for all retailers)

  • Partner uses their own payment process (non retailers)

Overview

Payment Process Diagram

Invoice payment

The invoice payment will trigger an invoice that will be sent to the partner / retailer. Starting from version 2 of the payment service there are two optional reference fields available that may be set to internal references.

Only Swiss Francs (CHF) are accepted in payment.

See 20 payments-controller for details.

4.4. Booking

After an offer (or offers) was prebooked (and the payment was successful) it can be booked.

The api requires a list of preBookingIds to be sent as an array in the body of the POST request and returns one bookingId plus a section for each preBookingId the corresponding ticket as the ticketId.

See the 20 bookings-controller for details.

4.5. Changes in booking v2

In v2, a booking status can be sent when booking a prebooking. This can be either "PENDING" or "COMMITTED".

Example:

{
    "prebookingIds": [1234],
    "status": "PENDING"
}

Status COMMITTED

If no status is sent, or the status "COMMITTED" is sent, the booking behaves as in v1.

Status PENDING

If the status PENDING, a booking can be deleted up to 20 minutes after it has been booked. This can be done over the 20 delete-booking call.

A booking can be confirmed earlier instead of waiting for the 20 minutes to pass until the booking is automatically moved to the status CONFIRMED. Use the 20 patch-booking call to confirm a booking manually.

This confirming is entirely optional, as the system will automatically confirm the booking if neither a deletion nor a confirmation is sent. Do note the limitation below though.
A booking in a PENDING state cannot be refunded through the aftersales refund. Only bookings in a COMMITTED state can be successfully refunded.
Please be aware of the impact to flex products: The activation of the single travel days can not be done while the booking is PENDING state.

4.6. Fulfillment

After the successful booking, the tickets can be downloaded.

All tickets are available for download until one year after travel or latest validity date.

Tickets are available in several formats. Just define the accepted format as HTTP header information, i.e. "Accept": "application/pdf" to get a PDF. We recommend to download all available formats and cache them on your side.

Content type Ticket type

application/pdf

PDF (client needs to print the document)

text/html

Screen Ticket (client can show the ticket on his device or print it)

application/vnd.apple.pkpas

Wallet (to store in a mobile wallet vault)

The bookingId and the ticketId must be provided in the url path to download the ticket. See the 20 bookings-controller/getTicketUsingGET for details.

Please note that not all ticket types are available for every booking. The booking response provides the information which ticket types are downloadable.

4.7. Additional services

Master data

Networks

The B2P web service supports the following services to query information about Swiss railway networks.

  • /api/networks allows to fetch the list of available swiss railway networks. The response contains a list of the available networks including a link to query the network details.

  • /api/networks/{networkId} allows to fetch the network details for a given network. The response contains the name and description of the network and a list of the network zones.

  • /api/networks/{networkId}/zones allows to fetch the list of network zones for a given network. Please refer to the network zone map of the railway company to locate the zone geographically.

See 20 networks-controller for details.

Products

The B2P web service supports the following services to query information about offered products.

  • /api/products allows to fetch a complete list of supported products.

  • /api/products/{productId} allows to fetch product details for a given productId. These details include the available customer segments for a product as well as the offer-entrypoints that may be used.

See 20 products-controller for details about the returned data.

Journey services

Locations

The location service is used to perform a pattern-based search to retrieve a list of matching locations of type STATION in the journey planner database. The result is a possible match of (train-, bus-, tramway-) stations with corresponding UIC codes (standard ID-type for Switzerland) and coordinates.

To get an initial list of all possible stations please visit the public transport page https://opentransportdata.swiss/en/organization/oevch and download the newest Timetable xxxx (GTFS) zip file. Unpack it and use the stops.txt CSV file. Inside the file you can ignore the stops, where a parent station is given and import the parent station itself with the stop_id but without the trailing P. Further you need to remove the possible duplicated entries for the stop_id. Be aware that the stop list will be updated +/- weekly. So it is suggested to updated the initial stop list on a regular base.

See 20 locations-controller for details.

Trips

The trips service returns different trips (concrete journeys from the viewpoint of a passenger planning his trip) for a specified origin and destination (and via). The response body of the trip request contains some navigation links indicating the next services you can call. All journeys rely on a yearly plan (usually changing in first decade of December). Each Segment means a separate transport-product (by means passengers need to change at the ending Stop of a Leg). The underlying system provides a default change time when passengers need to switch transport-products. The underlying system handles date/time requests in Swiss timezone "Europe/Zurich" (seconds are irrelevant). If you’re interested in real-time data, you can find additional information here.

See 20 trips-controller for details.

Prices

The B2P web service prices operation allows to query the cheapest prices for a given trip.

Use the trips service to retrieve the (required) tripId.

A price offer cannot be used for prebooking and indicates the best price only.

By default the service assumes that the traveler is an adult with half-fare reduction card. The price offer can be based on a regular fare or (if available) a super saver fare. Starting from V2 the traveler details may be specified when requesting prices to overwrite the defaults.

See 20 prices-controller for details.

There may be multiple tripIds specified in one request to fetch multiple price quotes at once.

To avoid breaking the look-to-book ratio between offers and bookings, we recommend using this services for requesting simple price information and to only use the trip offers service after the user chose a specific trip.

The /prices request can be invoked either by using the GET or POST HTTP method.

We strongly recommend using POST as the provided tripId may in some cases exceed the maximum length allowed by the HTTP GET method which would result in an error response.

Barcodes

The service is used to generate the barcode for the public transport platform (German "öV-Platform"), which is part of the interface NOVA Control (German "NOVA Kontrolle"). This service allows authorized callers for producing barcodes (2d-codes and textcode). These barcodes can be validated by control devices using one of the control applications of the öV-CH (either the "KoServ app" running on Android or one of the "KoServ kernels" (or KSK)). The barcode produced are conform to the e-Ticketing concept.

The barcode service generates a barcode from a collection of attributes which are passed by the caller. The attributes have a type and a semantic attached to them. Most of the attributes are optional. The barcode is generated on the base of the attributes which are effectively passed. The validation of the barcode by the control application exploits the semantic of each attribute in order to compute the validity of the ticket.

See 20 barcodes-controller for details.

5. After sales process

In some situations, the booked ticket has to be refunded or cancelled for various reasons (technical errors, sickness, wrong ticket, change of plans or others). To address this, the B2P web service offers an aftersales functionality.

The aftersales flow (often referred as a SAV process, French "service après-vente") is shown in the figure below.

Aftersales Process Diagram
Figure 2. Aftersales process

5.1. Booking data

The booking data services provide information about the booking. The service is general usable to retrieve information about the booking and its tickets. The returned data contains also information about the refund possibilities and the reasons. A refund reason is necessary to get an offer for a refund.

The booking data can be retrieved via

ticket id

Retrieve booking data by entering the id of the ticket (printed on the ticket).

or booking id

If the booking id is known from the sales process, it can be used to retrieve the booking data.

See version 2 services 20 bookings-controller for details.

5.2. Refund offers

To get an offer for a possible refund, the refund reason must be selected, as the possibilities are returned in the B2P booking-data service. If no possible reason is returned in the booking data service, no refund offer and so no refund will be possible.

B2P refund offers are valid for 20 minutes only. After that the refund offers are discarded.
Not all products can be refunded and rules apply on partially used products and retention.

Currently there is only one refund reason possible over B2P. This is set by default.

refundReasonId description

NICHT_BENUTZT

Not used. Can only be used before start of validity of the ticket.

To call the refund offer service it is necessary to hand in all ticket ids, where a refund offer should be created. If one given ticket is not refundable, an error will be returned. If all given tickets are refundable for the same refund reason, one refund offer including refund offer id will be returned. This contains the compelete information of refundable amount, original price, excess, used part and so on.

See 20 refund-offers-controller for details.

5.3. Refund

The refund service confirms the refund of the tickets included in the given refund offer. It requires the refundOfferIds as input which are returned in the Refund offers response. See B2P refund-offers service. Only if the refund of all tickets of all given refund offers can be successfully refunded, the service will return a success response. Else an error will be returned and none of the tickets in one of the given refund offers will be refunded.

On success it returns a savBookingId and a savTicketId. For the moment this information is not necessary to be stored. Instead keep the bookingId and call the B2P booking-data service to check the new status of the tickets.

The refunded amount is always put back on the used payment method. So if the payment has been done with credit card, the refunded amount will be credited to the same credit card. In case of invoice payment, the refunded amount will be credited on the next invoice.

See the POST service 20 refund-booking-controller for details.

6. Error handling

The B2P web service implements the RFC 7807 (https://tools.ietf.org/html/rfc7807) standard.

6.1. Format

With this besides a HTTP code, a problem json body with further information is returned.

HTTP header

The response header in an error case is always like the following:

content-Type: application/problem+json

The following HTTP codes are used:

HTTP code Name Description

400

Bad Request

Request contains errors / is malformed.

401

Unauthorized

Authorization is required.

403

Forbidden

The requested action is forbidden for the current authorized user.

404

Not Found

Requested entity could not be found

406

Not Acceptable

The requested accept header in the request cannot be accepted.

422

Unprocessable Entity

The request can not be processed like this (by definition).

Common problem JSON body

{
 "type": "./b2p/{service-name}/{problem-id}",
 "title": "{title}",
 "documentation": "https://b2p.app.sbb.ch/docs/index.html#error-handling"
 "code": "{code}"
}

The title will always be written in English.

6.2. Example

Here an example for the locations service.

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json Content-Language: en

{
 "type": "./b2p/locations/name-too-short",
 "title": "The given name parameter is too short to do a reasonable locations search.",
 "documentation": "https://b2p.app.sbb.ch/docs/index.html#error-handling"
 "code": "422"
}

6.3. Services

Only the newest version of each service works with the described error response format.

Common

Certain problem types are thrown by multiple services. In this case, the service name in the reported problem indicates which of the services has reported the problem. These common problems are summarized in the following. The last column indicates which services can report the according problem.

HTTP code problem-id title services

403

access-to-booking-id-forbidden

You are not allowed to access the given booking with the given contract.

bookings, booking-data

404

ticket-not-found

The ticket with the given id could not be found or does not belong to the given booking id.

bookings, booking-data

406

ticket-format-not-supported

The requested ticket format is not supported for the given ticket.

bookings, booking-data

404

origin-and-destination-must-be-different

The origin and destination UIC must be different.

trips, trip-offers

404

via-must-be-different-than-origin-and-destination

The via UIC must be different than the origin and destination UIC.

trips, trip-offers

Locations

service-name = locations
HTTP code problem-id title

422

name-too-short

The given name parameter is too short to do a reasonable locations search.

Trips

service-name = trips

Please also take into account the common problems, as the trips service also reports problems defined there.

HTTP code problem-id title

404

date-too-far-in-the-past

The date parameter is too far in the past. In general it is possible to search until the last time table switch last December.

404

date-too-far-in-the-future

The date parameter is too far in the future. In general it is possible to search until the next time table switch in December. In fall a search already to the overnext December is possible.

404

location-uic-invalid

The origin, destination or via UIC is unknown.

404

trip-id-invalid

The trip id is invalid.

400

train-type-invalid

At least one of the given train types is invalid.

Prices

service-name = prices
HTTP code problem-id title

404

price-not-determinable

The price cannot be determined. Reasons for this can be e.g. that the passed trip id is invalid, that the trip id is too far in the past or too far in the future.

Trip-Offers

service-name = trip-offers

Please also take into account the common problems, as the trip-offers service also reports problems defined there.

HTTP code problem-id title

404

trip-id-too-far-in-the-future

The trip id parameter or the return trip id parameter is too far in the future. In general it is possible to get an offer for the next 2 months.

404

trip-id-too-far-in-the-past

The trip id parameter or the return trip id parameter is too far in the past. It is not possible to get offers for this trip.

404

location-uic-invalid

The origin, destination or via UIC is unknown.

404

trip-id-invalid

The trip id is invalid.

Prebookings

service-name = prebookings
POST Prebookings
HTTP code problem-id title

404

offer-id-not-found

At least for one offer id the according offer could not be found. The reason for this is that either the offer id expired and is no longer valid or that it never existed and is, thus, invalid.

404

sales-parameter-invalid

At least one given sales parameter could not be found.

Bookings

service-name = bookings

Please also take into account the common problems, as the bookings service also reports problems defined there.

POST Bookings
HTTP code problem-id title

404

prebooking-not-found

At least one of the given prebooking ids could not be found. This problem occurs if either the according prebooking id has expired and is no longer valid or if it has not been returned by a previous call of the prebooking service.

404

passenger-ids-of-prebookings-and-offers-not-matching

There has been at least one passenger id for the prebooking which does not match with a passenger id for the offer.

404

payment-confirmation-missing

The confirmation that the payment has been successfully done is missing. Please take care that the same x-conversation-id is used in payment process and in bookings.

Booking data

service-name = booking-data

Please also take into account the common problems, as the booking data service also reports problems defined there.

HTTP code problem-id title

404

booking-not-found

The booking with the given id could not be found. This problem can occur if the booking with the given id does not exist at all. Besides it can occur if there is a general problem with the processing of the booking.

403

access-to-booking-id-forbidden

You are not allowed to access the given booking with the given contract.

404

ticket-not-found

The ticket with the given id could not be found or does not belong to the given booking id.

406

ticket-format-not-supported

The requested ticket format is not supported for the given ticket.

Refund-Offers

service-name = refund-offers
HTTP code problem-id title

404

ticket-not-found

At least for one of the given ids, no ticket could be found.

404

ticket-already-refunded

At least one ticket has already been refunded.

404

refund-not-possible

At least one ticket could not be refunded with the given refund reason. At least one ticket is not refundable. The reason could be that the ticket is not refundable or that the given refund reason is not supported.

Refund Booking

service-name = refunds
POST Refunds
HTTP code problem-id title

404

refund-offer-not-found

At least one of the given refund offers could not be found. This problem occurs if either at least one of the given refund offers has expired and is no longer valid or if at least one refund offer id has not been returned by a previous call of the refund-offers service.