> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solvice.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Run result

> Fetch the plan of a finished run

<Info>
  **V3 is in beta.** General availability (GA) is planned for January 2027.
</Info>


## OpenAPI

````yaml vrp-v3-runs GET /v3/routing/runs/{id}/result
openapi: 3.1.0
info:
  title: 'Solvice Routing API: async runs'
  description: >-
    Run a routing problem in the background: submit it, poll the run, then fetch
    the plan. The run takes the same request body as `POST /v3/routing/solve`
    and its result is the same `SolveResponse`. Served by the API gateway at
    `https://api.solvice.io`, not by the solver.
  contact:
    name: Solvice
    url: https://www.solvice.io
  license:
    name: Proprietary
  version: 3.0.0
servers:
  - url: https://api.solvice.io
    description: Production — Solvice API gateway
security:
  - apiKey: []
tags:
  - name: Runs
    description: Async routing runs
paths:
  /v3/routing/runs/{id}/result:
    get:
      tags:
        - Runs
      summary: Get the plan of a run
      description: >-
        Returns the plan of a `succeeded` run: the same `SolveResponse` that
        `POST /v3/routing/solve` returns. While the run is `queued` or `running`
        this is a `409` with `run_not_finished`; a `failed` or `cancelled` run
        has no plan (`409`, `no_result`).
      operationId: getRoutingRunResult
      parameters:
        - name: id
          in: path
          required: true
          description: The run id returned by `POST /v3/routing/runs`.
          schema:
            type: string
            format: uuid
      responses:
        '200':
          description: The plan.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SolveResponse'
        '400':
          description: '`id` is not a UUID. Body: `{"error": "Invalid UUID string: …"}`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                error: 'Invalid UUID string: not-a-uuid'
        '401':
          description: >-
            Missing or invalid API key. Returned by the API gateway, so it does
            not use the `ErrorBody` shape and can have an empty body. Branch on
            the HTTP status.
        '404':
          description: >-
            No run with this id on your account. Runs of other accounts are also
            `404`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                message: 'not_found: routing run d28568b1-34cc-4f89-b10b-dc24b26a8275'
                error: GATEWAY_ERROR
        '409':
          description: >-
            The run has no plan to return. `message` starts with
            `run_not_finished` while the run is `queued` or `running`, and with
            `no_result` when it `failed` or was `cancelled`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/GatewayError'
              example:
                message: >-
                  run_not_finished: run d28568b1-34cc-4f89-b10b-dc24b26a8275 is
                  queued
                error: GATEWAY_ERROR
components:
  schemas:
    SolveResponse:
      type: object
      description: |-
        The result of `POST /v3/routing/solve` and `POST /v3/routing/evaluate`:
        one shape for a plan the solver built and a plan it was given to score.
      required:
        - summary
        - routes
        - plan
        - unassigned
      properties:
        plan:
          $ref: '#/components/schemas/Plan'
          description: >-
            The plan these routes follow, in the request's vocabulary: valid
            input

            to evaluate, suggest or a warm-started solve as it stands.
        routes:
          type: array
          items:
            $ref: '#/components/schemas/Route'
          description: One entry per non-empty route.
        summary:
          $ref: '#/components/schemas/Summary'
          description: Aggregate statistics for the solve run.
        unassigned:
          type: array
          items:
            $ref: '#/components/schemas/Unassigned'
          description: Tasks that could not be feasibly assigned.
      example:
        plan:
          routes:
            - shift: mon
              stops:
                - id: job-1
                  type: job
                - id: job-2
                  type: job
              vehicle: v1
        routes:
          - distance_m: 8450
            load_peak:
              weight: 55
            shift: mon
            stops:
              - arrival: '2026-07-01T08:00:00+02:00'
                departure: '2026-07-01T08:00:00+02:00'
                depot: gent
                load_after:
                  weight: 0
                location:
                  - 3.7174
                  - 51.0543
                service_s: 0
                type: start
              - arrival: '2026-07-01T08:10:00+02:00'
                departure: '2026-07-01T09:05:00+02:00'
                distance_m: 2600
                id: job-1
                lateness_s: 0
                load_after:
                  weight: 20
                location:
                  - 3.725
                  - 51.05
                service_s: 300
                travel_s: 600
                type: job
                wait_s: 3000
              - arrival: '2026-07-01T09:13:00+02:00'
                departure: '2026-07-01T09:23:00+02:00'
                distance_m: 2350
                id: job-2
                lateness_s: 0
                load_after:
                  weight: 55
                location:
                  - 3.71
                  - 51.06
                service_s: 600
                travel_s: 480
                type: job
                wait_s: 0
              - arrival: '2026-07-01T09:38:00+02:00'
                departure: '2026-07-01T09:38:00+02:00'
                depot: gent
                distance_m: 3500
                load_after:
                  weight: 55
                location:
                  - 3.7174
                  - 51.0543
                service_s: 0
                travel_s: 900
                type: end
            time:
              break_s: 0
              depot_s: 0
              overtime_s: 0
              service_s: 900
              span_s: 5880
              travel_s: 1980
              wait_s: 3000
            vehicle: v1
        summary:
          distance_m: 8450
          score:
            components:
              depot_visits: 0
              distance: 1.69
              drop_fees: 0
              fixed: 0
              grouping: 0
              lateness: 0
              other: 0
              overtime: 0
              tag_preference: 0
              target: 0
              time: 57.1536
              waiting: 0
              window_choice: 0
            cost: 58.8436
            currency: EUR
            unserved_priority: 0
            violations: 0
          shifts_used: 1
          tasks:
            served: 2
            unserved: 0
            unserved_required: 0
          time:
            break_s: 0
            depot_s: 0
            overtime_s: 0
            service_s: 900
            span_s: 5880
            travel_s: 1980
            wait_s: 3000
          timings:
            search_ms: 100
            total_ms: 142
          vehicles_used: 1
        unassigned: []
    GatewayError:
      type: object
      description: >-
        The gateway's own error answer on `/v3/routing/runs*`, not the
        `ErrorBody` shape. `message` starts with a code (`not_found`,
        `run_not_finished`, `no_result`), a colon and a sentence; branch on the
        HTTP status and that code.
      required:
        - error
      properties:
        error:
          type: string
          description: '`GATEWAY_ERROR`, or the reason for a malformed `id`.'
          example: GATEWAY_ERROR
        message:
          type: string
          description: Absent on a malformed `id`.
          example: 'not_found: routing run d28568b1-34cc-4f89-b10b-dc24b26a8275'
    Plan:
      type: object
      description: >-
        A plan: which stops each vehicle shift serves, in order. A result's
        `plan`

        has exactly this shape and goes back into evaluate, suggest or a

        warm-started solve unchanged.
      required:
        - routes
      properties:
        routes:
          type: array
          items:
            $ref: '#/components/schemas/PlanRoute'
          description: One entry per vehicle shift that serves something.
      additionalProperties: false
    Route:
      type: object
      description: A single vehicle's route.
      required:
        - vehicle
        - shift
        - distance_m
        - time
        - stops
      properties:
        distance_m:
          type: integer
          format: int64
          description: Total route distance, in metres.
          example: 8450
        load_peak:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/BTreeMap'
              description: Peak load reached on the route, by named dimension.
          description: Peak load reached on the route, by named dimension.
        polyline:
          type:
            - string
            - 'null'
          description: >-
            Road geometry for this route as an [encoded polyline] at precision 5

            (~1.1 m), ready to hand to a map library. Present only when

            `options.polylines` was set, and absent for a route whose geometry
            the

            routing engine could not produce.


            Traced with this vehicle's `profile` at the solve's departure time,
            so

            it is the same road path the plan was costed on — not a generic car

            route. It is a decoration, though: `distance_m` and `time` come

            from the solver's matrix and are authoritative if the two ever
            disagree.


            [encoded polyline]:
            https://developers.google.com/maps/documentation/utilities/polylinealgorithm
          example: _p~iF~ps|U_ulLnnqC_mqNvxq`@
        shift:
          type: string
          description: The shift id (`vehicles[].shifts[].id`) this route runs on.
          example: mon
        stops:
          type: array
          items:
            $ref: '#/components/schemas/StopOutput'
          description: Ordered stops, including depot bookends.
        time:
          $ref: '#/components/schemas/TimeTotals'
          description: |-
            Where this route's time goes. `time.span_s` is what the route's
            `costs.per_route_hour` is charged on: the shift's rate, else its
            vehicle's, else `objective.costs.per_route_hour`.
        vehicle:
          type: string
          description: The vehicle id (`vehicle.id` from the request) serving this route.
        violations:
          type: array
          items:
            $ref: '#/components/schemas/Violation'
          description: >-
            Route-level constraint violations (e.g. `max_distance`,
            `max_duration`,

            or `unreachable` for a leg whose destination is not a job stop — the

            return to the end depot, or a leg into a reload).

            Only populated by `POST /v3/routing/evaluate`; absent on solve
            responses.
      example:
        distance_m: 8450
        load_peak:
          weight: 55
        shift: mon
        stops:
          - arrival: '2026-07-01T08:00:00+02:00'
            departure: '2026-07-01T08:00:00+02:00'
            depot: gent
            load_after:
              weight: 0
            location:
              - 3.7174
              - 51.0543
            service_s: 0
            type: start
          - arrival: '2026-07-01T08:10:00+02:00'
            departure: '2026-07-01T09:05:00+02:00'
            distance_m: 2600
            id: job-1
            lateness_s: 0
            load_after:
              weight: 20
            location:
              - 3.725
              - 51.05
            service_s: 300
            travel_s: 600
            type: job
            wait_s: 3000
          - arrival: '2026-07-01T09:13:00+02:00'
            departure: '2026-07-01T09:23:00+02:00'
            distance_m: 2350
            id: job-2
            lateness_s: 0
            load_after:
              weight: 55
            location:
              - 3.71
              - 51.06
            service_s: 600
            travel_s: 480
            type: job
            wait_s: 0
          - arrival: '2026-07-01T09:38:00+02:00'
            departure: '2026-07-01T09:38:00+02:00'
            depot: gent
            distance_m: 3500
            load_after:
              weight: 55
            location:
              - 3.7174
              - 51.0543
            service_s: 0
            travel_s: 900
            type: end
        time:
          break_s: 0
          depot_s: 0
          overtime_s: 0
          service_s: 900
          span_s: 5880
          travel_s: 1980
          wait_s: 3000
        vehicle: v1
    Summary:
      type: object
      description: 'The plan in numbers: its score, what it serves and what it takes.'
      required:
        - score
        - tasks
        - vehicles_used
        - shifts_used
        - distance_m
        - time
        - timings
      properties:
        distance_m:
          type: integer
          format: int64
          description: Sum of all route distances, in metres.
          example: 8450
        score:
          $ref: '#/components/schemas/Score'
          description: >-
            How good the plan is. On `/solve`, `score.violations` is always 0;
            on

            `/evaluate` it counts the constraints the given plan breaks.
        shifts_used:
          type: integer
          format: int32
          description: 'Routes with at least one task stop: one per used shift.'
          example: 1
          minimum: 0
        tasks:
          $ref: '#/components/schemas/TaskCounts'
          description: Tasks served and left out.
        time:
          $ref: '#/components/schemas/TimeTotals'
          description: Where the fleet's time goes, summed over routes.
        timings:
          $ref: '#/components/schemas/Timings'
          description: Where the request's time went.
        travel_estimated:
          type: boolean
          description: >-
            `true` when Solvice Maps could not be reached and the plan was
            costed

            on estimated travel: straight-line distance × a detour factor, at a

            typical speed for the profile. No one-way streets or traffic, so it

            can be tens of percent off: the plan, `unassigned[].reasons` and

            `score.violations` hold only against it, and no `routes[].polyline`
            is

            returned. Solve again once Maps is back if the plan must hold on the

            road; `options.travel_fallback: "fail"` returns the error instead.

            Absent when travel is road-routed.
        vehicles_used:
          type: integer
          format: int32
          description: Distinct vehicles with at least one route.
          example: 1
          minimum: 0
      example:
        distance_m: 8450
        score:
          components:
            depot_visits: 0
            distance: 1.69
            drop_fees: 0
            fixed: 0
            grouping: 0
            lateness: 0
            other: 0
            overtime: 0
            tag_preference: 0
            target: 0
            time: 57.1536
            waiting: 0
            window_choice: 0
          cost: 58.8436
          currency: EUR
          unserved_priority: 0
          violations: 0
        shifts_used: 1
        tasks:
          served: 2
          unserved: 0
          unserved_required: 0
        time:
          break_s: 0
          depot_s: 0
          overtime_s: 0
          service_s: 900
          span_s: 5880
          travel_s: 1980
          wait_s: 3000
        timings:
          search_ms: 100
          total_ms: 142
        vehicles_used: 1
    Unassigned:
      type: object
      description: A job the solver could not assign to any vehicle.
      required:
        - job_id
        - reasons
        - relaxations
      properties:
        category:
          $ref: '#/components/schemas/UnassignedCategory'
          description: Which kind of "unassigned" this is.
        job_id:
          type: string
          description: The unassigned job id.
          example: job-2
        reasons:
          type: array
          items:
            $ref: '#/components/schemas/UnassignedReason'
          description: Structured reasons the job could not be served.
        relaxations:
          type: array
          items:
            $ref: '#/components/schemas/Relaxation'
          description: |-
            Best-effort, actionable relaxation suggestions. Empty when no simple
            relaxation exists (e.g. a skills mismatch).
      example:
        category: blocked
        job_id: job-2
        reasons:
          - code: TIME_WINDOW_VIOLATED
            message: No vehicle can reach this job within its time window.
        relaxations:
          - amount: 900
            field: /jobs/job-2/time_windows
            op: extend_time_window
            suggestion: Extend a time window by 900s (~15 min).
            unit: s
    PlanRoute:
      type: object
      description: >-
        One vehicle shift's route: every trip of the shift, split by `reload`
        stops.
      required:
        - vehicle
        - shift
        - stops
      properties:
        locked_count:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            On solve, the first `locked_count` stops stay where they are
            (already

            dispatched). Counts every listed stop. Cannot be combined with a

            `reload` stop, and must not exceed the route's stop count — both are

            validated on every endpoint that takes a plan. Otherwise inert on

            evaluate. On suggest, no insertion lands before them.
          example: 1
          minimum: 0
        shift:
          type: string
          description: Shift id, within that vehicle.
        stops:
          type: array
          items:
            $ref: '#/components/schemas/PlanStop'
          description: Stops in visiting order.
        vehicle:
          type: string
          description: Vehicle id.
      additionalProperties: false
      example:
        shift: mon
        stops:
          - id: boiler-17
            type: job
        vehicle: van-3
    BTreeMap:
      type: object
      description: >-
        Named capacity/demand/load dimensions, e.g. `{"weight": 30, "volume":
        2}`. Keys are user-chosen dimension names; values are integer
        quantities. Order-independent and self-documenting.
      additionalProperties:
        type: integer
        format: int32
      propertyNames:
        type: string
      example:
        volume: 2
        weight: 20
    StopOutput:
      type: object
      description: A single stop within a route.
      required:
        - type
      properties:
        arrival:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            Physical arrival time (RFC 3339), before any waiting; the service

            start is `arrival + wait_s`. Every stop time is rendered in the UTC

            offset of the route's shift `from` (`Z` when that `from` is UTC or
            has

            no offset): a `+02:00` shift reports `2026-07-01T08:10:00+02:00`,
            the

            same instant as `2026-07-01T06:10:00Z`.
          example: '2026-07-01T08:10:00+02:00'
        departure:
          type:
            - string
            - 'null'
          format: date-time
          description: Departure time (RFC 3339, in the offset of `arrival`).
          example: '2026-07-01T09:05:00+02:00'
        depot:
          type:
            - string
            - 'null'
          description: >-
            The `depots[].id` of this stop: on a `start`/`end` stop whose shift
            end

            names a depot, and on every `reload` stop. Absent on a `location` or

            open end and on task and break stops.
          example: gent
        distance_m:
          type:
            - integer
            - 'null'
          format: int32
          description: Travel distance from the previous stop, in metres.
          example: 2600
        hold_s:
          type:
            - integer
            - 'null'
          format: int32
          description: |-
            The part of `wait_s` spent holding for a `synchronized` or
            `time_lag` partner on another vehicle, beyond any wait the time
            window already imposed. Present on task stops only when non-zero.
          example: 0
        id:
          type:
            - string
            - 'null'
          description: >-
            Stop id: the job id on a `job` stop, the leg's stop id on

            `pickup`/`delivery` (its own `id`, else `{shipment}:pickup` /

            `{shipment}:delivery`). Absent on start, end, break and reload
            stops.
          example: job-1
        lateness_s:
          type:
            - integer
            - 'null'
          format: int32
          description: |-
            Seconds late beyond the latest allowed arrival (`0` when on time).
            Measures the hard time window only; a soft target is reported in
            `target_lateness_s`.
          example: 0
        load_after:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/BTreeMap'
              description: Cumulative load carried after this stop, by named dimension.
          description: Cumulative load carried after this stop, by named dimension.
        location:
          type:
            - array
            - 'null'
          items:
            type: number
            format: double
          description: |-
            Stop location `[longitude, latitude]` (GeoJSON order). Absent on
            every `break` stop, including a break with a pinned location, and on
            `start`/`end` stops for a genuinely open leg (no configured depot
            coordinate for that end of the shift). A virtual (location-less) job
            has no coordinate of its own and reports its nearest located
            neighbor's instead, so it is absent only when the whole route is
            virtual with open depot ends.
          example:
            - 3.725
            - 51.05
          maxItems: 2
          minItems: 2
        service_s:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            On-site service time at this stop, in seconds.


            The **effective** time, not the nominal `service_duration_s` from
            the

            request: on a task stop it already has the serving vehicle's

            `service_factor` applied. The timeline reconciles as

            `departure - arrival - wait_s == service_s` only when the stop pays
            no

            setup time; with `setup_duration_s` set, the difference is larger by

            the (unscaled) setup seconds. Depot, reload, and break stops report

            their own nominal handling/break duration, which `service_factor`

            never scales.


            On `start`/`end`: the depot handling time applied there (0 on an

            ignored leg); absent on an open end.
          example: 300
        service_start:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            When service starts (RFC 3339, in the offset of `arrival`): after
            the

            arrival, any windowed

            break taken on arrival there, and the wait. On task and reload
            stops;

            like `arrival`, absent on a request without time windows.
          example: '2026-07-01T09:00:00+02:00'
        snapped_location:
          type:
            - array
            - 'null'
          items:
            type: number
            format: double
          description: The same point snapped to the routable graph, when available.
          maxItems: 2
          minItems: 2
        target_lateness_s:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            Seconds past this task's `target.at`, measured at the stop's arrival

            or departure per `target.on`; `0` when met. Present only on a task

            stop carrying a target. A shipment's target is measured

            on its delivery leg, so it appears on the `:delivery` stop and never
            on

            the `:pickup` stop.
          example: 0
        travel_s:
          type:
            - integer
            - 'null'
          format: int32
          description: Travel time from the previous stop, in seconds.
          example: 600
        type:
          $ref: '#/components/schemas/StopType'
          description: What kind of stop this is.
        violations:
          type: array
          items:
            $ref: '#/components/schemas/Violation'
          description: >-
            Constraint violations detected at this stop. Only populated by

            `POST /v3/routing/evaluate` (imported solutions may be infeasible);
            a

            solve response never emits violations, so this is absent there.
        wait_s:
          type:
            - integer
            - 'null'
          format: int32
          description: |-
            Seconds spent waiting here before service: for the time window to
            open, and for any cross-route hold (`hold_s`, included in this
            figure).
          example: 3000
      example:
        arrival: '2026-07-01T08:10:00+02:00'
        departure: '2026-07-01T09:05:00+02:00'
        distance_m: 2600
        id: job-1
        lateness_s: 0
        load_after:
          weight: 20
        location:
          - 3.725
          - 51.05
        service_s: 300
        travel_s: 600
        type: job
        wait_s: 3000
    TimeTotals:
      type: object
      description: |-
        Where a route's time goes, in seconds. On the summary: the sum over
        routes.

        `span_s` is the wall-clock span, from the start stop's `arrival` to the
        end stop's `departure`; it is what `per_route_hour` is charged on. The
        other fields break it down. They do not sum to `span_s` exactly: two
        parts of the span have no field of their own, setup time
        (`setup_duration_s`) and the idle before a windowed break's window opens
        (`wait_s` is measured after that break). And a `fixed` break that begins
        while the vehicle is driving overlaps that drive: the overlap is in both
        `travel_s` and `break_s`, so on such a route the parts can exceed
        `span_s`.
      required:
        - span_s
        - travel_s
        - service_s
        - depot_s
        - wait_s
        - break_s
        - overtime_s
      properties:
        break_s:
          type: integer
          format: int64
          description: Time on driver breaks.
        depot_s:
          type: integer
          format: int64
          description: Handling time at start, end and reload stops.
        overtime_s:
          type: integer
          format: int64
          description: |-
            The part of the span after the shift's `to` (possible only with
            `max_overtime_s`).
        service_s:
          type: integer
          format: int64
          description: On-site service time at job, pickup and delivery stops.
        span_s:
          type: integer
          format: int64
          description: |-
            Wall-clock span: travel, service, setup, depot handling, waiting and
            breaks.
        travel_s:
          type: integer
          format: int64
          description: 'Driving time: the sum of the stops'' `travel_s`.'
        wait_s:
          type: integer
          format: int64
          description: Waiting before service, cross-route holds included.
      example:
        break_s: 0
        depot_s: 0
        overtime_s: 0
        service_s: 900
        span_s: 5880
        travel_s: 1980
        wait_s: 3000
    Violation:
      type: object
      description: >-
        A single constraint violation detected while evaluating an imported
        solution.


        Reported on stops (`routes[].stops[].violations`) and on routes

        (`routes[].violations`) in the `POST /v3/routing/evaluate` response.
      required:
        - type
        - message
      properties:
        message:
          type: string
          description: Human-readable description of what was violated.
          example: Cumulative load 30 exceeds vehicle capacity 15 (dimension weight)
        type:
          type: string
          description: >-
            Machine-readable violation type: `time_window`, `capacity`,
            `skills`,

            `tags`, `first_job`, `unreachable`, `commitment`, `eligibility`,

            `same_vehicle`, `same_day`, `same_route`, `synchronized`,
            `time_lag`,

            `max_distance`, `max_duration`, `shift_end`, `sequence`,
            `max_tasks`,

            `break`, `shipment`, `multi_trip`, `period_limit` (a
            `limits.periods`

            cap, reported once per period on the route of its first used shift),

            `quota` (a `quotas[]` cap, reported the same way), or `infeasible`

            (the insertion check refused a stop without naming a constraint; not

            expected in practice). `max_tasks`, `break`, `multi_trip`,

            `period_limit` and `quota` are route-level; `sequence` and

            `shipment` are on the stop.


            Deliberately an open string rather than an enum: stop-level types
            come

            from the active constraint set, so a new constraint can add one
            without

            a breaking schema change. Match on the values you handle and treat

            unknown ones as generic violations.
          example: capacity
      example:
        message: Cumulative load 30 exceeds vehicle capacity 15 (dimension weight)
        type: capacity
    Score:
      type: object
      description: |-
        How good a plan is. Plans compare in order: fewer `violations` first,
        then less `unserved_priority`, then less `cost`.
      required:
        - violations
        - unserved_priority
        - cost
        - components
      properties:
        components:
          $ref: '#/components/schemas/ScoreComponents'
          description: The money of each objective term.
        cost:
          type: number
          format: double
          description: 'Total cost, in the objective''s currency: the sum of `components`.'
          example: 58.8436
        currency:
          type:
            - string
            - 'null'
          description: Informational currency label, echoed from `objective.currency`.
          example: EUR
        unserved_priority:
          type: integer
          format: int64
          description: |-
            Summed `priority` of the required tasks left unassigned (a task that
            priced a `drop_fee` counts in `components.drop_fees` instead).
          example: 0
        violations:
          type: integer
          format: int32
          description: Hard-constraint violations. Always `0` on a solve result.
          example: 0
          minimum: 0
      example:
        components:
          depot_visits: 0
          distance: 1.69
          drop_fees: 0
          fixed: 0
          grouping: 0
          lateness: 0
          other: 0
          overtime: 0
          tag_preference: 0
          target: 0
          time: 57.1536
          waiting: 0
          window_choice: 0
        cost: 58.8436
        currency: EUR
        unserved_priority: 0
        violations: 0
    TaskCounts:
      type: object
      description: |-
        How many tasks the plan serves. A job is one task; a shipment (pickup
        plus delivery) is one task.
      required:
        - served
        - unserved
        - unserved_required
      properties:
        served:
          type: integer
          format: int32
          description: Tasks on a route.
          minimum: 0
        unserved:
          type: integer
          format: int32
          description: 'Tasks on no route: the length of `unassigned`.'
          minimum: 0
        unserved_required:
          type: integer
          format: int32
          description: |-
            The unserved tasks that carry no `drop_fee`: tasks the plan was
            required to serve and did not.
          minimum: 0
      example:
        served: 2
        unserved: 0
        unserved_required: 0
    Timings:
      type: object
      description: Where the request's wall-clock time went, in milliseconds.
      required:
        - total_ms
      properties:
        search_ms:
          type:
            - integer
            - 'null'
          format: int64
          description: Time spent in the search. Absent on `/evaluate`, which runs none.
          minimum: 0
        total_ms:
          type: integer
          format: int64
          description: |-
            From the request's arrival to the end of the search (of the scoring,
            on `/evaluate`): fetching travel times and waiting for capacity
            included, building the response not.
          minimum: 0
      example:
        search_ms: 100
        total_ms: 142
    UnassignedCategory:
      type: string
      description: Which kind of "unassigned" a task is.
      enum:
        - impossible
        - blocked
        - priced_out
        - search_limit
      example: priced_out
    UnassignedReason:
      type: object
      description: A machine-readable reason a task could not be assigned.
      required:
        - code
        - message
      properties:
        code:
          type: string
          description: >-
            Stable machine code. Closed set of eleven values — exactly one of:

            `SOLVER_LIMIT` (a feasible slot existed but the time budget ran
            out),

            `CAPACITY_EXCEEDED`, `TIME_WINDOW_VIOLATED`,
            `CAPACITY_AND_TIME_WINDOW`,

            `SKILLS_MISMATCH`, `TAG_RESTRICTED`, `COMMITMENT_BLOCKED`,

            `VEHICLE_EXCLUDED`, `VEHICLE_RANGE_EXCEEDED`,
            `UNREACHABLE_LOCATION`,

            or `ALL_ROUTES_BLOCKED` (a mix no single code describes).

            `UNREACHABLE_LOCATION` outranks the others when it applies:

            a coordinate the routing engine cannot reach is a fact about the
            input,

            not about the fleet. Treat an unrecognised value as

            `ALL_ROUTES_BLOCKED`.
          example: TIME_WINDOW_VIOLATED
        message:
          type: string
          description: Human-readable explanation.
          example: No vehicle can reach this job within its time window.
      example:
        code: TIME_WINDOW_VIOLATED
        message: No vehicle can reach this job within its time window.
    Relaxation:
      type: object
      description: >-
        A best-effort, actionable suggestion for relaxing the problem so a task
        can be

        assigned — derived from the smallest constraint relaxation the solver
        found.
      required:
        - field
        - op
        - amount
        - unit
        - suggestion
      properties:
        amount:
          type: integer
          format: int64
          description: Magnitude of the change, expressed in `unit`.
          example: 900
        field:
          type: string
          description: >-
            Names the task and the field to change. For a job:
            `/jobs/{id}/pickup`

            (`/jobs/{id}/delivery` for a job with only a `delivery`) or

            `/jobs/{id}/time_windows`. For a shipment: `/shipments/{id}/load` or

            `/shipments/{id}/pickup/time_windows` (either leg's window may be
            the

            one to extend). `{id}` is the task id, the same value as `job_id`.
            It is

            a label, not a JSON Pointer into the request body: it uses the id,
            not

            the array index, and has no `/problem` prefix.
          example: /jobs/job-2/time_windows
        op:
          $ref: '#/components/schemas/RelaxationOp'
          description: The kind of change suggested.
        suggestion:
          type: string
          description: Human-readable suggestion.
          example: Extend a time window by 900s (~15 min).
        unit:
          type: string
          description: |-
            Unit of `amount`: `"s"` (seconds, for `extend_time_window`) or
            `"load"` (demand units, for `reduce_demand`).
          example: s
      example:
        amount: 900
        field: /jobs/job-2/time_windows
        op: extend_time_window
        suggestion: Extend a time window by 900s (~15 min).
        unit: s
    PlanStop:
      oneOf:
        - type: object
          title: Job
          description: A job, by its id.
          required:
            - id
            - type
          properties:
            id:
              type: string
              description: Job id.
              example: boiler-17
            type:
              type: string
              enum:
                - job
        - type: object
          title: Pickup
          description: A shipment's pickup leg.
          required:
            - id
            - type
          properties:
            id:
              type: string
              description: 'The leg''s stop id: its own `id`, else `{shipment}:pickup`.'
              example: parts-9:pickup
            type:
              type: string
              enum:
                - pickup
        - type: object
          title: Delivery
          description: A shipment's delivery leg.
          required:
            - id
            - type
          properties:
            id:
              type: string
              description: 'The leg''s stop id: its own `id`, else `{shipment}:delivery`.'
              example: parts-9:delivery
            type:
              type: string
              enum:
                - delivery
        - type: object
          title: Reload
          description: 'A reload at a depot: the next trip starts there.'
          required:
            - depot
            - type
          properties:
            depot:
              type: string
              description: A depot id from the shift's `reloads`.
              example: gent
            type:
              type: string
              enum:
                - reload
      description: |-
        One stop of a plan route. Start, end and breaks are placed by the solver
        and are not listed.
      example:
        id: parts-9:pickup
        type: pickup
    StopType:
      type: string
      description: |-
        The kind of a stop in a route.

        Every route has one `start` and one `end`. A served job is `job`, and a
        shipment's legs are `pickup` and `delivery`. A driver break is `break`,
        and a mid-shift reload at a depot is `reload`.
      enum:
        - start
        - job
        - pickup
        - delivery
        - break
        - reload
        - end
      example: job
    ScoreComponents:
      type: object
      description: |-
        The money of each objective term, in the objective's currency. The
        components always sum to `score.cost` exactly: every term the solver
        charges lands in exactly one of them.
      required:
        - fixed
        - time
        - distance
        - waiting
        - overtime
        - lateness
        - window_choice
        - target
        - tag_preference
        - depot_visits
        - grouping
        - drop_fees
        - other
      properties:
        depot_visits:
          type: number
          format: double
          description: >-
            Cost of reload visits, in currency units
            (`depots[].cost_per_visit`).
        distance:
          type: number
          format: double
          description: |-
            Distance cost, in currency units: each route's distance priced at
            its `costs.per_travel_km` (shift, vehicle or fleet).
        drop_fees:
          type: number
          format: double
          description: >-
            The summed `drop_fee` of the tasks left unassigned, in currency
            units.
        fixed:
          type: number
          format: double
          description: |-
            Vehicle cost, in currency units: `costs.fixed` once per used shift,
            at the shift's, vehicle's or fleet's rate.
        grouping:
          type: number
          format: double
          description: |-
            Cost of splitting close tasks across routes, in currency units
            (`objective.grouping`).
        lateness:
          type: number
          format: double
          description: |-
            Cost of priced lateness past a time window, in currency units
            (`objective.per_late_hour` or `time_windows[].per_late_hour`).
        other:
          type: number
          format: double
          description: |-
            Everything else the solver charges, in currency units: vehicle
            preferences (`preferences[].violation_cost`) and the
            non-preferred-date cost.
        overtime:
          type: number
          format: double
          description: |-
            Cost of work past a soft shift end, in currency units: priced at the
            route's `costs.per_overtime_hour`.
        tag_preference:
          type: number
          format: double
          description: |-
            Cost of serving tasks outside a vehicle's `preferred_tags`, in
            currency units.
        target:
          type: number
          format: double
          description: |-
            Cost of missing tasks' `target` times, in currency units
            (`target.per_late_hour`).
        time:
          type: number
          format: double
          description: |-
            Time cost, in currency units: each route's span priced at its
            `costs.per_route_hour` (shift, vehicle or fleet).
        waiting:
          type: number
          format: double
          description: |-
            Cost of waiting for time windows to open, in currency units: each
            route's wait priced at its `costs.per_wait_hour`.
        window_choice:
          type: number
          format: double
          description: |-
            The price of the time window each task was served in, in currency
            units (`time_windows[].cost`).
      example:
        depot_visits: 0
        distance: 1.69
        drop_fees: 0
        fixed: 0
        grouping: 0
        lateness: 0
        other: 0
        overtime: 0
        tag_preference: 0
        target: 0
        time: 57.1536
        waiting: 0
        window_choice: 0
    RelaxationOp:
      type: string
      description: The kind of change a relaxation suggests.
      enum:
        - reduce_demand
        - extend_time_window
      example: extend_time_window
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: Authorization

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.