Stop removal (beta)
Take stops of a plan you hold off their routes into the unassigned pool and receive the edited plan priced.
plan.remove
Beta
node
How to call it
REST
POST
/v1/plan/remove
GraphQL
query
openPlanRemove
MCP
open_plan_remove
Take stops off their routes into the unassigned pool and get the edited plan priced and judged as open_plan_recost does, with the edited plan in `plan` (`unassigned` lists every job on no route). Billed per stop priced. Every plan tool takes an optional `matrix`, a distance snapshot from open_plan_matrix_open; the answer is the same with or without it.
Request schema
Generated from the same validation rules the endpoint runs, so a field cannot be documented without being validated.
POST /v1/plan/remove
{
"type": "object",
"properties": {
"departed_at": [],
"jobs": {
"type": "array",
"minItems": 1,
"maxItems": 2000,
"items": {
"type": "object",
"properties": {
"amount": {
"type": [
"array",
"null"
]
},
"id": {
"type": "string",
"maxLength": 128
},
"location": {
"type": "array"
},
"service_seconds": {
"type": [
"integer",
"null"
],
"minimum": 0
},
"skills": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64
}
},
"time_windows": {
"type": [
"array",
"null"
]
}
},
"required": [
"id",
"location"
]
}
},
"matrix": {
"type": [
"string",
"null"
],
"maxLength": 200
},
"options": {
"type": [
"object",
"null"
],
"properties": {
"geometry": {
"type": [
"boolean",
"null"
]
}
}
},
"profile": {
"type": [
"string",
"null"
],
"enum": [
"car",
"van",
"truck",
"bike",
"foot",
"motorcycle"
]
},
"region": {
"type": [
"string",
"null"
],
"enum": [
"NA",
"EU",
"AU",
"ASIA",
"na",
"eu",
"au",
"asia"
]
},
"routes": {
"type": "array",
"minItems": 1,
"maxItems": 200,
"items": {
"type": "object",
"properties": {
"reverse": {
"type": [
"boolean",
"null"
]
},
"stops": {
"type": "array",
"maxItems": 2000,
"items": {
"type": "string",
"maxLength": 128
}
},
"vehicle_id": {
"type": "string",
"maxLength": 128
}
},
"required": [
"vehicle_id"
]
}
},
"stops": {
"type": "array",
"minItems": 1,
"maxItems": 2000,
"items": {
"type": "string",
"maxLength": 128
}
},
"vehicles": {
"type": "array",
"minItems": 1,
"maxItems": 200,
"items": {
"type": "object",
"properties": {
"capacity": {
"type": [
"array",
"null"
]
},
"end": {
"type": [
"array",
"null"
]
},
"id": {
"type": "string",
"maxLength": 128
},
"max_distance_meters": {
"type": [
"integer",
"null"
],
"minimum": 0
},
"max_tasks": {
"type": [
"integer",
"null"
],
"minimum": 0
},
"max_travel_time_seconds": {
"type": [
"integer",
"null"
],
"minimum": 0
},
"return_to_start": {
"type": [
"boolean",
"null"
]
},
"skills": {
"type": "array",
"items": {
"type": "string",
"maxLength": 64
}
},
"start": {
"type": [
"array",
"null"
]
},
"time_window": {
"type": [
"array",
"null"
]
}
},
"required": [
"id"
]
}
}
},
"additionalProperties": false,
"required": [
"jobs",
"routes",
"stops",
"vehicles"
]
}
Request example
{
"departed_at": "2026-10-23T09:30:00-04:00",
"vehicles": [
{
"id": "van-1",
"start": {
"lat": 45.5017,
"lng": -73.5673
},
"return_to_start": true,
"capacity": {
"parcels": 10
}
},
{
"id": "van-2",
"start": {
"lat": 45.5017,
"lng": -73.5673
},
"return_to_start": true,
"capacity": {
"parcels": 10
}
}
],
"jobs": [
{
"id": "order-1001",
"location": {
"lat": 45.5088,
"lng": -73.554
},
"service_seconds": 300,
"amount": {
"parcels": 2
}
},
{
"id": "order-1002",
"location": {
"lat": 45.4972,
"lng": -73.5786
},
"service_seconds": 300,
"amount": {
"parcels": 3
}
},
{
"id": "order-1003",
"location": {
"lat": 45.5231,
"lng": -73.5817
},
"service_seconds": 300,
"amount": {
"parcels": 1
}
}
],
"routes": [
{
"vehicle_id": "van-1",
"stops": [
"order-1001",
"order-1002",
"order-1003"
]
}
],
"options": {
"geometry": false
},
"matrix": "tile2.3f0c9a5e7b1d4c2a9e8f6d5c4b3a2910",
"stops": [
"order-1002"
]
}
Response
What a successful call returns: the schema of `data` and `meta`, with a description of each field, followed by an example response from a real call.
POST /v1/plan/remove
Response schema
{
"description": "The plan without the removed stops, priced and judged as plan re-costing prices it, and the edited plan in `plan` with the removed stops among `unassigned`.",
"data": {
"type": "object",
"properties": {
"routes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vehicle_id": {
"type": "string"
},
"stop_count": {
"type": "integer",
"description": "Stops including start and end."
},
"task_count": {
"type": "integer",
"description": "Jobs on the route."
},
"distance_meters": {
"type": "integer"
},
"duration_seconds": {
"type": "integer",
"description": "Driving time."
},
"service_seconds": {
"type": "integer"
},
"waiting_seconds": {
"type": "integer"
},
"departure": {
"type": "string",
"description": "ISO 8601 with offset."
},
"completion": {
"type": "string",
"description": "When the last stop (or the end) is reached. ISO 8601 with offset."
},
"unreachable_legs": {
"type": "integer"
},
"violations": {
"type": "array",
"items": {
"type": "object",
"description": "A route-level breach. Which fields are present depends on `rule`.",
"properties": {
"rule": {
"type": "string",
"enum": [
"capacity",
"max_tasks",
"max_distance",
"max_travel_time",
"vehicle_time_window"
]
},
"message": {
"type": "string"
},
"dimension": {
"type": "string",
"description": "capacity: the capacity dimension that overflows."
},
"load": {
"type": "number",
"description": "capacity: what the stops load."
},
"capacity": {
"type": "number",
"description": "capacity: what the vehicle carries."
},
"tasks": {
"type": "integer",
"description": "max_tasks: stops on the route."
},
"distance_meters": {
"type": "integer",
"description": "max_distance: distance of the route."
},
"duration_seconds": {
"type": "integer",
"description": "max_travel_time: driving time of the route."
},
"limit": {
"type": "integer",
"description": "max_tasks, max_distance, max_travel_time: the vehicle's limit."
},
"late_seconds": {
"type": "integer",
"description": "vehicle_time_window: how far past the working window the route ends."
},
"window_end": {
"type": "string",
"description": "vehicle_time_window: when the working window ends. ISO 8601 with offset."
}
}
},
"description": "Route-level breaches."
},
"violation_count": {
"type": "integer",
"description": "Route and stop breaches on this route."
},
"stops": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"start",
"job",
"end"
]
},
"id": {
"type": "string",
"description": "The caller's job id. Jobs only."
},
"sequence": {
"type": "integer",
"description": "Position of the job on the route, from 1."
},
"reachable": {
"type": "boolean",
"description": "Whether the hop into this stop could be routed. An unreachable hop has no distance or time and is counted in `unreachable_legs`."
},
"departure": {
"type": "string",
"description": "Start only: when the vehicle leaves. ISO 8601 with offset."
},
"waiting_seconds": {
"type": "integer",
"description": "Start only, when the vehicle must wait for its working window to open."
},
"arrival": {
"type": [
"string",
"null"
],
"description": "ISO 8601 with offset. Null after an unreachable hop."
},
"arrival_epoch": {
"type": [
"integer",
"null"
],
"description": "`arrival` as Unix seconds."
},
"leg_distance_meters": {
"type": [
"integer",
"null"
],
"description": "Distance of the hop into this stop."
},
"leg_duration_seconds": {
"type": [
"integer",
"null"
],
"description": "Driving time of the hop into this stop."
},
"leg_geometry": {
"type": [
"string",
"null"
],
"description": "Encoded polyline (precision 5) of the hop into this stop. Present when `options.geometry` is true (the default)."
},
"distance_meters": {
"type": [
"integer",
"null"
],
"description": "Cumulative distance from the start."
},
"duration_seconds": {
"type": [
"integer",
"null"
],
"description": "Cumulative driving time from the start."
},
"violations": {
"type": "array",
"items": {
"type": "object",
"properties": {
"rule": {
"type": "string",
"enum": [
"skills",
"time_window"
]
},
"message": {
"type": "string"
},
"missing": {
"type": "array",
"items": {
"type": "string"
},
"description": "skills: the skills the vehicle lacks."
},
"late_seconds": {
"type": "integer",
"description": "time_window: how late the arrival is."
},
"window": {
"type": "object",
"description": "time_window: the window that was missed.",
"properties": {
"from": {
"type": "string",
"description": "ISO 8601 with offset."
},
"to": {
"type": "string",
"description": "ISO 8601 with offset."
}
}
}
}
},
"description": "Constraints this stop breaks. Present only when it breaks one."
}
},
"required": [
"type"
]
}
}
}
},
"description": "The edited plan's routes priced and judged exactly as plan re-costing prices them."
},
"summary": {
"type": "object",
"properties": {
"routes": {
"type": "integer"
},
"tasks": {
"type": "integer",
"description": "Jobs across all routes."
},
"distance_meters": {
"type": "integer"
},
"duration_seconds": {
"type": "integer",
"description": "Driving time across all routes."
},
"unreachable_legs": {
"type": "integer",
"description": "Hops that could not be routed."
},
"violations": {
"type": "integer",
"description": "Breaches across all routes and stops."
}
}
},
"plan": {
"type": "object",
"description": "The edited plan in the shape it is sent: put it in place of your own. Routes keep your order; a vehicle that received its first stops is added last. Stops are in driving order, so a route sent with `reverse` comes back already reversed.",
"properties": {
"routes": {
"type": "array",
"items": {
"type": "object",
"properties": {
"vehicle_id": {
"type": "string"
},
"stops": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"vehicle_id",
"stops"
]
}
},
"unassigned": {
"type": "array",
"items": {
"type": "string"
},
"description": "Every job of the plan that is on no route."
}
},
"required": [
"routes",
"unassigned"
]
},
"removed": {
"type": "array",
"description": "Each removed stop with the vehicle and position it was taken from.",
"items": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"vehicle_id": {
"type": "string"
},
"position": {
"type": "integer"
}
}
}
}
},
"required": [
"routes",
"summary",
"plan",
"removed"
]
},
"meta": {
"type": "object",
"properties": {
"region": {
"type": "string",
"description": "The engine region used."
},
"profile": {
"type": "string",
"description": "The vehicle profile used."
},
"geometry": {
"type": "boolean",
"description": "Whether leg geometry was returned."
},
"geometry_format": {
"type": [
"string",
"null"
],
"description": "`polyline` when geometry was returned."
},
"departed_at": {
"type": "string",
"description": "The departure time the plan was timed from: `departed_at`, else the current time. ISO 8601 with offset."
}
},
"additionalProperties": true
}
}
Response example
{
"request_id": "req_01k8zq3m5n7p9r1t3v5x7z9b2d",
"capability": "plan.remove",
"billing": {
"unit": "node",
"quantity": 2,
"counted": true,
"breakdown": {
"tasks": 2,
"routes": 1
}
},
"data": {
"routes": [
{
"vehicle_id": "van-1",
"stop_count": 4,
"task_count": 2,
"distance_meters": 8931,
"duration_seconds": 1174,
"service_seconds": 600,
"waiting_seconds": 0,
"departure": "2026-10-23T09:30:00-04:00",
"completion": "2026-10-23T09:59:34-04:00",
"unreachable_legs": 0,
"violations": [],
"violation_count": 0,
"stops": [
{
"type": "start",
"departure": "2026-10-23T09:30:00-04:00"
},
{
"type": "job",
"id": "order-1001",
"sequence": 1,
"reachable": true,
"leg_distance_meters": 1759,
"leg_duration_seconds": 231,
"leg_geometry": null,
"arrival": "2026-10-23T09:33:51-04:00",
"arrival_epoch": 1792762431,
"distance_meters": 1759,
"duration_seconds": 231
},
{
"type": "job",
"id": "order-1003",
"sequence": 2,
"reachable": true,
"leg_distance_meters": 3620,
"leg_duration_seconds": 476,
"leg_geometry": null,
"arrival": "2026-10-23T09:46:47-04:00",
"arrival_epoch": 1792763207,
"distance_meters": 5379,
"duration_seconds": 707
},
{
"type": "end",
"reachable": true,
"leg_distance_meters": 3552,
"leg_duration_seconds": 467,
"leg_geometry": null,
"arrival": "2026-10-23T09:59:34-04:00",
"arrival_epoch": 1792763974,
"distance_meters": 8931,
"duration_seconds": 1174
}
]
}
],
"summary": {
"routes": 1,
"tasks": 2,
"distance_meters": 8931,
"duration_seconds": 1174,
"unreachable_legs": 0,
"violations": 0
},
"plan": {
"routes": [
{
"vehicle_id": "van-1",
"stops": [
"order-1001",
"order-1003"
]
}
],
"unassigned": [
"order-1002"
]
},
"removed": [
{
"id": "order-1002",
"vehicle_id": "van-1",
"position": 2
}
]
},
"meta": {
"region": "NA",
"profile": "car",
"geometry": false,
"geometry_format": null,
"departed_at": "2026-10-23T09:30:00-04:00",
"mode": "sync"
}
}
What it costs
Every point the solver must visit or depart from, including each vehicle's start and end.
Every billable response carries a billing block with the unit, the quantity and how the quantity was derived.
Errors it can return
| Status | Code | Description |
|---|---|---|
| 401 | TOKEN_INVALID |
Unknown or revoked API token. |
| 401 | TOKEN_MISSING |
No API token. Send Authorization: Bearer <your token>. |
| 403 | CAPABILITY_NOT_ENABLED |
This capability is not enabled for your account. See :doc to enable it. |
| 403 | CAPABILITY_NOT_GRANTED_TO_KEY |
Your account has this capability, but this API key was not granted it. |
| 403 | OPEN_API_DISABLED |
Open Platform access is not enabled for this account. |
| 422 | VALIDATION_FAILED |
The request failed validation. See details. |
| 429 | RATE_LIMITED |
Too many requests. Please retry after the indicated delay. |
| 500 | INTERNAL_ERROR |
An unexpected error occurred. Quote the request_id when contacting support. |