Skip to content
GuidesBlogPlaygroundDashboard
Routing & Navigation

Route optimization

Solve the traveling salesman problem. Find the fastest order to visit a set of stops.

Route optimization takes your stops and returns the visit order that minimizes total travel time (the traveling salesman problem).

Route optimization is a premium endpoint — each request counts as 4x.

10 stops or fewer return synchronously:

Terminal window
curl -X POST https://plaza.fyi/api/v1/optimize \
-H "x-api-key: pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"waypoints": [
{ "type": "Point", "coordinates": [-73.9857, 40.7484] },
{ "type": "Point", "coordinates": [-74.0060, 40.7128] },
{ "type": "Point", "coordinates": [-73.9712, 40.7831] },
{ "type": "Point", "coordinates": [-73.9680, 40.7614] },
{ "type": "Point", "coordinates": [-73.9855, 40.7580] }
],
"mode": "auto"
}'
import Plaza from "@plazafyi/sdk";
const client = new Plaza();
const result = await client.v1.optimize({
locations: [
{ type: "Point", coordinates: [-73.9857, 40.7484] },
{ type: "Point", coordinates: [-74.006, 40.7128] },
{ type: "Point", coordinates: [-73.9712, 40.7831] },
{ type: "Point", coordinates: [-73.968, 40.7614] },
{ type: "Point", coordinates: [-73.9855, 40.758] },
],
mode: "auto",
});
console.log(result.total_cost_s);
import plaza
client = plaza.Client()
result = client.v1.optimize(
locations=[
{"type": "Point", "coordinates": [-73.9857, 40.7484]},
{"type": "Point", "coordinates": [-74.0060, 40.7128]},
{"type": "Point", "coordinates": [-73.9712, 40.7831]},
{"type": "Point", "coordinates": [-73.9680, 40.7614]},
{"type": "Point", "coordinates": [-73.9855, 40.7580]},
],
mode="auto",
)
print(result["total_cost_s"])
import "github.com/plazafyi/plaza-go"
client := plaza.NewClient()
result, _ := client.V1.Optimize(ctx, plaza.OptimizeParams{
Locations: []plaza.GeoJSONPoint{
{Type: "Point", Coordinates: []float64{-73.9857, 40.7484}},
{Type: "Point", Coordinates: []float64{-74.0060, 40.7128}},
{Type: "Point", Coordinates: []float64{-73.9712, 40.7831}},
{Type: "Point", Coordinates: []float64{-73.9680, 40.7614}},
{Type: "Point", Coordinates: []float64{-73.9855, 40.7580}},
},
Mode: "auto",
})

Response — a GeoJSON FeatureCollection with waypoints in optimized visit order:

{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-73.9857, 40.7484] },
"properties": {
"waypoint_index": 0,
"cost_s": 0,
"cumulative_cost_s": 0
}
},
{
"type": "Feature",
"geometry": { "type": "Point", "coordinates": [-73.9855, 40.7580] },
"properties": {
"waypoint_index": 4,
"cost_s": 420,
"cumulative_cost_s": 420
}
}
],
"total_cost_s": 2940,
"optimization": "tsp",
"roundtrip": true
}

waypoint_index maps back to your input array. cost_s is travel time from the previous stop; cumulative_cost_s is the running total.

Above 10 stops, the request runs asynchronously and returns a job ID:

Terminal window
curl -X POST https://plaza.fyi/api/v1/optimize \
-H "x-api-key: pk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"waypoints": [
{ "type": "Point", "coordinates": [-73.9857, 40.7484] },
{ "type": "Point", "coordinates": [-74.0060, 40.7128] },
{ "type": "Point", "coordinates": [-73.9712, 40.7831] },
{ "type": "Point", "coordinates": [-73.9680, 40.7614] },
{ "type": "Point", "coordinates": [-73.9855, 40.7580] },
{ "type": "Point", "coordinates": [-73.9776, 40.7527] },
{ "type": "Point", "coordinates": [-73.9542, 40.7681] },
{ "type": "Point", "coordinates": [-73.9937, 40.7505] },
{ "type": "Point", "coordinates": [-73.9654, 40.7829] },
{ "type": "Point", "coordinates": [-73.9818, 40.7681] },
{ "type": "Point", "coordinates": [-73.9726, 40.7644] },
{ "type": "Point", "coordinates": [-73.9499, 40.7736] }
],
"mode": "auto"
}'
{
"status": "processing",
"job_id": "opt_8f3a2b1c"
}

Poll until it’s done:

Terminal window
curl https://plaza.fyi/api/v1/optimize/opt_8f3a2b1c \
-H "x-api-key: pk_live_YOUR_KEY"
// The SDK handles polling for you
const result = await client.v1.optimize({
locations: stops, // array of GeoJSON Point objects
mode: "auto",
});
// Blocks until the job finishes, then returns the same response format

When done, the poll endpoint returns { "status": "completed", "result": { ... } } with the same FeatureCollection format. While running, it returns { "status": "processing" }.

ModeNetwork
autoRoads, one-ways, turn restrictions
footSidewalks, footpaths, trails
bicycleBike lanes, cycleways, shared roads

Maximum 50 waypoints per request. Small jobs (up to 10) return in under a second. Larger ones scale roughly with the square of the stop count.

By default, the route returns to the starting point. Set "roundtrip": false for an open-ended route:

{
"waypoints": [
{ "type": "Point", "coordinates": [-73.9857, 40.7484] },
{ "type": "Point", "coordinates": [-74.0060, 40.7128] },
{ "type": "Point", "coordinates": [-73.9712, 40.7831] },
{ "type": "Point", "coordinates": [-73.9680, 40.7614] }
],
"mode": "auto",
"roundtrip": false
}