- Hard constraints define feasibility. A plan that violates one is invalid — the job is left unassigned rather than placed illegally.
- Soft constraints are priced into the objective. They can be bent for a cost, so the solver trades them off against everything else.
The V3 schema is final, but capabilities land in phases. Rules marked
Coming soon are accepted by the schema and currently return a
400 that names
the field — never a silently-ignored constraint.Overview
| Constraint | Kind | Driven by | Status |
|---|---|---|---|
| Capacity | hard | vehicle.capacity · job.demand | Available |
| Load compatibility | hard | vehicle.incompatible_dimensions | Coming soon |
| Time windows | hard | job.time_windows (no cost fields) | Available |
| Soft time windows | soft | job.time_windows.earliness_cost_per_hour / lateness_cost_per_hour | Coming soon |
| Shift hours & overtime | hard | shift.from/to, shift.max_overtime_s | Available |
| Skills (hard) | hard | job.skills[].name ⊆ vehicle.skills | Available |
| Skills (soft) | soft | job.skills[].violation_cost | Coming soon |
| Allowed / excluded vehicles | hard | job.eligible_vehicles.allowed/excluded | Available |
| Vehicle preferences | soft | job.preferences[].violation_cost | Coming soon |
| Max distance / drive time | hard | vehicle.limits.max_distance_m / max_drive_time_s | Available |
| Max stops | hard | vehicle.limits.max_tasks | Available |
| Sequence (ordered) | hard | relations: ordered (job ids) | Available |
| Consecutive | hard | relations: consecutive | Available |
| Same resource | hard | relations: same_resource | Available |
| Same route | hard | relations: same_route | Available |
| Group sequence | hard | relations: ordered (tags) | Available |
| Same day | hard | relations: same_day | Coming soon |
| Pickup & delivery | hard | job.pickup + job.delivery | Available |
| Driver breaks | hard | shift.breaks | Coming soon |
| Synchronisation | hard | relations: synchronized | Coming soon |
Capacity
Every vehicle has a multi-dimensional capacity; every job a demand. The load on a vehicle may never exceed its capacity on any dimension. Dimensions are named and matched by name, soweight, volume, pallets line up across jobs
and vehicles regardless of declaration order.
400 — you never
get a silently-infeasible plan.
The response carries load_after on every stop as a named map ({ "weight": 30, "volume": 2 }),
matching the same dimension names.
Load compatibility
Coming soon.
vehicle.incompatible_dimensions: [["general", "glass"]] — declares pairs of load dimensions that may not share a vehicle at the same time (the waste-collection “don’t mix streams” rule).Time windows
A job may carry one or moretime_windows. A hard window must be
respected — if the vehicle can’t arrive within any window, the job is unassigned.
Multiple windows mean “any of these slots is acceptable”.
The allowed service window. Hard by default — arriving outside the window
makes the job unassignable. Available.
Cost rate per hour of arriving early. When set, early arrival is allowed
and priced instead of forbidden. (Coming soon — currently returns 400.)
Cost rate per hour of arriving late. When set, late arrival is allowed
and priced instead of forbidden. (Coming soon — currently returns 400.)
from == to and both cost fields set models a soft target time
(penalised on both sides). The old target_arrival field is gone — this replaces it.
Shift hours & overtime
A vehicle works only within its shift windows. Each shift has afrom/to; the
route — including travel back to the end depot — must finish by to, unless
max_overtime_s allows a costed extension.
Skills
Each job can require skills the serving vehicle must have. Matching is a subset check:job.skills[].name ⊆ vehicle.skills.
The required skill name. The serving vehicle must have this skill in its
skills list. Available (hard).When set, the skill becomes soft — assigning a vehicle that lacks it costs
violation_cost instead of being infeasible. (Coming soon — currently returns 400.)Vehicle eligibility
One object expresses every “which vehicle may serve this job” rule. Hard restrictions live ineligible_vehicles; soft preferences live in preferences.
Hard whitelist — only these vehicles may serve the job. Omit to allow all
vehicles. Available.
Hard blacklist — these vehicles may never serve the job. Mutually exclusive
with
allowed. Available.Soft vehicle affinity:
[{ "vehicle": "v2", "violation_cost": 800 }]. Serving
a non-preferred vehicle costs violation_cost against the objective.
(Coming soon — currently returns 400.)Route limits
Per-vehicle caps on the shape of a route, grouped underlimits. All hard.
Total route distance cap, metres. Available.
Total driving time cap, seconds (excludes service & wait). Available.
Total duty time cap, seconds (includes service & wait). Available.
Maximum number of job stops on the route. Available.
Sequencing
Inter-job ordering and grouping are expressed through therelations array. Each
relation references jobs either explicitly (job_ids) or by tag (group), but
not both.
| Rule | Meaning | Status |
|---|---|---|
ordered (job ids) | Jobs appear in this order on one route | Available |
ordered (tags) | Tag groups appear in this order; order within a group is free | Available |
consecutive | Jobs are adjacent; ordered: true also fixes their order | Available |
same_resource | Jobs served by the same vehicle — continuity of care across days | Available |
same_route | Jobs on the same route in the same shift | Available |
same_day | Jobs on the same calendar day | Coming soon |
synchronized | Two vehicles meet at a location within max_wait_s | Coming soon |
job_ids entries are polymorphic — each string is a job id or a tag
(which expands to all jobs carrying that tag).
Shipments
A shipment is a pickup → delivery pair: ajob with pickup + delivery legs
instead of flat visit fields. The solver guarantees the pickup precedes the
delivery on the same route, and the carried demand counts against capacity only
between the two stops. Same-vehicle and ordering are implicit — never expressed as a
separate relation.
Available for mandatory shipments with coordinate legs, hard skills, hard time windows, and (optionally) a single allowed vehicle. Droppable shipments, soft skills/windows, multi-vehicle eligibility, and depot-referenced legs are Coming soon.
Driver breaks
Coming soon.
shift.breaks[] — floating (flexible within a window) and fixed (a mandatory off-duty interval), with an optional drive/duty trigger.The V3 API Model
How the full request is structured.
API Reference
The
POST /v3/routing/solve schema.