Samtrafiken ACCESS API - Integration Handbook

Version: 1.4

Last updated: September 23 2024

DISCLAIMER

The Samtrafiken ACCESS API and its documentation is work in progress. Changes and additions will be made to the documentation during the implementation process.

 

Samtrafiken ACCESS/DISTRIBUTION API

The Samtrafiken ACCESS API is an entry point to Swedish public transport sales. The API provides access to approximately 50 public transport carriers on the Swedish market. Through the API, users can search journeys, make bookings, seat reservations, add ancillaries, handle fulfillment and after sales.

The API is based on the OSDM (Open Sales and Distribution Model) standard. The OSDM standard is introduced below, along with details of the Samtrafiken implementation of the standard.

This documentation is mainly aiming to support Samtrafiken ACCESS implementation. When the information is directed to Samtrafiken DISTRIBUTION implementation the text starts with with “Instructions to Samtrafiken DISTRIBUTION:”

Architecture

 

Introduction to OSDM

Why OSDM?

OSDM is a standard to provide public transportation products in a common way, created by a group of members representing fare providers (operators), allocators (GDS) and distributors in Europe.

What is OSDM?

The objectives of the Open Sales and Distribution Model (OSDM) are twofold:

  1. to substantially simplify and improve the booking process for customers of public transport trips and,

  2. to lower complexity and distribution costs for distributors and carriers.

OSDM strengthens rail and public transport as a convenient and ecological means of transportation by simplifying distribution. Finally, it lays a solid fundament which can be extended to the distribution of other means of transportation.

OSDM Documentation

The official OSDM documentation can be found here: https://osdm.io/

Current OSDM version supported by Samtrafiken ACCESS is 3.0.3

Main objects in OSDM

The main objects in the model are:

  • products

  • trips

  • passengers

  • offers

  • bookings

  • fulfillments

These objects are both structurally and by references built together to create useful objects in the sales and after sales processes.

Offers

Offers are representing bookable elements (normally a travel ticket) a customer can book or buy through the sales system. Several types of offers can be returned. Trip offers, Non-trip offers, Reservations and Ancillaries. In a regular sales flow, trip offers and non-trip offers are presented to the customer.

Trip-offers normally has offerMode set to INDIVIDUAL where each passenger will have their own admission and fulfillment. An exception to this is an offer that represents a private compartment for the travel party. In this case one offer with offerMode COLLECTIVE and one admission for all passengers will be created.

Offer parts (offerPart)

The offer holds one or many offer parts of the following types:

  • Admission - represents a permission to travel. This is the most often used offer type. At individual ticketing each passenger in the travel party will have their own admission represented in the offer. An admission can have references to different other offer parts like reservations, ancillaries and fees, to create a complete fulfillment for the passenger

  • Reservation - represents a reservation of a specific type of inventory, e.g. seat, berth, or compartment. Reservations are mostly used together with admissions. Reservation as a stand-alone offer is not that common. It’s used if the customer requests for only reservation without an admission. The admissions in those cases are covered by NRT tickets or travel passes.

  • Ancillary - represents mainly non-travel products, e.g. meals, beverages, snacks, etc.

  • Fee - represents cost for customers related to certain type of actions, e.g. bookings, refunds, re-bookings. In many cases it’s used for covering the labor related costs related to above-mentioned activities.

  • Fares type, NOT used and implemented in the Samtrafiken ACCESS API.

To enable defining more complex products, offer parts can be coupled by references under the main offer part. Currently, there are only admissions that couple offer parts like this.

Trip with no reservation

Trip with reservation on leg 1

Two leg trip with reservations

Two leg trip with reservations and breakfast at leg 1

Admission

Admission

Admission

Admission

 

Reservation (leg 1)

Reservation (leg 1)

Reservation (leg 1)

 

 

Reservation (leg 2)

Ancillary (leg 1)

 

 

 

Reservation (leg 2)

The extract example below shows the model for a one leg trip offer with admission, reservation and an ancillary:

{ "offerId": "offer1", "summary": "2nd, class Stockholm C - Gothenburg C", "admissions": [ { "objectType": "Admission", "id": "part1", "summary": "2nd, class Stockholm C - Gothenburg C with SJ high speed train 421", "reservationRefs": [ { "id": "part2" } ], "ancillaryRefs": [ { "id": "part 3" } ] } ], "reservations": [ { "id": "part2", "summary": "Seat reserved in coach 5 seat 21" } ], "ancillaries": [ { "id": "part3", "summary": "Meat balls" } ] }

Booking part (bookingPart) status model

Status is placed on offer part and not on offer level. For trip offers and non-trip offers the admission is the root offer part but status on underlying offer parts (reservations, ancillaries) must be managed as well:

  • prebooked - when an offer is booked (the initial state);

  • confirmed, when a prebooked offer is confirmed (i.e. customer has paid);

  • fulfilled, when a prebooked offer is fulfilled (i.e. travel document has been issued);

  • released, when a fulfilled offer part is cancelled but not refunded (i.e. the inventory has been made available for the other customers to book);

  • refunded, when a fulfilled offer part is refunded to the customer;

  • exchange ongoing, when an exchange process is initiated;

  • exchanged, when the exchange process is finalized;

  • onhold, when the sales channel has asked for an extended TTL (time to live) period for the offer.

Trip coverage (tripCoverage)

Trip coverage exists on offer level and on offer part level. It explains which trip and trip leg the offer/offer part covers.

In given implementation an offer covers the complete trip. An admission, normally covers the whole trip as well. Reservations and ancillaries cover one trip leg.

Prm need wheelchair

To search available offer for passenger with prm need ”wheelchair”, in the offer request add offer.anonymousPassengerSpecifications.prmNeeds: WHEELCHAIR. The IMS will respond with offer when available.

There are different reasons an offer is not returned when searching with this parameter. The seat availablity is fully booked or the carrier do no support wheelchair on the specific departure.

Interrail

Some carrier offer discount for Interrail/Eurail card holder. In the offer request add offer. anonymousPassengerSpecifications.cards: type: REDUCTION_CARD and code: UIC_INTERRAIL.

If the discount is applicable on the specific journey, the offer response will include

"appliedReductionCardTypes": [

                                {

                                    "code": "UIC_INTERRAIL",

                                    "issuer": "urn:x_swe:carrier:313",

                                    "name": {

                                        "id": "5a5e4e5c-fc7a-4b04-acfb-bfac08f012ba",

                                        "text": "Interrail discount"

                                    }

                                }

Travel Pass

Communication of time: The validity period for the Travel pass should be communicated in UTC time to the recipient, with a time zone offset.

In the field validUntil for a Travel pass, it should be specified so that it corresponds to 23:59:59 local time on the day the pass expires to get the correct date of the last day.

·        Examples:

offer request validFrom 2024-08-24T22:00:00Z is preferred

offer request validFrom 2024-08-25T00:00:00+02:00 is also acceptable

response validFrom 2024-08-24T22:00:00Z corresponds to local time 00:00:00 on the 25th

response validUntil 2025-08-24T21:59:59Z corresponds to local time 23:59:59 on the 24th of the next year

Products

Offer part has references to products. A product describes the rules and properties of the offer part. E.g., a product for an admission describes the ticket-type like “Refundable 1st Class ticket”.

Flexibility

In OSDM, three types of flexibilities exist:

  • FULL_FLEXIBLE - Can be refunded (and rebooked)

  • SEMI_FLEXIBLE - Can be rebooked to another trip

  • NON_FLEXIBLE - Can not be rebooked or refunded

Travel class (travelClass)

  • FIRST - 1 Class travel

  • SECOND - 2 Class travel

  • ANY_CLASS - Used for ancillaries

Service class (serviceClass)

Describes the level of comfort within the Travel class.

Possible levels are:

  • BEST - Not used in this implementation

  • HIGH - A better/higher level of the travel class e.g. “2nd class with meals included”

  • STANDARD - The standard travel class ticket

  • BASIC - Not used in this implementation

  • ANY_CLASS - Used for ancillaries

Product name for Samtrafiken carrier will only be distributed in Swedish. E.g on Samtrafiken ticket the product name will be displayed in Swedish.

Journeys and Trips

A trip consists of one or several consecutive legs. In the Samtrafiken ACCESS implementation, one offer covers one trip. If the legs are not through-ticketed (i.e. co-priced), the system will split the trip to several trips within a Journey.
A multi carrier journey will be divided into multiple trips per carrier, since they are not through-ticketed.

Trip reference

The externalRef of a trip (trip.externalRef) contains information about the journey that the trip belongs to, and the order number of the trip in given journey.

Example:

"externalRef": "ea6cdf35-0dd5-4453-8702-f18c47953915|0|e55ded6a-22ce-4168-af3f-5c7b890fd46f":

  • The journey reference (UUID)

  • 0 indicates the first leg of the journey, 1 the second, etc.

  • The trip reference (UUID)

Service description

To show the end user what service and type of transport that operates a tripLeg it is good to combine different elements in the DatedJourney.

For example, it is possible to concatenate the content in elements Carrier, ProductCategory, Mode and PublishedServiceName: <carrier><ProductCategory><publishedServiceName>

Example:

  • Vy Night train 94

  • SJ AB High-speed train 421

  • SL Metro 14

Service.ProductCategory

ProductCategory describes the product category, or service brand, for the transport mode. E.g InterCity is a type of Train. The code set for productCategory is provided by Samtrafiken in namespace urn:x_swe:sbc.

Service.Mode

The Service Mode describes the transport method for the service:

  • BUS: Bus

  • UNDERGROUND: Metro

  • TRAIN: Train

  • TRAM: Tram

  • SHIP: Ferry

  • NIGHT_TRAIN: Night train

Promotion

In the offer request it is possible to search with a promotion code.

"promotionCodes": [ { "code": "SPRING_BREAK", "issuer": "urn:x_swe:carrier:310" } ]

Applied reduction card/promotion/corporate agreement

To know which carrier respond to reduction card, promotion and corporate agreements requested in the offer search, can be found in offerCollectionsResponse => offers => admissionOfferParts => appliedPromotionCodes/appliedCorporateCodes/appliedReductionCardTypes

If there are multiple reduction card provided, the reduction card with the highest discount is always applied.

Passengers and Purchaser

anonymousPassengerSpecifications

When searching for offers, anonymousPassengerSpecifications are provided. One for each passenger.

ExternalRef is a reference the sales channel can use to locate what offers in the response that match the passenger. The provider is obligated to return the reference in all responses.

In the request for a passenger with no special need use passenger type “PERSON”.

To get different prices depending on age, the age parameter must be set. No age will return an adult-price offer.

To get student or early retiree offers in Sweden, REDUCTION_CARD with the codes SWE_STUDENT and SWE_PENSIONER need to be provided.

"anonymousPassengerSpecifications": [ { "externalRef": "PASSENGER_1", "age": 60, "type": "PERSON", "cards": [ { "type": [ "REDUCTION_CARD" ], "code": "SWE_PENSIONER" } ] } ],

The IMS respond with the carrier’s applied passenger type in the description text.

Example

Client request

 

IMS respond with STUDENT fare and passenger type ADULT as carrier offer STUDENT fare. In appliedPassengerTypes.description the IMS respond with the “actual” passenger type to be printed on the ticket.

In addition the IMS respond with their own carrier code, when the reduction cards SWE_STUDENT, SWE_PENSIONER or SWE_TDT are used in the request. The redction cards starting with SWE_ are generic cards used at the swedish market without an issuer but all carriers returning discounts based om these cards should return their own carrier code as issuer.

IMS respond with YOUTH fare as carrier have no offer for STUDENT fare:

IMS respond with ADULT fare and passenger type ADULT as carrier does not offer STUDENT or YOUTH fare.

To search offer with discount, add the discount card in anonumousPassengerSpecifications with the type of card, code, number and issuer (owner of the discount card)

If the card is applied by the IMS, the IMS respond with returning information in appliedReductionCardTypes with code, issuer, http://name.id (card number) and text (name of the card)

The sales channel provide the applied card in the booking request and send the type, code, number and issuer.

The IMS respond with the applied card in the booking response in appliedReductionCardTypes and appliedReductions

Passenger

The passenger object can be updated with name and other contact information with the endpoint PATCH /bookings/{bookingId}/passengers/{passengerId}

Purchaser

The purchaser object can be updated with name and other contact information with the endpoint PATCH /bookings/{bookingId}/purchaser/{passengerId}. The PATCH will create a new purchaser if not already created.

Bookings

The booking can be used as a shopping cart, holding different journeys. A booking consists of one or several bookedOffers with references to trips and passengers.
Before fulfillment/confirmation of the booking (prebooked state) it is possible to add/replace/remove bookedOffers, reservations and ancillaries from a booking.

Book offers

New booking

To add an initial offer and create a booking, run POST /bookings. Together with the selected offerId, it is possible to add optionalReservationSelections and optionalAncillariySelections from the offer-search response to make a complete booking in the pay-load.

It is also possible to add optional reservations and ancillaries and purchaser/passenger information before confirmation of the booking by:

  • POST /bookings/{bookingId}/booked-offers/{bookedOfferId}/reservations

  • POST /bookings/{bookingId}/booked-offers/{bookedOfferId}/ancillaries

  • PATCH /bookings/{bookingId}/passengers/{passengerIds}

  • PATCH /bookings/{bookingId}/purchaser.

Promotion codes to use is also possible to provide in the pay-load.

Add offers to an existing booking

The endpoint to use when adding a new offer to a already existing booking is POST /bookings/{bookingId}/booked-offers. The pay-load is the same as for POST /bookings. The only difference is that the existing bookingId is provided as a parameter in the call.

Multi Carrier Journey

For multi carrier journeys, each carrier will book their own offer for that part (trip) of the journey.

Individual offerMode

In individual bookings (the normal case), each passenger will have their own admission in the booked offer together with reservations and ancillaries. With this model, each passenger has their own admission and fulfillment to handle refunds and other after sales activities.

Grouped offerMode

Grouped offers (private compartment) have more than one passenger referred from the admission. They share the admission and fulfillment. Aftersales activities will affect all passengers in the offer. It is not possible to refund only one of the passengers.

provisionalPrice and confirmedPrice

booking.confirmedPrice and booking.provisionalPrice should be seen as de facto mandatory and always be present regardless of the booking status, sometimes having the value 0 and sometimes not.

  • provisionalPrice
    Total sum of the offerParts that are pre-booked and yet to be confirmed. The
    (remaining) amount to be paid by the customer/passenger.

  • confirmedPrice
    Sum of the offerParts that are confirmed and paid for by the customer/passenger, the monetary value of the booking. A refund will reduce the confirmedPrice because the offerPart is not active/valid any more.

ticketTimeLimit

The timestamp in ticketTimeLimit indicates the latest time to fulfill the booking. The time is set from the offer with the shortest ticketTimeLimit in the booking.

Modify

Passenger name, address, phone number, email address can be modified on a provisional booking (prebooked).

Cancel

Instructions to Samtrafiken DISTRIBUTION: To avoid a refund on a ticket cancelled due to traffic disturbance the overrule code EXTERNAL_COMPENSATION is used in the Release offer reques

Availabilities

With GET /availabilities/preference endpoint the client will have the possibility to display the seat availability with seat characteristics for carrier and journey offering prebooked seat reservation.

NDS support contextType ”OFFER” and resourceType ”RESERVATION” in the offer flow.

NDS support contextType ”BOOKING” and resourceType ”RESERVATION” in the booking flow.

 

 

Instructions to Samtrafiken DISTRIBUTION: To avoid too large lists in the UI and make it possible to count overallAvailability the implementation of GET/availabilities/preferences should not include all available combinations.

Example: We have 1 seat with 3 placeProperty: Window, Power Socket, Table.

Wrong:

Correct:

Fulfillments

It is the fulfillment process that finalizes the booking. The result of the fulfillment is an offer with status fulfilled with a link to a document (e.g. PDF) for the offer.

Note: It is the distributor’s responsibility to distribute the fulfillment to the customer/passengers.

To make it possible for the distributor to create a digital ticket, it is possible to get complementary information by a drill-down in the offer together with fulfillment data as controlNumber and security objects provided in parallel with the PDF.

OSDM Endpoint Usage in Samtrafiken ACCESS API

The Samtrafiken ACCESS API will not implement all endpoints in the OSDM standard since it is not needed to achieve the objective to provide aggregated trips and offers in Sweden. Over time, more end points may be added.

The table below describes the currently identified/planned endpoint usage for Samtrafiken ACCESS API.

Note: The OSDM specification is still undergoing an evolution, with an active workgroup having meetings every week to evolve the standard to support upcoming needs. The exact OSDM version to be used in Samtrafiken ACCESS at the Start of Sales is yet to be decided.

Resource

Path

End-point description

Resource

Path

End-point description

Offers

POST /offers

Returns trip and non-trip offers.

 

GET /bookings/{bookingId}/bookedOffers/ {bookedOfferId}/additionalOffers

Returns ancillary and reservation offers

Availabilities

GET /availabilities/placeMap

Gets place map including availabilities.

 

GET /availabilities/preferences

Gets availabilities for a set of preferences.

Bookings

POST /bookings

Allows to create a booking based on a previously requested offer.

 

GET /bookings/{bookingId}

Returns a booking with the id provided.

 

DELETE /bookings/{bookingId}

Deletes the booking with the id provided.

 

PATCH /bookings/{bookingId}

Allows updating the fulfillment type of the booking.

BookedOffers

POST /bookings/{bookingId}/bookedOffers

Adds a bookedOffer in an existing booking.

 

DELETE /bookings/{bookingId}/bookedOffers/{offerId}

Deletes a booked offer in an existing booking.

BookingPart

POST /bookings/{bookingId}/bookedOffer/{bookedOfferId}/reservations

Adds a optional reservation to a prebooked offer.

 

DELETE /bookings/{bookingId}/bookedOffer/
{bookedOfferId}/reservations/{reservationId}

Deletes a reservation part from a prebooked offer.

 

POST /bookings/{bookingId}/bookedOffer/{bookedOfferId}/ancillaries

Adds an ancillary to a prebooked offer.

 

DELETE /bookings/{bookingId}/bookedOffer/
{bookedOfferId}/ancillaries/{ancillaryId}

Deletes an ancillary part from a prebook.

BookingsSearch

POST /booking-search

Searches for bookings according to parameters.

Passengers

GET /bookings/{bookingId}/
passengers/{passengerId}

Returns the passenger's information at every stage of the flow.

 

PATCH /bookings/{bookingId}/
passengers/{passengerId}

Updates the passenger's information.

Purchaser

GET /bookings/{bookingId}/purchaser

Returns the purchaser information.

 

PATCH /bookings/{bookingId}/purchaser

Updates the purchaser information.

Fulfillment

POST /bookings/{bookingId}/fulfillments

Triggers the fulfillment of the booking.

 

PATCH /fulfillments/{fulfillmentId}

Activates a fulfillment, i.e. changes the status to CONFIRMED/FULFILLED.

Refund

POST /bookings/{bookingId}/refundOffers

Initiates a refund process by creating a RefundOffer resource.

 

GET /bookings/{bookingId}/refundOffers/{refundOfferId}

Returns the refund offer for the ids provided.

 

PATCH /bookings/{bookingId}/refundOffers/{refundOfferId}

Allows to accept and confirm a refund offer.

 

DELETE /bookings/{bookingId}/refundOffers/{refundOfferId}

Deletes a refundOffer without waiting for an expiry. It is a good behavior to delete refundOffers that is not meant to be refunded.

 Exchange

POST /bookings/{bookingId}/exchangeOperations/{exchangeOperationId}

Allows to update an ongoing exchange operation.

 

DELETE /bookings/{bookingId}/exchangeOperations/{exchangeOperationId}

Cancels an ongoing exchange operation in provisional state. It is a good behavior to delete exchangeOffers that is not meant to be used.

 

POST /exchange-offer

Returns exchange offers for a specified fulfillments submitted given requested new trip characteristics.

Release (Cancel admission and resources but not refund)

POST /bookings/{bookingId}/releaseOffers

Initiates a release process by creating a releaseOffers resource.

 

PATCH /bookings/{bookingId}/
releaseOffers/{releaseOfferId}

Allows to accept and confirm a release offer.

MasterData

GET /places

Returns all searchable places (stops).

 

GET /coachLayouts

Returns all coach layouts.

 

GET /coachLayouts/{layoutId}

Returns a coach layout for a provided ID.

 

GET /reductionCards

Returns all reduction cards

Resplus

Samtrafiken is the owner of the RESPLUS brand. Samtrafiken’s national distribution service (NDS) is responsible for determining if a journey is a Resplus journey or not. The Samtrafiken ACCESS user should not send throughTicketTag RESPLUS in the offer request. The throughTicketTag is set by Samtrafiken. Samtrafiken's NDS will respond with throughTicketTags in the response when applicable.

The Samtrafiken ACCESS user is responsible to send the throughTicketTag RESPLUS in the booking request whenever this tag is returned in the offer response. It is up to the Samtrafiken ACCESS user to secure that the implementation of RESPLUS is correct as no validation is made to prevent incorrect behaviour. This will be validated by the certification carried out by Samtrafiken before access is given to Samtrafiken’s production environment.

API Authentication

Open API Specification

https://identity.ds.dev.ci.turnit.tech/help/index.html

Authentication

The proposed method for authentication in OSDM is to use OAuth2 and for Samtrafiken ACCESS we use a login service to request a valid token by using a Client Id/Client Secret. The token is then used in all requests to Samtrafiken ACCESS. The access token request follows the OAuth standard method.

To avoid too much traffic to the login service, the customer must reuse the token as long it is valid and ask for a new token when the old one is expired.

Requestor header

The requestor header contains detailed information about who is calling the API. It will include an id of the sales unit and name of the application used (if needed). The content of the string is part of a bilateral contract by the two parties and not standardized by OSDM. It is recommend to encrypt the information transferred.

Name

Details

Name

Details

Requestor*

{

     "salesApplication": "[String, name of the sales client, exact format provided by the inventory holder to the reseller]"

          "salesUnitCode": "[String, agreed between reseller and inventory owner]" (required)     

}

The content will be a parsable json and Base64-encoded to a single string like this:

Requestor: ewogICJzYWxlc0FwcGxpY2F0aW9uIjogIlRSQUlEIiwgICAgICAKICAic2FsZXNVbml0Q29kZSI6ICJTVDEyMzQ1NiIKfQ==

Accept-Language

The requestor can request languages Swedish or English

traceparent

 

tracestate

 

Idempotency-Key

 

Code Lists

Samtrafiken is responsible for providing a collection of code lists in the Swedish domain of the OSDM implementation standard. The namespace is defined as “urn:x_swe:” and contains different code lists to handle all sellable stops and carriers in Sweden handled by Samtrafiken.

Name

Code

Link

Details

Name

Code

Link

Details

Stops

urn:x_swe:stn:<nnnnnnnnn>

https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3620175886

National stop ID, 9 digits. “Rikshållplats” in Swedish.

Carrier

urn:x_swe:carrier:<nn>

https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3619717166

 

Product Category (Service Brand Code)

urn:x_swe:sbc:<XXX>

https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3619717173

 

ptMode (transport modes)

ptMode

https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3764158495

 

Attributes (Service Properties)

 

https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3735617539

 

Fare Product Details

The product is one-dimensional. Each product has a its own combination of travel class and flexibility.

Name

Code

Comment

Name

Code

Comment

Flexibility

FULL_FLEXIBLE

SEMI_FLEXIBLE

NON_FLEXIBLE

FULL_FLEXIBLE - Can be refunded (and rebooked)

SEMI_FLEXIBLE - Can be rebooked to another trip

NON_FLEXIBLE - Can not be rebooked or refunded

ServiceClass

STANDARD

HIGH

Only STANDARD and HIGH are currently implemented on the Swedish market. Type of quality level, finer grained than comfort class. E.g. a carrier offers regular First class (STANDARD) and luxury First class (HIGH)

TravelClass

SECOND

FIRST

 

Fulfillment

PDF_A4

Ticket data

Samtrafiken will provide PDF and the distributor can also create ticket with barcode (for carrier offering this) and ticket information. Important the distributor need to use Samtrafiken and carrier’s ticket template

Mandatory passenger and purchaser details

First name, Last name, Email

For the carriers in Samtrafiken’s IMS.

Mandatory passenger details for external IMSs to be verified.

VAT free

isPartOfInternationalTrip

It is up to the requestor to set to true if one or more parts of the journey is international.

BoB Tickets

With BoB, multiple admisson offer parts or admissions may reference the same leg. Read more about this on https://samtrafiken.atlassian.net/wiki/spaces/SamA/pages/3636133889.