⚡ Real-time nowcast
The current segment always carries live radar-derived lightning, thunderstorm, and precipitation data — not model estimates.
🔭 Forecast ahead
Upcoming segments are enriched with hourly NWP forecast weather so drivers can plan for conditions hours away.
🗺️ Smart segmentation
The route is split into Uber H3 hexagonal cells. Each cell gets its own ETA and independent weather query, keeping data fresh and spatially accurate.
What is the Enroute API?
The Enroute API turns a planned route into a live weather-monitoring session. You provide the route geometry, departure time, and duration — the API splits the path into geographic segments, attaches scheduled arrival times to each one, and returns weather data for every segment on every subsequent poll. Two endpoints drive the entire lifecycle:| Endpoint | Purpose |
|---|---|
POST /v1/enroute/register | Create a route session. Returns a routeId and the initial weather picture. |
POST /v1/enroute/weather | Poll an active session with the driver’s current location. Returns updated weather, position status, and any schedule changes. |
All timestamps in requests and responses are epoch milliseconds (64-bit integers). Never send ISO strings or fractional seconds.
How segmentation works
When you register a route, the service decodes the route geometry (encoded polyline or coordinate list) and maps every point to an Uber H3 hexagonal cell at resolution 5. Consecutive points falling in the same cell are merged, yielding an ordered list of unique cells — the segments. Each segment receives:eta— scheduled arrival time, interpolated fromdepartureTime + (distanceToEntry / totalDistance) × durationSecondsetd— scheduled departure time (same interpolation usingdistanceToExit)distanceToEntry/distanceToExit— cumulative metres from route startarrivalPoint/departurePoint— the geographic coordinates where the route enters and exits the cellh3Address— the H3 cell identifier (used for weather queries)
Nowcast vs Forecast
The response contains two structurally different weather payloads depending on the segment’s time horizon.currentSegment — Nowcast + Forecast
The segment the driver is currently in (or the first segment, at registration time) receives nowcast data: real-time observations derived from live radar and sensor networks. This is the richest, most accurate weather picture available.
Nowcast includes three dedicated summary objects:
| Object | Source | What it tells you |
|---|---|---|
lightningSummary | Lightning detection sensors | Flash counts, peak current, risk index, approach trend |
thunderstormSummary | Radar storm tracking cells | Active storm list, threat boundary proximity, bearing, severity |
precipitationSummary | Radar reflectivity | Current intensity, trend, expected start/end, forecast max |
- Lightning: Sensor networks record only events that have already occurred. They produce no forward-looking output whatsoever. A lightning nowcast for a cell the driver will reach two hours from now is physically impossible.
- Thunderstorm: Radar-based cell tracking observes the current position, speed, and direction of active storm cells. It generates no forecast projection; a meaningful threat assessment for a segment hours ahead cannot be derived from it.
- Precipitation: Alongside live radar observations, a very short-range NWP projection may also be available; this is what feeds the
expectedStartSec/expectedEndSecfields inprecipitationSummary. However, this horizon only extends slightly beyond the current observation window and does not represent conditions for a segment hours ahead.
upcomingSegments — Forecast only
All segments after the current one carry NWP (Numerical Weather Prediction) hourly forecast data: temperature, apparent temperature, humidity, cloud cover, wind speed/gust/direction, precipitation, precipitation probability, snowfall, and visibility.
At registration time, if
departureTime is within 60 minutes of now, the current segment also fetches nowcast data. If the departure is further in the future, only forecast data is returned for the first segment as well.Registering a route
Request
| Field | Type | Required | Description |
|---|---|---|---|
origin | GeoPoint | ✅ | Starting coordinate { lat, lng } |
destination | GeoPoint | ✅ | Ending coordinate { lat, lng } |
departureTime | number | ✅ | Epoch milliseconds of planned departure |
distanceMeters | number | ✅ | Total route length in metres |
durationSeconds | number | ✅ | Estimated travel duration in seconds |
geometry.encodedPolyline | string | ✅ (or coordinates) | Google-encoded polyline string |
geometry.polylinePrecision | number | — | Precision factor (5 = standard, 6 = high-precision) |
geometry.coordinates | GeoPoint[] | ✅ (or polyline) | Explicit coordinate list instead of polyline |
waypoints | GeoPoint[] | — | Optional intermediate waypoints (informational) |
Response
Polling route weather
Request
| Field | Type | Required | Description |
|---|---|---|---|
routeId | UUID string | ✅ | Session identifier from /register |
currentLocation | GeoPoint | ✅ | Driver’s current GPS coordinate |
Response
GetRouteWeatherResponse extends RouteRegistrationResponse and adds:
| Field | Type | Description |
|---|---|---|
segmentsRecalculated | boolean | true if segments were recalculated due to an off-schedule event |
warning | string | Human-readable message explaining why recalculation occurred |
routeId, expirationTime, distanceUnit, status, currentSegment, upcomingSegments) are identical in structure to the registration response.
Response field reference
LocationStatus
| Field | Type | Description |
|---|---|---|
progressPercentage | number | Journey completion percentage (0–100) |
distanceTraveled | number | Metres traveled from route start |
remainingDistance | number | Metres remaining to destination |
timeElapsedSeconds | number | Seconds since departureTime |
estimatedTimeRemainingSeconds | number | Remaining travel time based on current pace |
scheduleDeviationSeconds | number | Positive = ahead of schedule; negative = behind schedule |
expectedSegmentIndex | number | The segment index the driver should currently be in per the original schedule |
estimatedArrivalTime | number | Estimated epoch-millisecond arrival time, capped at expirationTime |
expectedSegmentIndex reflects the route schedule, not GPS position. If the driver is in segment 2 but the schedule expected them to be in segment 3, this field shows 3. Compare it with currentSegment.index to detect schedule drift.BaseRouteSegment (shared by currentSegment and upcomingSegments)
| Field | Type | Description |
|---|---|---|
index | number | Zero-based segment position in the route |
h3Address | string | Uber H3 cell identifier at resolution 5 |
eta | number | Scheduled arrival epoch-milliseconds |
etd | number | Scheduled departure epoch-milliseconds |
distanceToEntry | number | Cumulative metres from route start to cell entry |
distanceToExit | number | Cumulative metres from route start to cell exit |
arrivalPoint | GeoPoint | Coordinate where the route enters the cell |
departurePoint | GeoPoint | Coordinate where the route exits the cell |
ForecastWeatherEvents (all segments)
| Field | Type | Unit | Description |
|---|---|---|---|
temperature | number | °C | Air temperature at 2 m |
apparentTemperature | number | °C | Feels-like temperature |
humidity | number | % | Relative humidity |
cloudCover | number | % | Sky cloud fraction |
windSpeed | number | km/h | Wind speed at 10 m |
windGust | number | km/h | Maximum wind gust |
windDirection | number | ° | Meteorological wind direction (0 = N, 90 = E) |
snowFall | number | cm | Snowfall accumulation |
precipitation | number | mm | Precipitation accumulation |
precipitationProbability | number | % | Model precipitation probability |
visibility | number | m | Horizontal visibility |
Nowcast summary fields
ThecurrentSegment.weatherEvents object contains three additional summary objects when nowcast data is available.
LightningSummary
Real-time lightning activity derived from ground-based electromagnetic sensors.
| Field | Type | Description |
|---|---|---|
windowMinutes | number | Total observation window (e.g. 60 min) |
bucketMinutes | number | Slot resolution used for aggregation (e.g. 30 min) |
totalEventCount | number | All strike events within the window (in-cloud lightning + cloud-to-ground strikes) |
cgFlashCount | number | Flash count — the most dangerous type for exposed workers and drivers |
icPulseCount | number | Pulse count — indicator of storm electrification intensity |
lastEventAgeSec | number | Seconds since the most recent event of any type |
lastFlashAgeSec | number | Seconds since the most recent flash |
lastPulseAgeSec | number | Seconds since the most recent pulse |
nearestEventDistance | number | Metres to the closest event of any type |
nearestFlashDistance | number | Metres to the closest flash |
nearestPulseDistance | number | Metres to the closest pulse |
maxPeakCurrent | number | Maximum peak current (kA) in the window — higher values indicate more destructive flashes |
avgPeakCurrent | number | Average peak current (kA) |
avgSensorCount | number | Average number of sensors that detected each event — higher = more accurate location |
confidenceScore | number | 0–1 confidence score of detection quality |
confidenceLevel | enum | LOW / MEDIUM / HIGH |
riskIndex | number | Composite risk score (0–100) |
riskLevel | enum | NONE / LOW / MEDIUM / HIGH / EXTREME |
trend | enum | UNKNOWN / DECREASING / STABLE / INCREASING |
riskLevel colour. If riskLevel is HIGH or EXTREME, surface an urgent alert. Use nearestFlashDistance and lastFlashAgeSec to give context: “A flash was detected 3.2 km away 45 seconds ago — stay in your vehicle.”
ThunderstormSummary
Storm cell tracking derived from multi-layer radar analysis.
summary object
| Field | Type | Description |
|---|---|---|
stormCount | number | Total tracked storm cells in the observation window |
activeStorms | number | Cells currently producing lightning or heavy precipitation |
insideAnyThreatBoundary | boolean | true if the driver’s current H3 cell overlaps any storm’s threat polygon |
nearestThreatBoundaryDistance | number | Metres to the closest storm threat boundary |
nearestStormCentroidDistance | number | Metres to the closest storm cell centre |
maxSeverity | enum | LOW / NORMAL / HIGH / UNKNOWN — highest severity among all tracked storms |
lastEventAge | number | Seconds since the most recent storm event |
riskScore | number | Composite risk score (0–100) |
riskLevel | enum | NONE / LOW / MEDIUM / HIGH / EXTREME / UNKNOWN |
trend | enum | RISING / STABLE / FALLING / UNKNOWN |
activeStorms[] — per-storm detail
| Field | Type | Description |
|---|---|---|
eventId | string | Unique identifier of the tracked storm cell |
severity | enum | LOW / NORMAL / HIGH / UNKNOWN |
eventStartUtcEpoch | number | Epoch-milliseconds when this storm cell was first detected |
eventEndUtcEpoch | number | Epoch-milliseconds of last recorded activity |
eventAge | number | Seconds since the storm cell was first detected |
cell.area | number | Storm cell area (km²) |
cell.speed | number | Storm movement speed (km/h) |
cell.direction | number | Storm movement direction (degrees, meteorological) |
cell.centroidDistance | number | Metres from driver to storm cell centre |
cell.directionFromDriver | enum | Compass bearing: N, NNE, NE, ENE, E, ESE, SE, SSE, S, SSW, SW, WSW, W, WNW, NW, NNW |
cell.bearingFromDriver | number | Exact bearing in degrees from driver to storm centroid |
flashRates.inCloud | number | Pulse rate (count/min) |
flashRates.cloudToGround | number | Flash rate (count/min) |
flashRates.total | number | Total strike rate (count/min) |
flashRates.cloudToGroundRatio | number | Flash ratio (0–1); higher = more ground strikes |
threat.insideThreatPolygon | boolean | true if driver is inside this storm’s threat polygon |
threat.distanceToThreatBoundary | number | Metres to this storm’s threat polygon boundary |
threat.directionFromDriver | enum | Compass direction to threat boundary |
threat.bearingFromDriver | number | Exact bearing to threat boundary |
threat.approachState | enum | APPROACHING / MOVING_AWAY / STABLE / UNKNOWN |
score.stormRiskScore | number | Per-storm risk score (0–100) |
score.stormRiskLevel | enum | NONE / LOW / MEDIUM / HIGH / EXTREME / UNKNOWN |
insideAnyThreatBoundary is true, this is an immediate safety alert — the driver is inside a storm’s forecast impact zone. The approachState: APPROACHING flag combined with nearestThreatBoundaryDistance helps drivers decide whether to pull over or continue. Show the per-storm bearing so drivers understand which direction the storm is coming from.
PrecipitationSummary
Radar-derived precipitation analysis for the current H3 cell.
| Field | Type | Description |
|---|---|---|
windowMinutes | number | Observation window in minutes |
bucketMinutes | number | Aggregation slot in minutes |
currentIntensity | enum | Current intensity: DRIZZLE / LIGHT / MODERATE / HEAVY / VERY_HEAVY / EXTREME, or null if not precipitating |
isPrecipitating | boolean | true if precipitation is currently detected over the cell |
radarTimeStamp | number | Epoch-milliseconds of the radar scan used |
dataAgeSec | number | Age of radar data in seconds — below 600 s is considered fresh |
radarSnapshotCount | number | Number of radar scans included in the window |
maxIntensity | enum | Maximum intensity recorded in the window |
trend | enum | INCREASING / STABLE / DECREASING / UNKNOWN |
riskLevel | enum | NONE / LOW / MEDIUM / HIGH / EXTREME |
forecastMaxIntensity | enum | NWP model’s predicted maximum intensity for the near future |
expectedEndSec | number | Seconds until precipitation is expected to stop (if currently precipitating) |
expectedStartSec | number | Seconds until precipitation is expected to start (if currently dry) |
currentIntensity as a weather badge. Use expectedStartSec to give advance warning — “Heavy rain expected in 8 minutes” — so drivers can prepare (wipers, speed reduction). HEAVY or above warrants a proactive push notification.
Off-route and off-schedule
Off-route
The/weather endpoint checks whether the driver’s currentLocation is within 1,000 metres of any segment of the registered route (perpendicular distance).
If the driver has deviated beyond this threshold:
- The route session is immediately deleted from cache.
- A 400 Bad Request is returned with
error: "Off Route". - The
routeIdis no longer valid. - The client must call
/registeragain with a new route.
error: "Off Route". Show the user a dialog: “You have left the route. Please start navigation on your new route to continue weather monitoring.” Do not retry /weather with the same routeId.
Off-schedule
If the driver’s GPS position is significantly behind the expected schedule — specifically, ifnow is more than 10 minutes past the scheduled ETA of the segment after the driver’s current segment — the service silently recalculates the remaining route segments from the driver’s current position.
When recalculation occurs:
segmentsRecalculated: trueis set in the response.warningcontains a human-readable explanation.- Segment indices, ETAs, and distances are reset from the driver’s current position.
currentSegmentreflects the new segment 0 starting from where the driver is now.- The
expirationTimeis extended to new ETA + 2 hours.
Error reference
| HTTP Status | error | Trigger |
|---|---|---|
| 400 | Off Route | Driver is more than 1,000 m from the route. Session deleted. |
| 400 | Invalid Route | routeId not found, session expired, or route geometry invalid. |
| 409 | Duplicate Route | A session for the same origin → destination pair is already active. Use the existing routeId. |
| 402 | Payment Required | Subscription expired or exhausted. |
| 403 | Forbidden | No subscription for this endpoint, or queried location outside subscription boundaries. |
| 429 | Too Many Requests | Subscription rate limit exceeded. |
| 500 | Data Provider Error | A weather data provider was unreachable. Response includes source (Nowcast / Forecast) and service (Lightning, Thunderstorm, Precipitation, Current Forecast, Hourly Forecast) context. |
Duplicate Route (409)
Expired or Not Found (400)
Data Provider Error (500)
Returned when any of the underlying weather data services (lightning, thunderstorm, precipitation, or forecast) is unreachable. Themessage field identifies which source and service failed so you can log it and present a user-friendly fallback.
- Nowcast failure
- Forecast failure
Developer notes
All timestamps are epoch milliseconds
All timestamps are epoch milliseconds
Every
Instant-typed field in the API serializes as a 64-bit integer epoch millisecond — routeId, expirationTime, eta, etd, estimatedArrivalTime. Never parse these as seconds. Multiply by 1 and interpret directly as Date(value) in JavaScript or Instant.ofEpochMilli(value) in Java.One active session per origin–destination pair
One active session per origin–destination pair
The API enforces deduplication on
(userId, originH3, destinationH3). If the driver tries to register the same route while an active session exists, a 409 Conflict is returned with the existing routeId and expirationTime in the messages array. Parse the messages array to extract the existing routeId and resume polling rather than treating the 409 as a fatal error.Session expiration
Session expiration
Sessions expire at ETA + 2 hours. After expiration, calls to
/weather with the old routeId return 400. Poll /weather before expirationTime to detect expiry proactively without waiting for an error.Polling frequency
Polling frequency
There is no server-side push; all updates require a client-initiated
/weather poll. Recommended polling interval: every 30–60 seconds while the vehicle is moving. Reduce to every 5 minutes when stationary (e.g. at a traffic stop).Handling segmentsRecalculated
Handling segmentsRecalculated
When
segmentsRecalculated: true, the segment list has been rebuilt from the driver’s current position. Segment index values restart from 0. Any UI element that cached previous segment indices (progress bars, segment list scrolling) must be re-initialized using the new response.distanceUnit is always metres
distanceUnit is always metres
The
distanceUnit field in the response is always "m". All distanceToEntry, distanceToExit, and remainingDistance values are in metres. Convert to km or miles in your UI layer.Testing with Postman
The Postman visualization script below renders a human-readable route summary directly in the Visualize tab after each/register or /weather request — no need to read raw JSON to understand the current route state.
How to use:
- Open the request in Postman (
POST /v1/enroute/registerorPOST /v1/enroute/weather). - Go to Scripts → Post-response and paste the script below.
- Send the request, then switch to the Visualize tab to see the summary.