Skip to main content

Overview

Get routing options that integrate live bike-share availability. Returns multiple route alternatives:
  • Personal bike: direct cycling route, returned in both the SuperSafe and the direct variant
  • Docked bike-share: walk to station, cycle, then walk to the destination. Pickup and drop-off are always in the same system.
  • Docked e-bike: the same shape, from the nearest station with an e-bike available. Marked is_electric: true.
  • Dockless bike-share: walk to the bike, then cycle to the destination. One option per provider. Marked is_electric: true when the nearest vehicle is electric, which is every Lime and Forest bike.
Behavior:
  • Every response includes both the supersafe: true and supersafe: false personal variants, collapsed to one when they are identical, plus the other option types once at supersafe: true. Filter locally on each option’s supersafe flag; there is no request parameter for it.
  • Alternatives more than 3× slower than the personal bike route are filtered out
  • Bike availability is fetched in real time from bike-share system feeds and provider APIs
  • Assumed speeds: walking 5 km/h, cycling 15 km/h, e-bike 22 km/h
  • Maximum bike/station search radius: 1,500 m
  • Results are ordered Personal (SuperSafe first), then docked, docked e-bike, dockless
Versions are a per-endpoint path segment; this page documents v2 (POST /multi-modal/v2/). See API versioning.

Authentication

This endpoint requires an API key. Include it in the apikey header:
A valid user session is also accepted and grants higher rate limits.

Rate limits

Requests are rate-limited; authenticated requests are allowed a higher rate than anonymous ones. Multi-modal has a stricter limit than directions. On 429, honor the Retry-After header.

Performance

  • Typical response time: 800–1500 ms
  • Routing segments are computed in parallel

Request body

array
required
Starting point as [longitude, latitude]
array
required
Ending point as [longitude, latitude]
string
Identifier of a saved custom route, a UUID string (for example "a3b8c9d0-1e2f-4a5b-8c7d-6e5f4a3b2c1d"). When it resolves to a route, that route is appended as one or more non-reroutable cycling legs — one per stop on the route (see Custom routes) — and its details are returned in each option’s event field.
string
Destination ID for enriched destination information in the response, a UUID string (for example "3f9c6a1e-8b2d-4c5f-9e7a-1d2b3c4d5e6f").
string
Display name for the destination (used if destination_id not provided)
string
Display name for the origin waypoint
string
Planned departure as "YYYY-MM-DDTHH:mm" with no timezone offset, interpreted in the route city’s timezone. Determines night routing (see nighttime) and which temporary road avoidances apply; nearby active or imminent closures are surfaced per option as disruptions. Omit to route for now. Unparseable values return 400.
string
default:"en"
Language of every instruction, spoken cue, leg label and option label: en (English) or es (Spanish). A regional tag such as es-MX is accepted and read as its base language. Any other language returns 400. Enumerated values (bike_type, end_kind, maneuver type and modifier) are the same in every language.
string
Navigate-to-parking mode: "ebike" (designated rental e-bike bays) or "regular" (cycle racks/stands: TfL surveyed stands in London, NYC DOT racks in New York City and SFMTA racks in San Francisco). The Personal option becomes cycle-to-spot + walk-to-destination, ending at the nearest qualifying spot within 1,500 m of the destination; the spot is returned in parking. If none is found, or the destination borough does not mandate bays for "ebike", the option stays direct with parking: null. Use destination_parking to tell “park anywhere” from “no parking found”. Ignored when a custom route is attached. Other option types are unaffected.
string
Rental e-bike operator (London): "lime" or "forest". Restricts the "ebike" bay search to boroughs the operator serves; when the destination borough isn’t served, the route ends at the nearest bay inside the operator’s area and walks the rest (destination_parking.covered: false).
array
Intermediate stops between origin and destination, as [longitude, latitude] pairs in travel order, up to 23. The Personal option then carries one cycling leg per consecutive pair, each intermediate leg ending at its stop with end_kind: "stop" and an end_label of "Stop 1", "Stop 2", … in the requested language; parking_type still applies to the final hop. Only the Personal option composes with stops: with stops set, bike-share options are not built, and combining it with event_id returns 400. Every stop adds a hop to each Personal variant, so the request costs one rate-limit token per hop. See Personal route through stops.

Response body

string
Unique identifier (UUID) for this request. Include it in support enquiries.
array
Array of route option objects. An empty array with a 200 status means no viable option exists between the requested points; a temporary routing outage returns 503 instead.
object | null
The destination borough’s rental e-bike parking rule. Set on every request whose destination falls inside a bounded area (a London borough), whatever parking_type is, so a rider comparing a rental e-bike option can see the rule they will park under; null elsewhere.
  • ebike_parking_rule: "bay_mandatory" (hires must end in a designated bay) or "free_floating" (park anywhere; render as “park anywhere in area_name”, not an error).
  • With an operator in the request, also carries operator and covered, indicating whether that operator serves the borough.
The response example is captured from a real request. Long arrays in it are abridged with …. Each leg’s steps follows the same step shape as a Get directions response.

Variants

With a custom route

JavaScript

Route types

Personal bike

  • Direct cycling route, always first in results, in both the SuperSafe and direct variant
  • With parking_type set: cycle to the returned parking spot, then walk to the destination

Docked bike-share (GBFS/TFL)

  • Walk → cycle station-to-station → walk
  • Included only when suitable stations exist within 1.5 km
  • Omitted when the pickup and drop-off resolve to the same station — there is no bike-share leg to ride. A custom route still allows it, since the route itself is the ride

Docked e-bike

  • Same shape, from the nearest station with an e-bike available; cycling legs use the e-bike speed
  • Marked is_electric: true; name is "{system name} E-bike"

Dockless bike-share

  • Walk to the nearest available bike → cycle to destination, one option per provider
  • Marked is_electric: true when the vehicle is electric; its cycling legs then use the e-bike speed
  • Included only when a bike exists within 1.5 km and is standing inside its operator’s service area. A bike parked outside that area is skipped, because a rental cannot start there

Custom routes

When event_id resolves to a custom route:
  1. All cycling legs route to the custom route’s starting point
  2. Non-reroutable cycling legs are appended for the custom route itself — one leg per stop on the route, so a route with two intermediate stops arrives as three consecutive legs. Each leg ends with an arrive step named after its stop ("Arrive at Look Mum No Hands"); a route with no stops stays a single leg. Sum the non-reroutable legs for the route’s total distance and duration
  3. Custom route details are included in each option’s event field
  4. For docked bike-share, the final walking leg goes to the nearest station to the custom route’s endpoint

Personal route through stops

Add stops to route the Personal option through intermediate points. Each stop becomes a leg boundary: a request with two stops arrives as three consecutive cycling legs, the first two ending with end_kind: "stop" ("Stop 1", "Stop 2"), the last with the usual end. Each leg is aggregated on its own, so it starts with a depart step and ends with its own arrive step, and equals the route a plain origin-to-destination request for that pair returns. Both SuperSafe regimes come back as usual, and the SuperSafe variant’s avoidance covers the whole route.
Bike-share options are not built for a request with stops, and stops cannot be combined with event_id (a saved custom route already fixes where the ride goes). Set parking_type to end the personal route at a real parking spot near the destination, with a walking leg the rest of the way. The chosen spot comes back in parking and the cycling leg’s end_label is "Park bike".
destination_parking reports the destination borough’s rule on every request. For "ebike" requests it lets you tell “park anywhere” (free_floating, no bay returned) from “no parking found” (parking: null in a bay_mandatory borough); for other requests it is the rule a dockless e-bike option will end its hire under.

Step semantics

Each leg’s steps follows the same turn-by-turn shape as the directions endpoint:
  • step.distance is the length of the road after the maneuver. To render “in X metres, …”, use the previous step’s distance.
  • step.maneuver.location equals step.geometry.coordinates[0].
  • The final step of every leg is "Arrive at destination".
  • voice_instructions and banner_instructions are generated per leg independently, because every leg ends in its own arrive step.

Error responses

400 Bad request

Out-of-coverage routing carries a machine-readable code and the request’s search_id:

401 Unauthorized

404 Unknown version

Returned for a version sub-path that does not exist (e.g. POST /multi-modal/v3/). See API versioning.

405 Method not allowed

Returned for any HTTP method other than POST.

429 Too many requests

Includes a Retry-After header with the seconds until the current window closes:

500 Internal server error

503 Service unavailable

Routing is temporarily unavailable. This is distinct from a genuine no-route result, which returns 200 with an empty options array. Retry after a short delay.