--- title: Route optimization | Plaza Docs description: 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](/guides/authentication#premium-endpoints/index.md) — each request counts as 4x. ## Small jobs (10 stops or fewer) 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 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. ## Large jobs (more than 10 stops) 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" }`. ## Modes | Mode | Network | | --------- | ----------------------------------- | | `auto` | Roads, one-ways, turn restrictions | | `foot` | Sidewalks, footpaths, trails | | `bicycle` | Bike lanes, cycleways, shared roads | ## Limits 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. ## Round trips 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 } ```