Directions & live ETAs
Directions & live ETAs
Get turn-by-turn directions and an arrival time that reflects current congestion. Uses Routing for the geometry and POST /traffic/route for the traffic-adjusted ETA.
Scopes required: routing (and traffic for live ETAs).
Basic directions
POST /routing/route runs on Navvo's routing engine. Locations use the routing engine's native { lat, lon }:
const res = await fetch("https://navvo.io/api/v1/routing/route", {
method: "POST",
headers: { "x-api-key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({
payload: {
locations: [
{ lat: 31.9539, lon: 35.9106 },
{ lat: 31.9921, lon: 35.9505 },
],
costing: "auto",
directions_options: { units: "kilometers", language: "en-US" },
},
}),
});
const out = await res.json();
if (!out.available) throw new Error("Routing engine unavailable");
const trip = out.data.trip;
console.log(trip.summary.length, "km,", trip.summary.time, "s");
const steps = trip.legs[0].maneuvers.map((m) => m.instruction);
available before reading data. trip.legs[].shape is an encoded polyline (precision 1e6); decode it to draw the route on a map. All routing endpoints return HTTP 201 on success.Traffic-aware ETA
For an ETA adjusted to live, Navvo-sourced traffic, use POST /traffic/route. It uses a friendlier { lon, lat } body and returns colored segments ready to render:
const res = await fetch("https://navvo.io/api/v1/traffic/route", {
method: "POST",
headers: { "x-api-key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({
locations: [
{ lon: 35.9106, lat: 31.9539 },
{ lon: 35.9505, lat: 31.9921 },
],
costing: "auto",
departureTime: new Date().toISOString(),
}),
});
const r = await res.json();
console.log("Free-flow:", r.baseDurationSeconds, "s");
console.log("With traffic:", r.durationInTrafficSeconds, "s");
console.log("Delay:", r.delaySeconds, "s");
console.log("Arrival:", r.arrivalTime);
r.segments is a GeoJSON FeatureCollection colored by congestion — add it straight to Navvo Maps:
map.addSource("route", { type: "geojson", data: r.segments });
map.addLayer({
id: "route",
type: "line",
source: "route",
paint: { "line-color": ["get", "color"], "line-width": 6 },
});
Route to a place's entrance
When routing to a Navvo place, use its recommended entrance instead of the center pin:
const place = await (await fetch(`https://navvo.io/api/v1/places/${slug}`, { headers: { "x-api-key": KEY } })).json();
const dest = place.arrivalIntelligence.candidates[0].routeTarget; // { lat, lng }
// traffic-aware route to the entrance:
const body = { locations: [origin, { lon: dest.lng, lat: dest.lat }], costing: "auto" };
Travel-time matrix
To compare many origins/destinations at once (e.g. nearest driver), use POST /routing/matrix instead of N route calls — it's one request and far kinder to your quota.
const res = await fetch("https://navvo.io/api/v1/routing/matrix", {
method: "POST",
headers: { "x-api-key": KEY, "Content-Type": "application/json" },
body: JSON.stringify({
payload: {
sources: [{ lat: 31.95, lon: 35.91 }, { lat: 31.99, lon: 35.95 }],
targets: [{ lat: 31.90, lon: 35.93 }],
costing: "auto",
},
}),
});
// out.data.sources_to_targets[i][j] -> { time (s), distance (km) }
POST /routing/plan — it builds the request, optimizes stop order, and returns AI-parsed constraints plus logistics-zone risk.