Entur's developer portal has moved to developer.entur.no. Use the new portal for the latest documentation. This old version will be retired once its content has moved, but API changes are still published here for now, under News and Notifications.
Client guide
This is a guide for clients on how to sell shared mobility through their own channels with the shared-mobility API.
Note that the endpoints under the "TOMP endpoints" section should only be used by the transport operators to inform us about changes in the journey from their side.
These must not be used by the clients.
Booking a product can be done in two ways:
Selecting a product from the map: By choosing a product from the map, you can use the GBFS data from the Mobility API to display information about the product
(typically price, battery status, location and the distance the unit can travel), check if you have the right to sell the product, and use the assetId to create a booking.
Scanning a QR code: If you want to add functionality for scanning a QR code and then displaying product information, you first need to make a call to
"GET /shared-mobility/v1/qr/qr-code" to retrieve the assetId/vehicleId/bike_id from the scanned QR-code. After that, the sales flow continues as usual.
Payment
This section describes the payment flow for shared mobility bookings.
Recurring payment
Before a booking can be made, a recurring payment agreement must be in place. See the Add Recurring Payment guide for more information.
This will create a recurring payment, which will be used to pay for the bookings made by the user. Send the recurring payment id when creating a booking.
Finalize payment
When the booking is finished (booking state FINISHING/FINISH) and the final amount will be calculated.
The user will be charged the final amount asynchronous when the booking state changes to FINISHING/FINISH.
Failed payments
If the payment fails, this is the current error handling:
We try to charge the user 3 times with 10 seconds interval between each attempt.
If the payment still fails, we will try to charge the user every midnight up to 3 days.
If the payment still fails, we will try to charge the user for unpaid trip the next time the user tries to make a new booking.
A new trip will not be possible until the payment is successful. We use the recurring payment used to create a new booking to charge the user for the unpaid trip.
Authentication
The client should authenticate with the shared-mobility API by providing an OAuth2 bearer token in the request header. The token should be issued by Entur and have the necessary scopes to access the API.
In addition, a header for a specific distribution channel must be provided in the request when booking a trip with shared mobility.
Only distribution channels that have been registered with Entur and have been linked with your client will be accepted.
Returns a list of transport operators you can sell products on behalf of. If a vehicle's operator id (vehicle.system.operator.id in the Mobility API)
is included in this list, you can use the Shared Mobility service to book it.
Get vehicleId (GBFS) given QR-code
GET /shared-mobility/v1/qr/qr-code
Retrive the assetId (TOMP) / vehicleId (GBFS) /bike_id (GBFS) given the scanned QR-code
If you want to add a discount to the booking, you can add it as a pricing adjustment when creating the booking.
The price adjustment will be added to the current amount and final amount of the booking.
This means that if you want to give a discount, the amount should be negative.
If the final amount of the booking is negative after applying the price adjustment, the final amount will be set to 0.
Even tho the final amount will be set to 0 for these cases, the price adjustment will stay the same as when the booking was created.
Take this into consideration when showing the price adjustment to the user in your app.
We currently only support one pricing adjustment per booking, but you can combine multiple discounts into one if needed.
This amount will always be invoiced to the client, and the client can choose to give a discount to the user in their app if they want to.
The client should always make an agreement with the transport operator about how discounts should be handled before using this functionality.
Use this endpoint to change the state of a booking:
START: Start the trip
PAUSE: Pause the trip
RESUME: Resume the trip after pause
START_FINISHING: State usually used when the transport operator want the user to take a picture of the mobility etc. The traveler stops paying more for the journey after this step in the journey.
FINISH: Finish the trip (if a picture of the product is mandatory when finishing the trip, you have to set fileName, fileType and fileData)
Get a list of all bookings given customerNumber. If you set the parameter "active" to true, the endpoint will return all bookings who is not in FINISHED or CANCELLED state.
This is usually used when retrieving an active booking if the user closes the app in the middle of a trip.
All error objects look the same and follow this structure:
{
"timestamp": "2024-09-17T08:49:33.814422231+02:00",
"status": 409,
"error": "Conflict",
"exception": "VehicleNotFoundException",
"message": "Could not start trip. This vehicle is not available right now.",
"path": "/bookings/one-stop"
}
The message is provided as human-readable text, translated into Norwegian Bokmål, Norwegian Nynorsk, or English.
The language is determined by the 'Accept-Language' header in the request.
Here is a list of all error messages:
When
What
Exception
Response code
Response text (Accept-Language: Human readable text)
Scan QR-code
Find info about operator and vehicle given QR-code
CouldNotFindAssetException
404
NOB: Kunne ikke finne kjøretøy.
NNO: Kunne ikkje finne køyretøy.
ENG: Could not find asset.
Create booking, start trip, finish trip
Check if transport operator support chosen service
EndpointUnavailableException
400
NOB: Operatøren tilbyr ikke denne tjenesten.
NNO: Operatøren tilbyr ikkje denne tenesta
ENG: Operator does not provide this service
Create booking
Get info about transport operator
UnknownOperatorException
400
NOB: Operatør av kjøretøy ukjent.
NNO: Operatør av køyretøy ukjent.
ENG: Operator of vehicle unknown.
Create booking
Check access
InsufficientAccessException
403
NOB: Din leverandør har ikke tilgang til dette kjøretøyet.
NNO: Leverandøren din har ikkje tilgang til dette køyretøyet.
ENG: Your provider does not have access to this vehicle.
Create booking
Check recurring payment agreement
PaymentAgreementMissingException
400
NOB: Kunne ikke starte tur. Vi fant ingen gyldig betalingsmetode. Prøv igjen med et annet kort.
NNO: Kunne ikkje starte tur. Vi fann ingen gyldig betalingsmetode. Prøv igjen med eit anna kort.
ENG: Could not start trip. We could not find a valid payment method. Try again with a different card.
Create booking
Create order
CouldNotStartTripException
500
NOB: Kunne ikke starte tur. Prøv igjen eller velg et annet kjøretøy.
NNO: Kunne ikkje starte tur. Prøv igjen eller vel eit anna køyretøy.
ENG: Could not start trip. Try again or choose another vehicle.
Create booking
Active booking already exists
ActiveBookingAlreadyExistsException
409
NOB: Du har allerede en aktiv tur. Du kan bare ha én aktiv tur om gangen.
NNO: Du har allereie ein aktiv tur. Du kan berre ha éin aktiv tur om gongen.
ENG: You already have an active trip. You can only have one active trip at a time.
Start trip
Change state of trip
TompCreateOneStopBookingEventException
500
NOB: Kunne ikke endre tilstanden på turen. Leverandøren avslo forsøket. Prøv igjen eller velg et annet kjøretøy.
NNO: Kunne ikkje endre tilstanden på turen. Leverandøren avslo forsøket. Prøv igjen eller vel eit anna køyretøy.
ENG: Could not change state of trip. The provider refused the attempt. Try again or choose another vehicle.
Finish trip
Change state of trip
TompCreateOneStopBookingEventException
500
NOB: Kunne ikke avslutte tur. Leverandøren avslo forsøket. Prøv igjen eller ta kontakt med {operator}
NNO: Kunne ikkje avslutte tur. Leverandøren avslo forsøket. Prøv igjen eller ta kontakt med {operator}.
ENG: Could not end trip. The provider declined the attempt. Try again or contact {operator}.
Finish trip
Change state of trip
InvalidParkingZoneException
403
NOB: Ugyldig parkeringsområde.
NNO: Ugyldig parkeringsområde.
ENG: Invalid parking zone.
Finish trip
Illegal image type
IllegalImageTypeException
400
NOB: Ulovlig format på bildet.
NNO: Ulovleg format på bildet.
ENG: Illegal image type.
Change state of trip
Illegal event
IllegalEventException
400
NOB: Ulovlig hendelse i gjeldende tilstand.
NNO: Ulovleg hending i gjeldande tilstand.
ENG: Illegal event in current state.
Kafka Queue: Purpose and Usage
Introduction
This document is intended for clients, particularly those offering mobile applications for ticket sales, who will consume messages from our Kafka queue. The aim is to provide an overview of the queue's purpose, its functional role, and the type of data transmitted through it. This documentation focuses on the functional aspects, explaining the value and context of the queue. Technical details, such as integration steps, authentication, and protocols, will be covered separately.
Purpose of the Kafka Queue
The Kafka queue is a distributed messaging system designed to ensure real-time data exchange between different systems and clients. Its primary purpose is to reliably and efficiently distribute critical updates and event data, enabling client applications to provide accurate and up-to-date information to their end users.
For clients developing ticket-selling apps, the Kafka queue is essential for delivering real-time updates such as battery status, current ticket prices, and other dynamic information directly to users. This allows applications to enhance their user experience by offering timely and actionable insights, improving customer satisfaction and operational efficiency.
Type of Data Transmitted
Structured messages in the form of Avro-serialized objects are sent through the Kafka queue. These messages are self-descriptive and contain essential details regarding events or updates.
Primary Object Type: SharedMobilityKafkaEvent
The main object type transmitted through the queue is the SharedMobilityKafkaEvent, which encapsulates real-time updates related to mobility services and bookings.
The key fields include:
Timestamp:
The event's creation time, represented as a long in microseconds since January 1, 1970 (UTC). This ensures precision and allows chronological processing of events.
Booking Updates:
Details about a specific booking, including:
Booking ID: A unique identifier for the booking.
State: The current status of the booking, such as "IN_USE," "FINISHED," or "CANCELLED."
Pricing Details: Information about current and final ticket prices.
Operator Information: The mobility service provider associated with the booking.
Battery Status: Current charge percentage of a vehicle or device.
Dynamic Pricing and Plans:
Pricing plans include currency, base price, and per-minute pricing details for transparency in cost estimation.
Metadata and Additional Information:
Fields like "departureTime," "arrivalTime," "stateOfCharge," and "comments" provide contextual details.
Why Use the Kafka Queue?
1. Real-Time Information for Users
The Kafka queue enables ticket-selling apps to access up-to-date information about bookings and services, allowing them to deliver real-time updates to end users. For example:
Notifying users of changes in ticket prices.
Displaying real-time battery status for rented mobility devices.
2. Decentralized Processing
Clients can independently consume and process data from the Kafka queue. This decentralized approach allows each application to focus on its specific needs without relying on centralized processing.
3. Reliability and Scalability
Kafka is designed for high throughput and reliability, ensuring that messages are delivered without loss even during high traffic. This is critical for clients who need consistent data streams for accurate service delivery.
4. Standardized Data
By using Avro serialization, all messages follow a standardized schema. This minimizes compatibility issues and simplifies integration for client applications.
Example Use Case: Real-Time Ticket Updates
A ticket-selling app consuming the Kafka queue can:
Notify a user if the cost of their ticket changes.
Provide up-to-date battery status for a shared mobility vehicle, helping users decide whether it's suitable for their journey.
Example Data Structure
Below is an example of a SharedMobilityKafkaEvent message: