Open Application Platform Docs

Plan validation

Judge a plan against its stated constraints — time windows, capacity, skills, vehicle ceilings — with every violation named. The same evaluator as re-costing, without the map payload.

plan.validate Stable node

How to call it

REST

POST /v1/plan/validate

GraphQL

query openPlanValidate

MCP

open_plan_validate

Judge a plan against the constraints it states — time windows (early is waiting, past every window is late), capacity per dimension, skills, and the vehicle's window, distance, travel-time and stop-count ceilings — and get every violation named on the stop or route at fault. The same evaluator as open_plan_recost with the map payload stripped; violations are reported, never refused. Billed per stop.

Request schema

Generated from the same validation rules the endpoint runs, so a field cannot be documented without being validated.

POST /v1/plan/validate

{
    "type": "object",
    "properties": {
        "departed_at": [],
        "jobs": {
            "type": "array",
            "minItems": 1,
            "maxItems": 2000,
            "items": {
                "type": "object",
                "properties": {
                    "amount": {
                        "type": [
                            "array",
                            "null"
                        ]
                    },
                    "id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "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": [
                    "location"
                ]
            }
        },
        "matrix": {
            "type": [
                "string",
                "null"
            ],
            "maxLength": 200
        },
        "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"
                ]
            }
        },
        "vehicles": {
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
                "type": "object",
                "properties": {
                    "capacity": {
                        "type": [
                            "array",
                            "null"
                        ]
                    },
                    "end": {
                        "type": [
                            "array",
                            "null"
                        ]
                    },
                    "id": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "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"
                        ]
                    }
                }
            }
        }
    },
    "additionalProperties": false,
    "required": [
        "jobs",
        "routes",
        "vehicles"
    ]
}

Request example

{
    "departed_at": "2026-11-02T08:00:00-05:00",
    "vehicles": [
        {
            "id": "van-1",
            "start": {
                "lat": 45.5017,
                "lng": -73.5673
            },
            "return_to_start": true,
            "capacity": [
                10
            ]
        }
    ],
    "jobs": [
        {
            "id": "order-1001",
            "location": {
                "lat": 45.5088,
                "lng": -73.554
            },
            "service_seconds": 300,
            "amount": [
                2
            ]
        },
        {
            "id": "order-1002",
            "location": {
                "lat": 45.4972,
                "lng": -73.5786
            },
            "service_seconds": 300,
            "amount": [
                9
            ],
            "time_windows": [
                [
                    "2026-11-02T08:00:00-05:00",
                    "2026-11-02T08:05:00-05:00"
                ]
            ]
        }
    ],
    "routes": [
        {
            "vehicle_id": "van-1",
            "stops": [
                "order-1001",
                "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/validate

Response schema

{
    "description": "Whether the caller's routes keep every stated constraint, and where they do not. Same walk as plan.recost, reduced to what a violation highlighter needs. A plan with breaches answers 200 with `valid: false` and a PLAN_VIOLATIONS warning.",
    "data": {
        "type": "object",
        "properties": {
            "valid": {
                "type": "boolean",
                "description": "True when no route breaks anything."
            },
            "routes": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "vehicle_id": {
                            "type": "string"
                        },
                        "valid": {
                            "type": "boolean"
                        },
                        "violation_count": {
                            "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."
                        },
                        "waiting_seconds": {
                            "type": "integer"
                        },
                        "completion": {
                            "type": "string",
                            "description": "ISO 8601 with offset."
                        },
                        "unreachable_legs": {
                            "type": "integer"
                        },
                        "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": "Stops with their timing and their own violations; no geometry."
                        }
                    }
                }
            },
            "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."
                    }
                }
            }
        }
    },
    "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.validate",
    "billing": {
        "unit": "node",
        "quantity": 2,
        "counted": true,
        "breakdown": {
            "tasks": 2,
            "routes": 1
        }
    },
    "warnings": [
        {
            "code": "PLAN_VIOLATIONS",
            "message": "The plan breaks 2 stated constraint(s); see `violations` on the routes and stops."
        }
    ],
    "data": {
        "valid": false,
        "routes": [
            {
                "vehicle_id": "van-1",
                "valid": false,
                "violation_count": 2,
                "violations": [
                    {
                        "rule": "capacity",
                        "message": "The stops load more than the vehicle carries.",
                        "dimension": "0",
                        "load": 11,
                        "capacity": 10
                    }
                ],
                "waiting_seconds": 0,
                "completion": "2026-11-02T08:23:52-05:00",
                "unreachable_legs": 0,
                "stops": [
                    {
                        "type": "start",
                        "departure": "2026-11-02T08:00:00-05:00"
                    },
                    {
                        "type": "job",
                        "id": "order-1001",
                        "sequence": 1,
                        "reachable": true,
                        "arrival": "2026-11-02T08:04:05-05:00",
                        "arrival_epoch": 1793624645
                    },
                    {
                        "type": "job",
                        "id": "order-1002",
                        "sequence": 2,
                        "reachable": true,
                        "arrival": "2026-11-02T08:15:35-05:00",
                        "arrival_epoch": 1793625335,
                        "violations": [
                            {
                                "rule": "time_window",
                                "message": "Arrival is after every time window of this stop.",
                                "late_seconds": 635,
                                "window": {
                                    "from": "2026-11-02T08:00:00-05:00",
                                    "to": "2026-11-02T08:05:00-05:00"
                                }
                            }
                        ]
                    },
                    {
                        "type": "end",
                        "reachable": true,
                        "arrival": "2026-11-02T08:23:52-05:00",
                        "arrival_epoch": 1793625832
                    }
                ]
            }
        ],
        "summary": {
            "routes": 1,
            "tasks": 2,
            "distance_meters": 6416,
            "duration_seconds": 832,
            "unreachable_legs": 0,
            "violations": 2
        }
    },
    "meta": {
        "region": "NA",
        "profile": "car",
        "departed_at": "2026-11-02T08:00:00-05: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.