Skip to main content

Jobs

A job is something that needs to happen at one or more locations. For a simple visit (delivery, service call, inspection) place its visit fields directly on the job object. Pickup-then-delivery shipments use pickup + delivery instead — see Shipments.
  • location — a Place: { "coordinate": [lon, lat] }, or a reference to a named location or depot.
  • service_duration_s — seconds spent at the location, excluding travel.
  • time_windows — when the job can be served (ISO 8601 from/to pairs). Hard by default — no earliness_cost_per_hour or lateness_cost_per_hour.
  • demand — named capacity consumed, e.g. { "weight": 10 }. Matched against vehicle.capacity by name.
  • skills — capability requirements, e.g. [{ "name": "refrigerated" }]. A job can only be served by a vehicle that has all required skills.
  • mandatory — set true to require the job be served (infeasible if it cannot be). Omit or use unassigned_cost for a droppable job.

Shipments

Coming soon. Pickup-then-delivery jobs use job.pickup + job.delivery instead of flat visit fields. The solver guarantees pickup precedes delivery on the same route, and demand counts against capacity only between the two stops.

Vehicles

A vehicle represents a driver or asset with capacity, skills, a cost model, and one or more working shifts.
  • capacity — named dimension limits matched against job demand by name. { "weight": 1000, "volume": 50 } is two independent caps.
  • skills — capability tags the vehicle provides. A vehicle can serve a job only when its skills are a superset of the job’s required skills.
  • limits — optional route caps: max_distance_m, max_drive_time_s, max_duty_time_s, max_leg_drive_time_s.
  • shifts — working time windows (ISO 8601 from/to). At least one shift is required. start and end are the depot Place for this shift — set inside shifts, not at vehicle top-level. shifts[].max_tasks caps the number of stops in that shift.
Multiple shifts on one vehicle model multi-day availability.

Distance matrices

V3 automatically fetches road-network distance and duration matrices from Solvice Maps. You don’t need to provide a matrix unless you have custom distances. To supply a custom matrix, include it in options.runtime.matrix:
Both matrices must be square N×N. Values are distances in metres and durations in seconds. Road-network matrices are typically asymmetric (A→B ≠ B→A).

Constraints

The solver enforces these constraints (hard — never violated unless explicitly softened): See the full Constraints guide for field-level details and coming-soon capabilities.

Objective

The solver minimises a lexicographic objective:
  1. Serve as many jobs as possible (highest priority — assign before optimising cost)
  2. Minimise vehicles used (use as few vehicles as possible before optimising routes)
  3. Minimise cost (weighted sum of travel time, distance, and any soft penalties)
The default objective is equivalent to { "priorities": ["serve_jobs", "minimize_vehicles", "minimize_cost"] }. Omit the objective block entirely to use these defaults.
Every response includes an itemised estimated_cost breakdown (travel, waiting, overtime, unassigned, etc.) so you never need to recompute the objective yourself.

Relations

Relations express ordering and grouping constraints between jobs using a single relations array. Each relation is a tagged object with a type.
A relation references jobs either explicitly via job_ids, or by tag via the separate group field — never both. An ordered relation with group set orders all jobs carrying that tag relative to each other, leaving order within the group free.