V3 is in beta. General availability (GA) is planned for January 2027.
POST /v3/routing/solve. For each field and the JSON to send, see Constraints.
On this page a task is a job or a shipment. Where a rule applies to jobs only, the page says “job”.
Coming from V2? There are no constraint weights and no hard/medium/soft score levels here. A rule is either hard (it always holds) or it is a price in your own currency. See Migration from V2.
Hard and soft
Every rule you send is one of two kinds:
A solve result never contains a broken hard rule:
summary.score.violations is always 0 on /v3/routing/solve. To check a plan of your own, which may break hard rules, use /v3/routing/evaluate.
Hard constraints
Only the rules you send are active. A request with capacities and nothing else is checked for capacity and nothing else.Capacity
Dimensions are named and matched by name betweencapacity and pickup.
Time windows
A window is hard unless you price lateness. This job must be reached between 09:00 and 12:00:from; only the late side can be made soft.
Relations
relations[] ties jobs to each other. It has nine types, and all of them are hard.
An unknown relation
type is rejected with HTTP 400.
A shipment already has one built-in rule of its own: the pickup comes before the delivery, on the same route. See Relations for every field and every rejected combination.
Soft constraints
Use these levers to allow something at a price. Each one reports what it cost insummary.score.components.
How they combine:
- Lateness, per window or fleet-wide. Use
time_windows[].per_late_hourwhen only some tasks may run late: it softens that one window and leaves every other window hard. It must be greater than0and is allowed only on a task with exactly one window. Useobjective.per_late_hourto soften all windows at once; a window with its own rate keeps that rate. Omit the fleet rate to keep windows hard: an explicit0.0is rejected with HTTP 400. - Alternative-window cost does not soften anything. Every window stays hard;
costonly grades which of a task’s two or more windows is preferred. A non-zero windowcostanywhere in the request cannot be combined withobjective.per_late_hour(HTTP 400). - A target is a point, not a window. It never makes a task unassignable and never forces a vehicle to wait. On a shipment it is measured on the delivery leg. The stop reports
target_lateness_s. - Overtime is bounded.
max_overtime_sgrants the extension; anything beyondto + max_overtime_sis still forbidden. Withoutper_overtime_hourovertime carries no extra charge beyond the normal hourly route rate. - Preference entries are independent. A task listing several preferred vehicles pays for every listed vehicle that does not serve it, including when one of the others does. A vehicle with several
preferred_tagscharges each tag the task lacks.
drop_fee makes a task optional at a price, preferred_date with objective.non_preferred_date_cost steers a task to a day, and objective.grouping keeps nearby tasks together. Skills, capacity, eligibility, relations, limits and quotas have no soft form.
From constraints to the objective
Among the plans that respect every hard rule, the solver compares in a fixed order: leastunserved_priority first, then least cost. Serving required tasks always comes before saving money; every soft lever above is part of cost. Objective function covers the comparison, priority, and the cost model in full.
You set cost in two places: fleet-wide rates under objective.costs, and per-vehicle terms under vehicles[].costs.
start and end, each naming a location or a depot.
Why a task is left unassigned
When the solver leaves a task out of the plan, the solve response says why. Each task left out has an entry inunassigned[]; you do not need an extra request or flag.
categorytells you what kind of fix can work.impossibleandblockedmean a hard rule is in the way: change the request, or add capacity or working time.priced_outmeans the task has adrop_feeand paying it was cheaper than serving the task.search_limitmeans a worthwhile place exists and the time budget ran out first.reasons[].codenames the rule that blocked the task. One code is reported per task.relaxations[]gives the smallest change that would have let the task fit, when one number can express it:reduce_demand(in load units) for capacity,extend_time_window(in seconds) for time windows. It is empty for rules such as skills, where the fix is structural.fieldnames the task by its id, under/jobs/or/shipments/; it is a label, not a path into your request body.
Performance impact
The solver checks only the rules your request uses, so a plain capacity problem is the fastest kind to search. Each additional kind of rule (time windows, skills, relations, shipments, breaks) adds work to every candidate move, which means fewer moves explored in the sameoptions.time_limit_s. Send the rules your operation needs and leave out the ones it does not. See the Performance guide for the other levers.
Best practices
- Use a hard rule for anything that must always hold. Capacity, skills, eligibility and limits belong in their own fields, not in a large cost.
- Pick the narrowest lateness lever. Soften one task’s single window with
time_windows[].per_late_hour, soften all windows withobjective.per_late_hour, and usetargetfor a deadline that must never make a task unassignable. - Make a task optional with
drop_fee. Tasks are required by default. - Rank required tasks with
priority. When not every required task fits, the solver keeps the higher-priority ones. See Objective function. - Read
unassigned[]before tuning costs. Cost rates do not rescue a task that a hard rule blocks;category,reasonsandrelaxationstell you what does. - Do not rely on a relation to constrain a shipment. Relations act on jobs. To tie a shipment to a vehicle, set
locked_vehicleoreligible_vehicleson the shipment.
drop_fee and priority on one task, are rejected with HTTP 400 and a message describing the problem. See Errors.
Related topics
Constraints
Every constraint field, with the JSON to send
Objective function
How plans are compared,
priority, and the cost modelExplainable AI
Worked examples of the
unassigned[] diagnosisPerformance guide
How problem size and constraint choice affect solve time