What the routing SDK adds
The routing services, the map modules and the core types are one surface: every response is GeoJSON that the next call and the map take unchanged.
What you get
- One function across two endpoints —
calculateRoute()picks the right one and keeps your parameters valid whichever it picks. - Fields the API does not return, computed from the ones it does.
- Section types drawn and styled by config, not by layer specs.
- Every output is the next call's input — no adapters, one API key.
- The MapLibre escape hatch stays open:
map.mapLibreMap, and a full layer spec per section whenever you want one.
One function, two endpoints
calculateRoute() serves both the regular routing endpoint and the
long-distance EV one, switching on whether you passed
vehicle.preferences.chargingPreferences.
- You never choose, and never have to detect which ran.
- The same parameters mean the same thing on both: every field both endpoints take is built once, so adding charging preferences cannot quietly stop another parameter being honoured.
- A parameter an endpoint cannot take fails at the call rather than being dropped — see A parameter the endpoint cannot accept.
Fields the API does not return
| Field | How the SDK derives it |
|---|---|
LegSummary.stopTimeInSeconds |
The API has no wait-time field; time at a stop is the gap between one leg's arrival and the next leg's departure. Covers a requested wait, EV charging, or both at one stop. |
Route versus leg travelTimeInSeconds |
The route total includes time at stops; per-leg values are driving only. The difference is the time standing still. |
remainingChargeAtArrivalInPCT, batteryConsumptionInPCT, targetChargeInPCT |
The kWh figures converted against your vehicle.model.engine.charging.maxChargeKWH. Absent for a predefined variantId, which declares no capacity. |
Instruction.pathPointIndex |
Each maneuver point matched to its index in the route geometry. |
originalWaypointIndex on each leg |
Maps a leg back to the requested location it ends at, when the service has inserted charging stops of its own. |
countryCodeISO3 on country and vignette sections, countryCode on instructions |
Converted from the API's ISO 2 codes. |
categories on traffic sections |
Read from the incident's TPEG2-TEC cause codes. |
chargingInformationAtEndOfLeg |
A ChargingStop place feature, with chargingSpeed / chargingParkSpeed classes and a dataSources.chargingAvailability.id that getPlaceWithEVAvailability takes as is. |
Sections, drawn and styled
A route carries sections — stretches with a property worth showing: traffic delays, tunnels, ferries, toll roads, low-emission zones, unpaved surfaces, speed limits and more. The route object lists every type.
- Leaving
sectionTypesunset asks for all eighteen requestable types. Naming a list narrows the response to it: the SDK drops any type you left out, even where the API returns it anyway. RoutingModuledraws fifteen of them, and restyling one is config rather than a layer spec:
const routing = await RoutingModule.create(map, {
sections: {
urban: { visible: true },
lowEmissionZone: { color: '#1B7A43', opacity: 0.8 },
},
});
- The stretches worth seeing at a glance draw themselves — tunnels, ferries, toll roads,
traffic;
urbanis opt-in because it runs most of a route. Route sections covers which draw by default and every knob. - What the module keeps right is what rots in a hand-rolled version: z-order between the
selected route and its alternatives, surviving a
setStyle, keeping two route modules on one map from colliding, and hit-testing.
Every output is the next call's input
Each step takes the previous step's response as it stands:
const waypoints = await Promise.all(['Munich, DE', 'Verona, IT'].map(geocodeOne));
const routes = await calculateRoute({ locations: waypoints, vehicle: evVehicle });
// The route feature goes straight into the search
const alongRoute = await discoverPlaces({
filters: { poiCategories: ['CHARGING_LOCATION'] },
route: routes.features[0],
maxDetourTimeSeconds: 300,
});
// The destination waypoint goes straight into the range
const ranges = await calculateReachableRanges([
{ origin: waypoints.at(-1), budget: { type: 'timeMinutes', value: 20 } },
]);
- One key and one configuration for all four calls, and the results go to the map modules unchanged.
- The demo above is this chain, on a map.
Where a reachable range goes
A reachable range is a polygon rather than a route, so RoutingModule
does not draw it: the reachable ranges module does, titling each
band from its budget and nesting each origin's bands.
Related guides and examples
- Route planning parameters – Every parameter
calculateRoutetakes - Long distance EV routing – Charging preferences, and the endpoint they switch on
- Displaying routes –
RoutingModule, section styling and route events - Routing composite – The four-service chain above