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.
{
  "id": "delivery-1",
  "location": { "coordinate": [4.7005, 50.8798] },
  "service_duration_s": 300,
  "time_windows": [
    {
      "from": "2026-04-01T09:00:00+02:00",
      "to":   "2026-04-01T12:00:00+02:00"
    }
  ],
  "demand": { "weight": 10 },
  "skills": [{ "name": "refrigerated" }]
}
  • 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.
{
  "id": "truck-1",
  "capacity": { "weight": 1000, "volume": 50 },
  "skills": ["refrigerated"],
  "limits": {
    "max_distance_m": 250000,
    "max_drive_time_s": 28800
  },
  "shifts": [
    {
      "from": "2026-04-01T08:00:00+02:00",
      "to":   "2026-04-01T17:00:00+02:00",
      "start": { "coordinate": [4.3517, 50.8503] },
      "end":   { "coordinate": [4.3517, 50.8503] }
    }
  ]
}
  • 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_tasks.
  • 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.
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:
{
  "options": {
    "runtime": {
      "matrix": {
        "distances": [
          [0, 1500, 3200],
          [1400, 0, 2100],
          [3100, 2000, 0]
        ],
        "durations": [
          [0, 600, 1200],
          [550, 0, 900],
          [1150, 850, 0]
        ]
      }
    }
  }
}
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):
ConstraintDescription
CapacityVehicle load never exceeds capacity on any named dimension
Time windowsJobs served within their allowed time windows
SkillsVehicle must have all skills required by the job
Vehicle rangeMaximum distance or drive time per route
SequenceJob A served before job B on the same route (ordered relation)
Same resourceA set of jobs served by the same vehicle across shifts (same_resource relation)
Eligible vehiclesJob may only be served by vehicles in eligible_vehicles.allowed, never by vehicles in excluded
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.
{
  "objective": {
    "priorities": ["serve_jobs", "minimize_vehicles", "minimize_cost"],
    "costs": {
      "per_travel_hour": 50
    }
  }
}
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.
{
  "relations": [
    {
      "type": "ordered",
      "job_ids": ["pickup-A", "delivery-A", "delivery-B"]
    },
    {
      "type": "same_resource",
      "job_ids": ["monday-visit", "tuesday-followup"]
    }
  ]
}
TypeMeaningStatus
orderedJobs appear in listed order on one routeAvailable
consecutiveJobs appear consecutively (no stops between them)Available
same_resourceJobs served by the same vehicle (across shifts / days)Available
same_routeJobs on the same route in the same shiftAvailable
same_dayJobs on the same calendar dayComing soon
synchronizedTwo vehicles meet at the same location within max_wait_sComing soon
job_ids can reference a job id or a tag (jobs sharing a tag form a group). An ordered relation over tags orders the groups relative to each other while leaving order within each group free.