Traffic & Incidents
Traffic & Incidents
Real-time and typical congestion derived entirely from Navvo's own anonymous probe network (there is no third-party traffic feed), plus crowdsourced road incidents.
Scope required: traffic (the traffic-aware POST /traffic/route needs both routing and traffic).
[lng, lat]. The bbox parameter is west,south,east,north. Congestion line "tiles" return GeoJSON, not binary vector tiles. Congestion vocabulary: level ∈ free | slow | heavy | standstill; congestion ∈ light | moderate | heavy | blocked.GET /traffic/layers
Layer descriptor and legend for the live traffic layer.
{
"layerType": "traffic",
"name": "Live traffic",
"source": "navvo-user-traffic",
"tilePattern": "/api/v1/traffic/lines/tiles/{z}/{x}/{y}",
"refreshSeconds": 60,
"legend": {
"free": { "label": "Free flow", "color": "#2dbe60" },
"slow": { "label": "Slow", "color": "#f9a825" },
"heavy": { "label": "Heavy", "color": "#e84b36" },
"standstill": { "label": "Standstill", "color": "#a01a12" }
}
}
GET /traffic/summary
Aggregate live conditions over a bbox (or globally if bbox is omitted).
Query parameters
west,south,east,north. Omit to summarize all current edges.{
"source": "navvo-user-traffic",
"bbox": "35.85,31.90,35.99,31.99",
"conditions": {
"hasData": true,
"sampledSegments": 128,
"congestionScore": 0.42,
"level": "slow",
"congestion": "moderate",
"summary": "Slow moving",
"breakdown": [
{ "level": "free", "segments": 60, "share": 46.9 },
{ "level": "slow", "segments": 40, "share": 31.2 }
]
},
"freshnessAt": "2026-06-09T08:55:00.000Z",
"freshnessLabel": "From Navvo users"
}
congestionScore is a 0–1 weighted mean.
Typical-traffic blend (cold start)
When no live probes cover the view, the summary doesn't go blank: it answers from Navvo's learned typical profile for the current hour instead. The response is clearly flagged — it is never presented as live:
{
"source": "navvo-typical-traffic",
"bbox": "35.85,31.90,35.99,32.02",
"conditions": {
"hasData": true, "sampledSegments": 0, "typical": true,
"level": "free", "congestion": "light",
"summary": "Typically free flowing now", "congestionScore": 0.11,
"breakdown": [ … ]
},
"freshnessAt": null,
"freshnessLabel": "Typical for this hour (no live reports yet)"
}
Switch on source: navvo-user-traffic means live probe data (freshnessLabel: "From Navvo users"); navvo-typical-traffic means the historical estimate — show it with the freshnessLabel (e.g. as "Typical for this hour"), not as a live reading. When there is neither live nor typical coverage, hasData is false and level is null with freshnessLabel: "Awaiting Navvo user traffic".
GET /traffic/lines/tiles/{z}/{x}/{y}
Live congestion lines for one tile, as a GeoJSON FeatureCollection (only edges observed in the last ~6 hours).
curl -s "https://navvo.io/api/v1/traffic/lines/tiles/14/9783/6592" -H "x-api-key: nvvo_YOUR_KEY"
{
"type": "FeatureCollection",
"hasData": true,
"features": [
{
"type": "Feature",
"properties": { "level": "slow", "congestion": "moderate", "color": "#f9a825", "edgeId": "edge-12345", "averageSpeedKph": 22.4, "freeFlowSpeedKph": 50 },
"geometry": { "type": "LineString", "coordinates": [[35.9106, 31.9539], [35.9121, 31.9558]] }
}
]
}
GET /traffic/lines/tile-cover
Compute the tiles covering a bbox for the live line layer, with ready-made URLs.
Query parameters
west,south,east,north.14.24.{
"layerType": "traffic", "zoom": 14, "capped": false,
"tilePattern": "/api/v1/traffic/lines/tiles/{z}/{x}/{y}",
"tiles": [ { "z": 14, "x": 9783, "y": 6592, "url": "/api/v1/traffic/lines/tiles/14/9783/6592" } ]
}
GET /traffic/predicted/tiles/{z}/{x}/{y}
Typical/predicted congestion for one tile (sample-weighted historical averages), as GeoJSON. Identical shape to the live tile, but each feature's properties carries "predicted": true. A companion GET /traffic/predicted/tile-cover works like the live tile-cover and additionally accepts an at ISO timestamp (folded into the returned URLs).
POST /traffic/route
Compute a route and enrich its ETA with live, Navvo-sourced traffic. This is the traffic-aware sibling of POST /routing/route: it routes via the Navvo routing engine, samples congestion along the path, and returns a traffic-adjusted ETA plus the route split into colored segments.
Scopes required: routing and traffic.
Request body
{ "lon": number, "lat": number, "name"?: string }. At least 2 required.auto (default), truck, bicycle, pedestrian, or motor_scooter.arrivalTime. Defaults to now.en-US.[lon, lat] pairs. When provided, congestion is sampled along this exact shape and no route is re-planned — guaranteeing the colored segments match your drawn line (a re-planned route can diverge from a user-chosen alternative). Up to 10,000 points accepted (internally resampled to ≤ 2,000).shape — used as the basis for durationInTrafficSeconds. Only meaningful together with shape; without it the traffic-adjusted ETA fields are 0 and only the colored segments are useful.{
"locations": [ { "lon": 35.91, "lat": 31.95 }, { "lon": 35.95, "lat": 31.99 } ],
"costing": "auto",
"departureTime": "2026-06-09T08:30:00.000Z"
}
With your own displayed geometry (recommended when you render the route yourself):
{
"locations": [ { "lon": 35.91, "lat": 31.95 }, { "lon": 35.95, "lat": 31.99 } ],
"shape": [ [35.91, 31.95], [35.917, 31.958], [35.93, 31.972], [35.95, 31.99] ],
"baseSeconds": 540,
"costing": "auto"
}
Response (201)
{
"provider": "navvo-user-traffic-routing",
"available": true,
"distanceKm": 6.42,
"baseDurationSeconds": 540,
"durationInTrafficSeconds": 637,
"delaySeconds": 97,
"departureTime": "2026-06-09T08:30:00.000Z",
"arrivalTime": "2026-06-09T08:40:37.000Z",
"traffic": {
"hasData": true,
"congestionScore": 0.33,
"level": "slow",
"trafficFactor": 1.18,
"congestedShare": 50
},
"segments": {
"type": "FeatureCollection",
"features": [
{ "type": "Feature", "properties": { "level": "free", "color": "#1A73E8" }, "geometry": { "type": "LineString", "coordinates": [[35.91, 31.95], [35.92, 31.96]] } },
{ "type": "Feature", "properties": { "level": "slow", "color": "#F9A825" }, "geometry": { "type": "LineString", "coordinates": [[35.92, 31.96], [35.95, 31.99]] } }
]
},
"legend": { "free": { "label": "Free", "color": "#1A73E8" }, "slow": { "label": "Slow", "color": "#F9A825" } }
}
| Field | Description |
|---|---|
baseDurationSeconds | ETA from Navvo's routing engine, no traffic. |
durationInTrafficSeconds | Traffic-adjusted ETA (base × trafficFactor). |
delaySeconds | Extra time due to traffic. |
traffic.trafficFactor | Multiplier applied to the base duration. |
segments | The route as a GeoJSON FeatureCollection, colored by congestion — render directly on a map. |
If the routing engine is down, available is false, durations are 0, and segments is empty.
Incidents
Crowdsourced road incidents — jams, closures, accidents, hazards, and more. Scope required: traffic.
type ∈ jam, closure, accident, hazard, weather, breakdown, speed_check, construction, lane_closure, visibility. severity is 1–5. Only active, non-expired incidents are returned.GET /incidents/types
The catalog of supported incident types — for building a "report incident" type picker. Each entry carries a human label, a default severity, the default lifetime (defaultTtlMinutes), and whether the type blocks routing (route-blocking types are routed around; soft types only alert the driver).
curl -s "https://navvo.io/api/v1/incidents/types" -H "x-api-key: $NAVVO_API_KEY"
{
"provider": "navvo-incidents", "count": 10, "confirmBumpMinutes": 25, "maxTtlMinutes": 720,
"types": [
{ "type": "jam", "label": "Traffic jam", "defaultSeverity": 2, "defaultTtlMinutes": 90, "routeBlocking": false },
{ "type": "closure", "label": "Road closure", "defaultSeverity": 4, "defaultTtlMinutes": 240, "routeBlocking": true },
{ "type": "accident", "label": "Accident", "defaultSeverity": 4, "defaultTtlMinutes": 120, "routeBlocking": true }
]
}
The type values are exactly what POST /incidents and POST /incidents/report accept; confirmBumpMinutes/maxTtlMinutes describe how confirmations extend an incident's life.
GET /incidents
List active incidents, severity-then-recency ordered, with layer metadata.
Query parameters
west,south,east,north spatial filter.{
"total": 1,
"items": [
{
"id": "b1f2c3d4-…",
"type": "accident",
"status": "active",
"location": "POINT(35.9106 31.9539)",
"title": "Two-car collision",
"severity": 4,
"expiresAt": "2026-06-09T10:40:00.000Z",
"confirmations": 3,
"rejections": 0
}
],
"metadata": { "layerType": "incidents", "source": "navvo-incidents", "dataUrl": "/api/v1/incidents/geojson", "hasData": true }
}
items[].location is a WKT string; for parsed coordinates use the GeoJSON endpoint below.
GET /incidents/geojson
Active incidents as a GeoJSON FeatureCollection (coordinates [lng, lat]). Accepts the same bbox/type/limit/zoom filters. A GET /incidents/geojson/tiles/{z}/{x}/{y} per-tile variant and a GET /incidents/geojson/tile-cover planner are also available.
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [35.9106, 31.9539] },
"properties": { "id": "b1f2c3d4-…", "type": "accident", "title": "Two-car collision", "severity": 4, "confirmations": 3, "rejections": 0 }
}
],
"metadata": { "layerType": "incidents", "hasData": true }
}
POST /incidents
Report a new incident.
Request body
1–5. Defaults to 2.5–1440. Defaults to 180.{ "type": "hazard", "lat": 31.9539, "lng": 35.9106, "title": "Debris on road", "severity": 3, "ttlMinutes": 120 }
Returns 201 with the created incident (status: "active", expiresAt set from ttlMinutes).
POST /incidents/report
The community-report helper — like POST /incidents but with auto-deduplication. If an active incident of the same type already exists within ~80 m, this is treated as a confirmation (bumps that incident's confirmations and refreshes its expiry) instead of creating a duplicate pin — the right behaviour when many drivers report the same jam or accident. Otherwise a new incident is created.
Same body as POST /incidents, plus an optional dedupMeters (default 80, max 500).
curl -s -X POST "https://navvo.io/api/v1/incidents/report" \
-H "x-api-key: $NAVVO_API_KEY" -H "content-type: application/json" \
-d '{ "type": "jam", "lat": 31.97, "lng": 35.92, "severity": 3, "title": "Heavy traffic" }'
{ "provider": "navvo-incidents", "merged": true, "distanceM": 31, "confirmations": 2, "incident": { } }
| Field | Type | Notes |
|---|---|---|
merged | boolean | true if folded into a nearby same-type incident (a confirmation); false if a new one was created |
distanceM | number | (when merged) distance to the matched incident |
confirmations | number | (when merged) the incident's confirmation count after this report |
incident | object | the resulting incident |
Use this from a "Report" button so repeated reports of one event converge on a single, increasingly-confirmed pin rather than cluttering the map.
POST /incidents/{id}/votes
Confirm or reject an incident (crowd validation). Returns 201 with the updated incident. An incident with 5+ rejections (and rejections > 2× confirmations) is auto-marked rejected and drops out of listings.
Request body
confirm or reject.{ "vote": "confirm" }
Road edits & closures
Road edits are authored on the Navvo platform (operations dashboard) and are the
authoritative, longer-lived counterpart to crowd incidents: road closures, access
restrictions, custom (drawn) roads, and attribute adjustments. Active edits
appear on the map, here in the API, and — for closures/restrictions — are routed
around automatically (see roadEditConstraints in the route
response). Each edit can be permanent or temporary (a start/end window).
Required scope: tiles
GET /road-edits/geojson
Active road edits in a viewport as a GeoJSON FeatureCollection with mixed geometry
(LineString for road segments, Polygon for area closures, Point for point edits).
Only edits effective now are returned (a scheduled edit appears once its start time
passes; an expired or disabled one drops out).
west,south,east,north. Omit for everything (capped).curl -s "https://navvo.io/api/v1/road-edits/geojson?bbox=35.8,31.9,36.0,32.0" \
-H "x-api-key: $NAVVO_API_KEY"
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "LineString", "coordinates": [[35.911, 31.954], [35.912, 31.955]] },
"properties": {
"id": "…", "layerType": "road_edits", "editType": "closure", "geometryType": "line",
"name": "Rainbow St closed", "reason": "construction", "status": "active",
"severity": 4, "blocksRouting": true,
"startsAt": null, "endsAt": "2026-07-01T18:00:00.000Z", "permanent": false,
"color": "#DC2626"
}
}
],
"metadata": { "layerType": "road_edits", "name": "Road edits", "source": "navvo-road-edits", "hasData": true }
}
| Property | Notes |
|---|---|
editType | closure · restriction · custom_road · attribute |
geometryType | line · polygon · point |
blocksRouting | when true, routing detours around this edit |
permanent / startsAt / endsAt | validity window (permanent: true ⇒ no end) |
color | suggested render colour for the edit type |
custom_road edits are map annotations — they are drawn on the map but are not
routable (the routing engine drives a prebuilt graph; a new drivable road needs a graph
rebuild). Closures, restrictions, and adjustments take effect immediately.