Navvo
Guides

Directions & live ETAs

Turn-by-turn routing and traffic-aware arrival times.

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);
The response is an envelope — check 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) }
Need natural-language constraints ("deliver before 11:00, avoid downtown") or multi-stop optimization? Use POST /routing/plan — it builds the request, optimizes stop order, and returns AI-parsed constraints plus logistics-zone risk.
Copyright © 2026