How to Read an Optimized Route Plan and Schedule
- API or service
- Route Planner API
- Task
- Route Planner response → agent routes and execution schedule
- Examples
- Difficulty
- Intermediate
- Time
- 10 min
Read an optimized route plan and schedule
You have received a Route Planner GeoJSON response and need to turn it into driver routes, ordered work, and a schedule that the application can display or execute.
The top-level collection describes the complete solution. Each feature represents one assigned agent plan. Inside an agent plan, actions provide the execution sequence, waypoints group actions by visited location, and legs describe travel between consecutive waypoints.
Task flow: Route Planner response → validate issues → select an agent feature → read actions, waypoints, legs, and relative times.
Understand the response structure
| Path | Meaning |
|---|---|
properties.mode |
Travel mode used for the solution |
properties.params |
Normalized input used to calculate the plan |
properties.issues |
Optional indexes of unassigned agents, jobs, or shipments |
features[] |
One feature for each agent with an assigned plan |
features[].properties.agent_id |
Stable agent ID when one was supplied |
features[].properties.actions[] |
Ordered start, job, pickup, delivery, break, and end operations |
features[].properties.waypoints[] |
Ordered visited locations and the actions grouped at each location |
features[].properties.legs[] |
Travel segments between waypoint indexes |
features[].geometry |
Route geometry in GeoJSON [longitude, latitude] coordinate order |
Do not assume feature index equals agent index. Read agent_id when available or agent_index to map a feature back to properties.params.agents.
Keep params when storing a solution. Index fields such as job_index and shipment_index refer to the corresponding input arrays and cannot be interpreted safely without that input.
Read actions and relative times
The following reduced agent plan comes from the pickup-and-delivery example. Actions are already ordered for execution.
Reduced response:
{
"agent_id": "courier-a",
"agent_index": 0,
"distance": 18575,
"time": 2239,
"start_time": 0,
"end_time": 2239,
"actions": [
{"index": 0, "type": "start", "start_time": 0, "duration": 0, "waypoint_index": 0},
{"index": 1, "type": "pickup", "shipment_id": "order-101", "start_time": 0, "duration": 120, "waypoint_index": 0},
{"index": 2, "type": "delivery", "shipment_id": "order-101", "start_time": 398, "duration": 180, "waypoint_index": 1},
{"index": 3, "type": "pickup", "shipment_id": "order-102", "start_time": 901, "duration": 120, "waypoint_index": 2},
{"index": 4, "type": "delivery", "shipment_id": "order-102", "start_time": 1750, "duration": 180, "waypoint_index": 3},
{"index": 5, "type": "end", "start_time": 2239, "duration": 0, "waypoint_index": 4}
]
}
All times are relative seconds. If zero represents 08:00, the first delivery starts 398 seconds later, at 08:06:38. Its 180-second duration means service ends at 08:09:38.
Use job_id or shipment_id to retrieve the application record for an action. Use waypoint_index to find the visited location. Several actions may share one waypoint when work occurs at the same coordinates.
Read waypoints and route legs
The request location and the road-matched route location are deliberately separate:
Reduced response:
{
"waypoints": [
{
"original_location": [13.4132, 52.5219],
"location": [13.41373, 52.522937],
"start_time": 0,
"duration": 120,
"next_leg_index": 0
},
{
"original_location": [13.3777, 52.5163],
"location": [13.378236, 52.51634],
"start_time": 398,
"duration": 180,
"prev_leg_index": 0,
"next_leg_index": 1
}
]
}
original_location is the coordinate supplied by the application. location is the position matched for routing. Both use [longitude, latitude] order.
Use the matched location and returned geometry to draw the calculated route. Keep original_location when showing the customer's selected point or validating how far the service adjusted it.
prev_leg_index identifies travel into a waypoint; next_leg_index identifies travel away from it. Each referenced leg contains its distance, time, source and destination waypoint indexes, and lower-level geometry steps.
Check unassigned work before using the plan
properties.issues may contain zero-based indexes in unassigned_jobs, unassigned_shipments, or unassigned_agents. The property may be absent when the optimizer reports no issues.
const issues = routePlan.properties.issues ?? {};
const params = routePlan.properties.params;
const unassignedJobs = (issues.unassigned_jobs ?? [])
.map((index) => params.jobs[index]);
const unassignedShipments = (issues.unassigned_shipments ?? [])
.map((index) => params.shipments[index]);
if (unassignedJobs.length || unassignedShipments.length) {
console.warn("The route plan is incomplete", {
unassignedJobs,
unassignedShipments
});
}
Do not treat HTTP 200 as proof that every task was scheduled. Before dispatching, verify issue arrays, confirm every expected stable ID occurs in an action, and check that all agent plans fall within application-specific rules.
Typical causes include insufficient capacity, missing capabilities, incompatible time windows, an unavailable agent, or a route made infeasible by travel restrictions. Report the affected business IDs to the user rather than only their array indexes.