Skip to content

Drive-Time Routing API

PlaidCloud exposes drive-time routing as two REST endpoints under /rest/v1/analyze/route: an isochrone endpoint that draws a drive-time (or drive-distance) polygon around an origin, and a find-nearest endpoint that ranks candidate destinations by actual drive time rather than straight-line distance. Both run on PlaidCloud’s self-hosted routing engine, built from OpenStreetMap road data (ODbL), and wrap every result in a small plaidcloud envelope carrying attribution.

Every routing call needs:

  • A normal PlaidCloud session or bearer token carrying the analyze.table.read role — the same role that gates other read access to a project’s data. There is no routing-specific role.
  • Drive-time routing included in your plan — the drive-time entitlement enabled for your tenant. A tenant whose plan doesn’t include it gets a 403 with detail: "drive_time_disabled" on every call — there is no partial or read-only mode.

isochrone — Drive-Time Polygon Around an Origin

Section titled “isochrone — Drive-Time Polygon Around an Origin”
POST /rest/v1/analyze/route/isochrone
Field Type Notes
origin { lat, lon }, required A single coordinate. Isochrone takes one origin per call
costing string auto (default), truck, bike, or pedestrian
contours_minutes array of integers, required One entry per contour ring you want, each 1–120 minutes. Up to 5 contours per call
costing_options.truck.height float, meters Optional, > 0 and ≤ 10. Only applies under truck costing
costing_options.truck.weight float, kilograms Optional, > 0 and ≤ 100000. Only applies under truck costing
costing_options.truck.length float, meters Optional, > 0 and ≤ 50. Only applies under truck costing
{
"origin": { "lon": -122.4194, "lat": 37.7749 },
"costing": "auto",
"contours_minutes": [10, 20, 30]
}

Response — the routing engine’s own isochrone GeoJSON, unmodified, plus the plaidcloud envelope:

{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"properties": { "contour": 10, "metric": "time" },
"geometry": { "type": "Polygon", "coordinates": [[[-122.44, 37.79], [-122.40, 37.79], [-122.40, 37.76], [-122.44, 37.76], [-122.44, 37.79]]] }
},
{
"type": "Feature",
"properties": { "contour": 20, "metric": "time" },
"geometry": { "type": "Polygon", "coordinates": [[[-122.47, 37.81], [-122.37, 37.81], [-122.37, 37.74], [-122.47, 37.74], [-122.47, 37.81]]] }
}
],
"plaidcloud": {
"attribution": "Routing data © OpenStreetMap contributors, licensed under ODbL (https://www.openstreetmap.org/copyright)."
}
}

find-nearest — Nearest Destinations by Drive Time

Section titled “find-nearest — Nearest Destinations by Drive Time”
POST /rest/v1/analyze/route/find-nearest
Field Type Notes
origins array of { lat, lon }, required 1–5 origins
destinations array of { lat, lon }, required 1–500 candidates. See destination prefiltering below
costing string auto (default), truck, bike, or pedestrian
top_n integer Nearest destinations to return per origin. 1–50, default 5
costing_options.truck.{height,weight,length} same as isochrone Only applies under truck costing
{
"origins": [{ "lon": -122.4194, "lat": 37.7749 }],
"destinations": [
{ "lon": -122.4310, "lat": 37.7660 },
{ "lon": -122.4010, "lat": 37.7890 },
{ "lon": -122.4200, "lat": 37.7700 }
],
"costing": "auto",
"top_n": 2
}
{
"results": [
{
"origin_index": 0,
"nearest": [
{ "destination_index": 2, "destination": { "lon": -122.4200, "lat": 37.7700 }, "time_seconds": 184, "distance_km": 1.2 },
{ "destination_index": 0, "destination": { "lon": -122.4310, "lat": 37.7660 }, "time_seconds": 412, "distance_km": 2.8 }
]
}
],
"plaidcloud": {
"attribution": "Routing data © OpenStreetMap contributors, licensed under ODbL (https://www.openstreetmap.org/copyright)."
}
}

destination_index refers to the position of that destination in the destinations array you submitted, not its position in any internal ranking — hold onto it to map a result back to your own data.

You can submit up to 500 destinations, but only the 50 nearest by straight-line distance to any of your origins are ever sent into the actual drive-time routing calculation. If you submit more than 50, PlaidCloud narrows the field with a straight-line (great-circle) prefilter before ranking the survivors by real drive time — so a destination that’s close on the map but on the far side of a straight-line cutoff can be excluded before drive time is ever computed. For destination sets already under 50, every candidate is routed and this has no effect. top_n is capped at 50 for the same reason: it can’t return more candidates than the routing step ever considers.

auto, truck, bike, and pedestrian are supported. Under truck costing you can also constrain the route by vehicle dimensions — costing_options.truck.height, .weight, .length — so a route can avoid a low bridge or a weight-restricted road. Hazmat routing is not supported. There is no hazmat parameter on either endpoint, and none is available even indirectly through truck costing — this API does not route around hazardous-materials restrictions, so don’t rely on it for hazmat-regulated freight.

Status Meaning
403 Missing the analyze.table.read role, or your plan doesn’t include the drive-time entitlement
422 A request field failed validation — for example more than 5 contours, a contour outside 1–120 minutes, more than 5 origins, or a truck dimension out of range
503 route_unavailable The routing engine could not be reached, timed out, or returned an error — or your tenant’s concurrent-request allowance was already in use (see Limits)

A 503 here is never a raw 5xx and never an unbounded hang — every call to the routing engine runs under a bounded timeout, so a slow or hung upstream surfaces quickly as 503 rather than leaving your request open.

  • Per-tenant concurrency is capped at 2 simultaneous requests. This reflects the shared routing pool behind the preview, not a per-plan quota — a third concurrent request from the same tenant gets 503 route_unavailable until one of the first two finishes. There’s no queueing; retry after a short backoff.
  • No response caching. Every call is answered live against the current routing index.
  • Coordinates are never logged. Failure logs record the request path and error type, not the origin, destination, or any other location data you submitted.
  • Routing data is built from OpenStreetMap road data (ODbL) — the same coverage and freshness caveats that apply to PlaidCloud’s geocoding API apply here: strong in well-mapped regions, more variable elsewhere, and continuously community-edited rather than a versioned commercial dataset.
  • If you display routing results or drive-time areas to an end user, display the plaidcloud.attribution string (or equivalent OSM credit) alongside them — the same ODbL obligation that applies to geocoding results applies to routing results.