Discovery endpoints provide the reference data and availability data needed by user-facing apps: branches, vehicles, categories, stations, physical stations, POIs, attributes, and selected settings. Use these endpoints for maps, vehicle detail screens, station selection, booking discovery, and localized app configuration.
| Related reference: User API | Stations User API | Points-Of-Interest User API | User API Guide | Radar Guide | Tutorial Guide | Fair-Use Policy |
A branch represents a geographic and operational context. Branches influence available vehicles, categories, pricing, rental requirements, packages, subscriptions, terms, stations, and payment behavior.
Use the branch resolver when an app needs to determine the best branch for a user position. Use direct branch reads when the app already knows the branch ID.
GET /vehicles is the main customer-facing availability endpoint. It is intended for app maps and nearby vehicle discovery. Responses can include location, category, battery/state-of-charge information, pricing-related fields, promotion context, and rental eligibility hints depending on tenant configuration.
Poll this endpoint responsibly. Availability changes frequently, but excessive polling can affect platform performance.
Vehicle categories describe user-facing vehicle types and their rental behavior. Category configuration can affect allowed actions, additions, pricing options, booking availability, rental requirements, battery thresholds, and display metadata.
The User API exposes station concepts for user-facing discovery. Station data can support station-based vehicles, physical docking/parking infrastructure, booking station selection, and parking-area availability.
Points of interest are informational map markers. They are not a replacement for stations, areas, or business rules. Use them to show helpful map locations such as service points, partner locations, or informational markers.
| Task | Endpoint |
|---|---|
| List branches | GET /branches |
| List branch IDs | GET /branches/ids |
| Resolve closest or fallback branch | GET /branches/resolve |
| Get branch detail | GET /branches/{id} |
| Get intersectable branches | GET /branches/{id}/intersectable |
Branch data is good cache material, but refresh it periodically because service areas, settings, and branch availability can change.
| Task | Endpoint |
|---|---|
| List available vehicles | GET /vehicles |
| Get vehicle by ID | GET /vehicles/{id} |
| Get vehicle by code | GET /vehicles/code/{code} |
| Check start rental requirements | GET /rentals/requirements |
| List the user’s vouchers | GET /vouchers |
| Locate a vehicle | POST /vehicles/{id}/locate |
| Generate Bluetooth tokens | POST /vehicles/{id}/bluetooth/generate-tokens |
Use GET /vehicles/code/{code} for scan flows. Use GET /vehicles/{id} when the user opens a detail sheet from the map. Use Bluetooth token generation only when the app is about to perform an allowed BLE action for the selected vehicle.
Use GET /vehicles as a map-viewport query, not as a full-fleet sync endpoint. This is especially important for branches with many vehicles. Repeatedly loading the full branch fleet for every map refresh can produce very large responses, slow down the app, and run into rate limiting that protects the platform service.
For mobile and web maps, derive the query from the visible viewport:
lat and lng.rad from the current viewport, normally the distance from the center to the farthest visible corner.rad in miles.branchId, categoryId, excludeStationedVehicles, and minStateOfCharge before rendering markers.Example:
GET /vehicles?branchId=3&lat=48.20849&lng=16.37208&rad=1.2&categoryId=7&minStateOfCharge=30
Do not call GET /vehicles without spatial parameters for interactive maps unless the app is intentionally showing a complete branch-level availability list. Without lat, lng, and rad, the endpoint can return all available vehicles in the accessible branches, which is usually more data than a map needs. Apps that poll this unbounded response frequently, especially in high-volume branches, should expect throttling or rate limiting to protect service stability.
The spatial parameters are all-or-nothing: if you send one of lat, lng, or rad, send all three. The backend uses the provided center and radius to reduce the candidate set and also applies tenant-level minimum-radius behavior so very small map views still return a usable result around the user. Because the API can return candidates around the viewport, the client should still avoid rendering markers that are outside the visible map bounds.
Use this refresh pattern for map screens:
GET /vehicles with the viewport-derived lat, lng, and rad.GET /vehicles/{id} before acting on it.Use the filters intentionally:
| Parameter | How to use it |
|---|---|
branchId |
Send it when the app already knows the active branch. This keeps the result scoped to the branch the user is browsing. |
lat, lng, rad |
Use the current map viewport. rad is in miles and must be sent with both coordinates. |
categoryId |
Send one or more category IDs when the user selected vehicle types, for example only scooters or only e-bikes. |
excludeStationedVehicles |
Set to true for free-floating-only map views. Keep false when station-based vehicles should also be shown. |
minStateOfCharge |
Use for app-level filters such as “show vehicles with at least 30% battery”. The value is a percentage from 0 to 100. |
If the app has both free-floating vehicles and station-based availability, keep those display modes explicit. Use GET /vehicles for available vehicle markers, and use station or physical-station endpoints for station markers, parking locations, docking infrastructure, and station detail screens.
If the current viewport has no suitable vehicle, offer a vehicle radar instead of widening the map request indefinitely. A radar lets the user save a radius and receive a notification when an available vehicle appears in that area. See the Radar Guide for the full flow.
Vehicle discovery can mark vehicles that have a user-facing benefit. Use the benefits array on GET /vehicles responses to decide how the marker should look:
| Benefit | What it means | Suggested map treatment |
|---|---|---|
DISCOUNTED |
A vehicle or geofence promotion currently applies to this vehicle. | Show a discount badge or highlighted marker. |
REWARDED |
The vehicle is configured as a reward vehicle. | Show a reward badge or highlighted marker. |
The legacy benefit field can contain one value, but new clients should prefer benefits because a vehicle can carry more than one benefit.
GET /vehicles is optimized for map discovery. It tells the app that a vehicle should be visualized as discounted, but it should not be treated as the source of the exact discount copy. When a user taps a discounted marker or opens the vehicle sheet, call GET /vehicles/{id} or GET /vehicles/code/{code} and read pricing.discount.
Use the returned pricing discount like this:
| Field | Meaning | Display example |
|---|---|---|
pricing.discount.discountPercentage |
Fractional discount. 0.2 means 20% off. Multiple applicable percentage discounts can be combined by the backend. |
20% off |
pricing.discount.discountValue |
Fixed rental rebate amount in the vehicle currency. | €2 off |
If both values are present, show both only when the product design has enough room and the wording is clear. Otherwise prefer a concise badge on the map and explain the full discount in the vehicle detail sheet.
Example vehicle-map logic:
if vehicle.benefits contains DISCOUNTED:
render discounted marker
on marker tap:
GET /vehicles/{id}
if pricing.discount.discountPercentage is present:
show "{discountPercentage * 100}% off"
if pricing.discount.discountValue is present:
show "{discountValue} off"
Discount visibility and discount application are related but not identical. The map marker should communicate that a benefit is available now. The rental start and billing flow still performs the final eligibility and pricing checks, because promotions can depend on time, branch, category, geofence, vehicle annotations, user eligibility, and redemption limits.
When a user taps a vehicle, the app can show which of the user’s vouchers are eligible for that selected vehicle. Do this from the vehicle detail response, not from the map list alone.
Recommended flow:
GET /vehicles.GET /vehicles/{id} or GET /vehicles/code/{code}.vehicle.applicableVouchers.applicableVouchers is scoped to the authenticated user, the vehicle’s branch, and the vehicle category. In other words, it answers: “Which of this user’s active constraint vouchers can be used for a rental with this vehicle type in this branch?”
Useful voucher fields for display:
| Field | Meaning |
|---|---|
name |
User-facing voucher name. |
voucherableCode |
Code of the voucher template or redeemable campaign behind the issued voucher. |
rentalRebate / rentalRebateNet |
Monetary rebate amount. |
valueGross / remainingValueGross |
Monetary value still available on value-based vouchers. |
freeMinutes / remainingFreeMinutes |
Free-minute entitlement, when the voucher represents minutes instead of money. |
numberOfRentals / remainingNumberOfRentals |
Rental-count limits. |
validFrom / validUntil |
Validity window. |
applicablePriceType |
Price component the voucher targets, such as driving, parking, distance, reservation, or unlock fee. |
Use GET /vouchers?branchId={branchId}&active=true when building a voucher wallet or benefits screen for the selected branch. Do not use that list alone to decide what to show on a specific vehicle detail screen, because vehicle category constraints still matter. If you need to enrich a selected vehicle voucher with fields from the broader voucher list, match by voucherableCode and prefer vehicle.applicableVouchers as the source of vehicle-level eligibility.
If multiple vouchers are returned, treat them as eligible vouchers, not as a guaranteed ordered application result. At billing time, the backend applies the final voucher rules on the rental. The current pricing logic applies cost-source-scoped vouchers before broad vouchers, applies at most one rebate or percentage-discount voucher per rental, and can apply value vouchers until the rental price reaches zero. The final applied rebate is visible in the rental or invoice pricing after the rental is priced.
Example detail-sheet logic:
on marker tap:
GET /vehicles/{id}
if applicableVouchers is not empty:
show "Voucher available"
show the best readable value from rentalRebate, remainingValueGross, or remainingFreeMinutes
else if pricing.discount is present:
show the vehicle or geofence promotion from pricing.discount
When a user taps a vehicle, do not wait until POST /rentals to discover that the user cannot start. Use the selected vehicle’s branchId and categoryId to retrieve the current user’s start rental requirements.
Typical detail-sheet flow:
GET /vehicles.GET /vehicles/{id} to load current vehicle detail, pricing, benefits, and availability.GET /rentals/requirements?branchId={branchId}&vehicleCategoryId={categoryId}.fulfilled=false.message and route the user to the relevant setup flow.Example:
GET /rentals/requirements?branchId=3&vehicleCategoryId=7
Example response shape:
[
{
"rentalRequirement": "LICENSE",
"fulfilled": false,
"message": "Please verify your driving license."
},
{
"rentalRequirement": "PAYMENT_SOURCE",
"fulfilled": false,
"message": "Please add a payment method."
}
]
The API response is the UI checklist. message is the localized user-facing explanation; rentalRequirement is the stable code your app should use to decide which screen or call-to-action to open.
Common requirement handling:
| Requirement | What it usually means | Suggested action |
|---|---|---|
LICENSE |
Driving license verification is missing, pending, rejected, expired, or requires reverification. | Route to driving license verification, usually starting with POST /verification/init. |
ID_DOCUMENT, MANUAL, CUSTOM_EXTERNAL_VERIFICATION |
The tenant requires additional identity, manual, or custom verification. | Route to the configured verification flow. |
PAYMENT_SOURCE, PAYMENT_ANY, PAYMENT_PUSH |
The user has not fulfilled the required payment setup for this branch/category. | Route to payment method setup or package/payment flow. |
TERMS_ACCEPTED, TERMS_ACCEPTED_LATEST, RENTAL_AUTHORITY |
The user has not accepted required terms or does not yet have rental authority on the branch. | Show and accept the required branch terms before retrying. |
MINIMUM_AGE, MAXIMUM_AGE, USER_REQUIRED_DRIVING_LICENCE_TYPE_PRESENT, INSUFFICIENT_B_CATEGORY_DURATION |
The user’s profile or license category/tenure does not satisfy this vehicle category. | Explain the blocker; only route to profile or verification if the user can resolve it. |
USER_HAVE_ENOUGH_BALANCE, POSITIVE_CREDIT, USER_HAS_NO_UNPAID_INVOICES |
The account, wallet, balance, credit, or invoice state blocks rental start. | Route to balance top-up, invoice payment, or support depending on tenant setup. |
RIDE_PASS, PREVIOUS_RENTALS, VEHICLE_IN_STATION_AREA |
The branch/category has a specific configured requirement. | Show the returned message and product-specific action. |
For business-account or group-funded rentals, include the selected user group:
GET /rentals/requirements?branchId=3&vehicleCategoryId=7&userGroupId=42
For booking or pre-booking flows, include the intended booking window so price- and time-dependent checks can be evaluated:
GET /rentals/requirements?branchId=3&vehicleCategoryId=7&bookingStartTime=2026-05-21T10:00:00Z&bookingEndTime=2026-05-21T12:00:00Z
Do not hard-code requirement text from rentalRequirement alone. Use the returned message for display, because the same code can represent different user states. For example, LICENSE can mean the user never started verification, the license is still processing, verification was rejected, the license expired, or reverification is required.
| Task | Endpoint |
|---|---|
| List vehicle categories on a branch | GET /vehicles/categories |
| Get vehicle category detail | GET /vehicles/categories/{id} |
| List vehicle attributes | GET /vehicle-attributes |
| Get on-demand pricing options | GET /on-demand-pricing-options |
Use category and pricing-option data together before creating a rental when a branch supports multiple on-demand pricing choices.
Use vehicle utility endpoints only after the user has selected a vehicle or has an active/reserved rental context.
| Task | Endpoint |
|---|---|
| Trigger locate behavior | POST /vehicles/{id}/locate |
| Generate Bluetooth access tokens | POST /vehicles/{id}/bluetooth/generate-tokens |
POST /vehicles/{id}/locate is a user-facing convenience action to help the user find the selected vehicle, for example by flashing lights or sounding a configured signal. Re-read the vehicle after locate actions if the UI depends on fresh state.
POST /vehicles/{id}/bluetooth/generate-tokens is used by app flows that need Bluetooth access tokens for supported vehicles. Generate tokens close to the moment they are needed, store them only according to the app’s secure-storage policy, and do not assume every vehicle category or IoT integration supports Bluetooth access.
| Task | Endpoint |
|---|---|
| List stations from the main User API | GET /stations |
| List tenant stations from the Stations User API | GET /stations |
| Get tenant station detail from the Stations User API | GET /stations/{stationId} |
| List physical stations | GET /physical-stations |
| Get physical station detail | GET /physical-stations/{id} |
| List points of interest | GET /pois |
| List POI categories | GET /categories |
Physical stations and booking stations can affect parking, booking, and rental-end behavior. POIs are informational markers only.
| Task | Endpoint |
|---|---|
| Read selected settings | GET /settings |
| Get localized message resources | GET /resources/messages |
| List available message languages | GET /resources/messages/languages |
Use GET /settings only for known user-facing setting keys. Do not build broad setting-catalog flows with the User API. Tutorials have their own flow; see the Tutorial Guide.
| Area | Endpoints |
|---|---|
| Branches | GET /branches, GET /branches/ids, GET /branches/resolve, GET /branches/{id}, GET /branches/{id}/intersectable |
| Vehicles | GET /vehicles, GET /vehicles/{id}, GET /vehicles/code/{code}, POST /vehicles/{id}/locate, POST /vehicles/{id}/bluetooth/generate-tokens |
| Rental readiness | GET /rentals/requirements |
| Vouchers on selection | GET /vehicles/{id}, GET /vehicles/code/{code}, GET /vouchers |
| Categories and attributes | GET /vehicles/categories, GET /vehicles/categories/{id}, GET /vehicle-attributes, GET /on-demand-pricing-options |
| Stations | GET /stations, GET /physical-stations, GET /physical-stations/{id} |
| Specific station API | GET /stations, GET /stations/{stationId} in station-user-api.yaml |
| POIs | GET /pois, GET /categories in pois-user-api.yaml |
| Content and settings | GET /settings, GET /resources/messages, GET /resources/messages/languages |
lat, lng, and rad for interactive vehicle maps instead of loading all available vehicles.benefits from GET /vehicles for discounted or rewarded map markers, then re-read the vehicle detail to show exact discount copy.applicableVouchers from GET /vehicles/{id} or GET /vehicles/code/{code} to show vouchers eligible for the selected vehicle; use GET /vouchers for wallet-style lists.GET /rentals/requirements after vehicle selection so users see missing setup steps before starting a rental.