Skip to content

Routing debug (expansion)

When a route takes a strange detour, the question is usually “what did the router consider?” POST /api/v1/expansion answers it. It runs the search and returns every road edge it settled, as GeoJSON LineStrings you can drop on a map. Edges on the chosen path have on_path: true.

This is a debug tool. Responses can be large, so access is restricted:

  • Send the header X-Plaza-Debug: true, or use an API key with the admin scope. Without either you get 403 debug_access_required, and the request isn’t billed.
  • Expansion has its own limit of 10 requests per minute on every plan, on top of your plan’s rate limit.
  • Each request counts as one premium request (4x).
Terminal window
curl -X POST https://plaza.fyi/api/v1/expansion \
-H "x-api-key: pk_live_YOUR_KEY" \
-H "X-Plaza-Debug: true" \
-H "Content-Type: application/json" \
-d '{
"action": "route",
"origin": { "type": "Point", "coordinates": [2.294, 48.858] },
"destination": { "type": "Point", "coordinates": [2.350, 48.870] },
"mode": "auto",
"expansion_properties": ["duration", "distance", "cumulative_cost"]
}'
{
"type": "FeatureCollection",
"properties": {
"action": "route",
"algorithm": "dijkstra",
"mode": "auto",
"edge_count": 1247,
"total_edges": 1247,
"truncated": false
},
"features": [
{
"type": "Feature",
"geometry": { "type": "LineString", "coordinates": [[2.2941, 48.8581], [2.2952, 48.8586]] },
"properties": { "duration": 2.3, "distance": 45.0, "cumulative_cost": 2.3, "on_path": true }
}
]
}

Path edges come first. The rest follow in the order the router settled them, by cumulative_cost. If you color edges by cumulative_cost, you can watch the search spread out from the origin.

action picks the search. The other fields are that endpoint’s own:

actionFieldsWhat you get
routeorigin, destination, mode, excludeEverything Dijkstra settled before reaching the destination
isochronegeometry (center), time (seconds: a number, an array or a comma-separated string, at most 10 distinct values, each 1 to 7200), mode, excludeEvery edge within the largest time budget. on_path is always false
matrixorigins, destinations, mode, excludeEach origin’s search up to its farthest destination. At most 100 pairs (origins x destinations); more is a 400

mode is any of auto, foot, bicycle, truck, motorcycle and motor_scooter, with that mode’s options object, so you can see where a truck or scooter search goes. Every action takes datasets too, so the search runs over your own roads as well; their edges have osm_way_id: null.

expansion_properties picks what each edge carries. on_path is always included. The default is ["duration"].

PropertyMeaning
durationSeconds to drive the edge in the search direction
distanceEdge length in meters
costThe edge’s search cost. Plaza’s router minimises time, so this equals duration
cumulative_costCost from the origin to the far end of the edge
edge_idRouting edge id
osm_way_idOSM way the edge belongs to

A response holds at most 50,000 edges and 10 MB of geometry. When a search settles more, truncated is true and total_edges tells you how many there were. The path edges are kept, so the route always shows up. A search that runs past your plan’s request timeout returns 408 request_timeout.

expansion(
action: "route",
origin: point(48.858, 2.294),
destination: point(48.870, 2.350),
expansion_properties: ["duration", "cumulative_cost"]
);

expansion() takes action plus that computation’s keywords: origin/destination for a route, center/time for an isochrone, origins/destinations for a matrix. It returns the same FeatureCollection as the REST endpoint, and POST /api/v1/query applies the same rules: the debug header or an admin key, and the 10-per-minute limit.