Overview
The V3 Routing API is a ground-up rewrite with a new, faster solver engine replacing Timefold. The V2 endpoint (/v2/vrp/sync/solve) remains available for backwards compatibility — internally it maps to V3 and back.
Endpoint change
Request mapping
Vehicles (Resources → Vehicles)
name→idshifts[].start/endmove to insideshifts[]as aPlace({ "coordinate": [lon, lat] }) — this is still inside the shift in both V2 and V3, but the coordinate format changes- Coordinates:
{ "latitude", "longitude" }object →{ "coordinate": [longitude, latitude] }Place (GeoJSON order, wrapped in object) capacity: array[100]→ named map{ "weight": 100 }(dimension names must match jobdemandkeys)tags→skills(resource-leveltags[]is mapped 1:1 via the V2 compat endpoint; only per-shiftshifts[].tags— per-shift capability tags — has no V3 equivalent, since V3 skills are vehicle-level, not shift-level)- New:
limits.max_distance_m,limits.max_route_duration_sfor vehicle range constraints (max_route_duration_scaps the whole route span — travel + service + wait — not pure drive time; V3 has no pure-drive-time cap)
Jobs
name→idlocation:{ "latitude", "longitude" }→ Place object{ "coordinate": [longitude, latitude] }duration→service_duration_s(still in seconds)loadarray →demandnamed map (e.g.[10]→{ "weight": 10 })windows→time_windows(nohardflag — all time windows are hard in V3 Phase 1)- Skills:
skills: [{ "name": "refrigerated" }]— supported today; all required skills must be present on the vehicle - Committed vehicle: a hard pin uses
locked_vehicle(survives re-optimization).eligible_vehicles: { "allowed": [...] }is a different mechanism — an eligibility whitelist among several allowed vehicles, not a single-vehicle pin
Relations
V3 uses a tagged-union format withjob_ids (not jobs). V2 relation types map as follows:
resource field (pin relation to a specific vehicle) maps to locked_vehicle applied to every job in the relation — supported today, not a workaround.
Options
- V2’s
?millis=query parameter (already in milliseconds) →options.runtime.time_limit_msrequest body field (also milliseconds) - New:
options.runtime.seedfor reproducible results - New:
options.runtime.matrix— supply custom distance/duration matrices (bypasses Solvice Maps) - Objective tuning (minimize time vs. distance) is configured via the
objectivefield — Coming soon
Response mapping
trips→routes;resource→vehicle(a plain vehicle-id string, e.g."truck-1")visits→stops(typed:start,job,end, etc.)- V3 stops carry
type,id,arrival,departure,wait_s,service_s,travel_time_s,load_after(named map) - V3 routes use
distance_m/duration_s(not baredistance/duration) unserved(string list) →unassigned(objects withjob_idandreasons[])- New
summaryblock withjobs_assigned/jobs_unassigned,total_distance_m,total_duration_s,estimated_cost,elapsed_ms,iterations - Coordinates in response are bare
[longitude, latitude]arrays
V2 features not mapped via compat endpoint
When using the V2 endpoint (/v2/vrp/sync/solve), the following V2 fields are silently dropped during conversion:
shifts[].tags(per-shift capability tags) — V3 skills are vehicle-level; split the resource into one V3 vehicle per differing shift to approximate this. (Resource-levelresources[].tagsitself is forwarded, viaskills.)windows[].hard: false+ its per-windowweight— V3 can price lateness fleet-wide viaobjective.costs.per_late_hour, but the per-window weight is lost; there is no per-window soft-cost equivalent- Per-visit
serviceTime,travelTime,distance— not populated in the V2 response
Feature parity
Most of V2’s features already ship in V3 today, often via a different mechanism (currency-priced rather than ranked, or a coarser-grained workaround field). A handful remain genuine gaps.V3 is under active development. The V2 endpoint (
/v2/vrp/sync/solve) remains available and internally maps to the V3 solver — you get V3’s performance with the V2 API contract.