“Crash on I-80, right lane blocked.”
That sentence describes two completely different events. In one, it’s a dry afternoon, the lane clears in twenty minutes, and the right call is to hold the load and wait. In the other, the pavement is iced, visibility is down to a quarter mile, and the wind is gusting across an exposed grade — in which case the crash you can see is the least interesting fact on the screen, because the conditions that produced it are still there, and they are about to produce another one three miles up.
Every incident feed on the market gives you the first sentence. Almost none of them tell you which of the two events it actually is. Dispatch doesn’t respond to incidents. Dispatch responds to incidents in context — and the context has to arrive attached to the incident, at the moment it appears, or it arrives too late to change the decision.
The Context Already Exists, Sitting in a Different Feed
State DOTs have spent decades installing roadside weather stations — RWIS, in the trade — the instrumented poles that report air temperature, wind, visibility, humidity, precipitation type, and, critically, what the road surface itself is doing — dry, wet, icy, snow-covered. Each agency says that in its own words rather than a shared vocabulary, which turns out to matter a great deal and which we come back to in detail below.
Road511 currently carries 3,877 active roadside weather stations across 36 states and provinces, alongside 8,119 active road-condition segments across 20 — the latter being the DOT’s own segment-level assessment of a stretch of road, as opposed to a single station’s point reading. (Counts measured 14 August 2026, active records only. Stations come and go as agencies retire hardware, so treat these as this month’s figure rather than a constant.)
The data is public, official, and already flowing. The problem is that it lives in a different layer from the incidents, on a different schema, keyed to different geometry. So the dispatcher gets an incident in one panel and a weather map in another, and does the spatial join in their head, under time pressure, at 3am. That join is the product.
Every Event Carries Its Own Weather
When a new incident lands in Road511 — a crash, a closure, a work zone — we immediately look for the nearest active weather station within 50 km and write down what it was reporting at that moment. That reading is stapled to the event, permanently. Here is an actual record, pulled from the production database as this post was last revised — a Delaware incident from the afternoon of 14 August 2026, verbatim:
GET /api/v1/analytics/event-weather/DE-waze-bf8241b1-82be-49c4-9faa-f1e9e322a53a
{
"event_id": "DE-waze-bf8241b1-82be-49c4-9faa-f1e9e322a53a",
"distance_km": 2.52,
"temperature": 82,
"temperature_c": 27.8,
"wind_speed": 2.9,
"wind_direction": "NE",
"visibility": 12.43,
"precipitation": "No Precipitation",
"road_surface": "Dry",
"humidity": 49,
"reading_recorded_at": "2026-08-14T13:53:38Z",
"created_at": "2026-08-14T13:56:39Z"
}
Read that as a dispatcher rather than as a developer. Dry pavement, no precipitation, a visibility of 12.43 — miles, on this feed — almost no wind, from a station a mile and a half away, recorded three minutes before the incident was written. That is a hold the load and wait incident, and you knew it without reading the description. Flip three of those fields — a road surface the agency has flagged for ice, visibility under a mile, a crosswind on an exposed grade — and the same incident text supports the opposite decision: reroute the following three loads now, don’t just delay them. The value here is not that the conditions are dramatic. It is that they are present, on the incident, at the moment it appears, in one call.
The distance_km field is doing real work there, and it’s the reason we return it. A station 2.5 km from the incident is describing the incident. A station 46 km away is describing a different valley, and you should discount it accordingly. Across the whole archive the average snapshot sits about 16 km out, so this is a filter you will actually use. We don’t hide that number behind a confidence score we made up — we give you the distance and let you decide what it’s worth.
What those field values actually look like
Notice that precipitation reads "No Precipitation" and road_surface reads "Dry" — capitalised, spelled out, in the reporting agency’s own words. These are not normalized enums, and you must not code against them as though they were. Across the archive the same two columns hold None, none, No Precipitation, not available, Unknown, light rain, rain moderate and 0 mm for precipitation; Dry, dry, Wet, Trace Moisture, Trace Wet, Moist, wet and dry, Ice Watch, Ice Warning, Snow Warning and Slushy for road surface. A handful of feeds leak raw sensor codes into the field — you will find literal 4.0 and 65535 values in there.
Two consequences worth internalising before you build on this. First, match case-insensitively and on substrings, and treat anything you don’t recognise as unknown rather than as safe. Second, and less obvious: some agencies publish their ice-detection subsystem’s alarm state in this field rather than an observation, which is why Ice Watch turns up on a Virginia road at 30 °C in August. Ice Watch means a sensor is armed, not that there is ice. If you are going to escalate on a surface value, escalate on it together with the temperature, never on the string alone. We pass the agency’s word through rather than mapping it to a tidy enum, because the mapping would have to guess at exactly the cases where guessing is most expensive — but that means the interpretation is genuinely yours to do.
From Anecdote to a Number You Can Argue With
“Bad weather causes accidents” is a thing everyone knows and nobody can put a figure on. Once every event carries a snapshot, the figure becomes a query. Group the incident history by what the road was doing and what was falling out of the sky:
GET /api/v1/analytics/weather-correlation?jurisdiction=KY
[
{ "precipitation": "None", "road_surface": "",
"event_count": 93392, "avg_severity": 2.03, "avg_temp_c": 21.8 },
{ "precipitation": "Rain", "road_surface": "",
"event_count": 4592, "avg_severity": 2.07, "avg_temp_c": 19.3 },
{ "precipitation": "None", "road_surface": "Dry",
"event_count": 2015, "avg_severity": 2.03, "avg_temp_c": 26.4 },
{ "precipitation": "None", "road_surface": "Wet",
"event_count": 54, "avg_severity": 2.06, "avg_temp_c": 21.0 },
{ "precipitation": "Rain", "road_surface": "Wet",
"event_count": 35, "avg_severity": 2.06, "avg_temp_c": 21.0 }
]
That is the real response for Kentucky on 14 August 2026, abridged to the top rows, and it is worth showing you exactly because it is not the tidy result a marketing example would invent. Three things in it are the honest state of this endpoint today, and you should know all three before you build on it.
The severity spread is currently flat. 2.03 on dry, 2.06 on wet, 2.07 in rain — that is noise, not a finding. (avg_severity is a weighted score: critical counts 4, major 3, moderate 2, everything else 1.) We are not going to tell you we have measured that ice doubles incident severity, because in this archive, so far, we have not. What we have built is the instrument; the reading it currently gives on most lanes is “no strong effect yet.”
The archive is young. Weather snapshots begin on 10 April 2026. There is no winter in this data at all yet, which is the single biggest reason the ice story above cannot be told from it — the interesting conditions have not happened during the archive’s lifetime. A date range starting before April 2026 returns an empty array, so don’t write one and conclude the endpoint is broken. The first real winter of this dataset is the 2026–27 one.
Most rows have an empty road_surface. Of roughly 2.1 million snapshots, about 322,000 carry a road-surface string and about 330,000 a precipitation string; only around 26,000 — about 1% — carry surface, precipitation, wind and visibility all four. Most stations report a subset, and the grouping key you most want is the one most often absent. That empty-string row at the top of the response is not a bug; it is 93,392 events whose nearest station published a temperature and nothing about the pavement.
Filter by jurisdiction, by event type, by severity, or by date range, and you can put the question your own lanes actually pose to the data — which corridors punish ice, which ones shrug it off. Just budget for the answer being “not enough observations yet” on a lot of them, and check event_count before you believe an avg_severity. We would rather hand you a thin dataset labelled thin than a thick one we smoothed.
On the Route
Weather stations also ride the corridor. Send a route to POST /routing/route and the stations near the line come back in warnings[] as type: "weather", each carrying its readings and the time the truck is projected to reach it — the same channel that already carries bridge clearances and corridor hazards.
Be clear about what that is and isn’t. Those weather markers are surfaced at info severity, as observations. Road511 does not currently threshold them — there is no rule that escalates “road_surface: ice” to a warning, no wind-speed limit that trips a flag for a high-profile trailer. The reading is handed to you; the policy is yours, because the policy is genuinely yours: the wind speed that stops a loaded reefer is not the one that stops a flatbed, and we’d rather give you the number than guess your fleet’s tolerance. When you write that policy, apply the two cautions above — the surface strings are the agency’s vocabulary rather than an enum, and wind and visibility carry no unit — because a threshold is exactly where an unnormalized field does its damage.
And the segment-level road_conditions layer — the DOT’s own “this stretch is snow-covered” assessment — is not enriched onto routes today. It’s queryable as a layer over any bounding box or corridor you define, but it does not currently arrive attached to a route response. If route-level surface state is what you need, that’s a gap, and we’d rather tell you now than have you discover it in integration.
What You Can Build With It
- Triage that reads the conditions, not just the headline — auto-escalate an incident whose snapshot shows a freezing temperature and an icy surface string, before a human has read the description. (Both halves: the surface string alone will fire on a summer sensor alarm.)
- Winter corridor scorecards — rank your lanes by the severity they produce under the same conditions. The endpoint for this exists today; the archive to fill it starts accumulating its first winter in November 2026.
- Post-incident review that isn’t guesswork — when a load is late or a claim is filed, the conditions at the event are already recorded, timestamped, and attributable to a named agency’s station.
- Driver-facing condition alerts — surface the observations along the route with your own thresholds applied, tuned to the trailer.
- Weather beside everything else on the corridor — conditions alongside work zones, planned construction, and closures in one schema.
Provenance, and the Honest Limits
These readings come from state DOT roadside stations — official instruments, not a modelled forecast and not crowd-sourced. That’s the strength, and it dictates the limits, which are worth stating plainly.
The snapshot is taken once, at the moment the event is created, and never refreshed. It answers “what were the conditions when this appeared,” which is the question that matters for triage and for later analysis. It does not track how the weather evolved over the life of a six-hour closure. For current conditions, query the station directly — /analytics/weather returns its reading time-series.
If no active station sits within 50 km, the event gets no snapshot at all. We do not reach further and pretend a reading from the next county describes this stretch of road. On a rural corridor, expect gaps; a missing snapshot is an honest absence, not a zero.
Readings pass through in the units the reporting agency publishes. Most US stations report Fahrenheit, miles, and miles per hour — but not all of them: British Columbia and, of all places, California publish Celsius. So temperature is the agency’s own number, and temperature_c sits beside it, normalized, for when you need to compare or average across jurisdictions. Where we haven’t established a feed’s unit, temperature_c is simply absent rather than guessed — roughly a quarter of snapshots carry it — and the correlation endpoint leaves those readings out of its average instead of blending them in.
Temperature is the only field we normalize. Wind and visibility are not. This matters more than it sounds: in the same visibility column you will find 12.43 from a Delaware station reporting miles and 621 from a Virginia one that plainly is not. There is no unit field to tell them apart. Compare visibility and wind within a single jurisdiction and never across them, and put a sanity bound on the value before you feed it to anything that makes a decision. If you need one cross-jurisdiction number, temperature_c is the one field that is safe to average.
This is observation, not prediction. There is no weather forecasting here, and we’re not going to bolt a forecast model onto a road-data API and call it dispatch intelligence. What we do is guarantee that when an incident exists, whatever the nearest station measured exists next to it, in one schema, from 3,877 stations we keep parsed and current as their feeds drift — so that job isn’t yours.
Weather snapshots, the correlation endpoint, and the reading time-series are analytics-tier features (Pro and above). The underlying weather_stations and road_conditions layers are available on every plan, free trial included.
Try It
- API docs — the analytics surface, plus the
weather_stationsandroad_conditionsfeature types - Live map — see the station network and current road conditions
- Free API key — no credit card, 14-day trial
The incident, and the conditions that made it
3,877 roadside weather stations across 36 states and provinces, in one schema — with the nearest station’s reading attached to every incident the moment it appears, the distance to that station returned so you can judge it, and the severity-by-conditions endpoint to query it over time. Free 14-day trial. No credit card.
Get Free API Key Read the Docs