> ## 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.

# Sync Solve VRP

> Synchronous solve operation for low latency results



## OpenAPI

````yaml vrp POST /v2/vrp/sync/solve
openapi: 3.1.0
info:
  title: Solvice Routing Solver
  description: >-
    Optimizes vehicle routes to minimize distance, time, or fleet size while
    respecting capacity, time windows, skills, and custom constraints.
  contact:
    name: Christophe Van Huele
  license:
    name: ''
  version: 3.0.0
servers: []
security: []
tags:
  - name: Routing
    description: Vehicle routing optimization
  - name: Legacy
    description: Solver2-compatible endpoints (V2)
  - name: Operations
    description: Health and diagnostics
paths:
  /v2/vrp/sync/solve:
    post:
      tags:
        - Legacy
      summary: Solve a routing problem (solver2-compatible V2 format)
      operationId: v2_solve_handler
      parameters:
        - name: millis
          in: query
          description: Time limit override in milliseconds
          required: false
          schema:
            type: integer
            format: int64
            minimum: 0
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/OnRouteRequest'
        required: true
      responses:
        '200':
          description: Solution found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/OnRouteResponse'
        '400':
          description: Validation error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '415':
          description: Request `Content-Type` is not `application/json`
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '422':
          description: Request body could not be deserialized into the expected schema
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Internal error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '502':
          description: Matrix fetch error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: >-
            Service unavailable (solver queue full or matrix provider circuit
            open)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  schemas:
    OnRouteRequest:
      type: object
      description: |-
        Top-level request body for `POST /v2/vrp/sync/solve`.

        Mirrors the solver2 OnRoute API. The mapping to V3 is handled by
        [`crate::api::v2_compat::map_v2_request`].
      required:
        - resources
        - jobs
      properties:
        jobs:
          type: array
          items:
            $ref: '#/components/schemas/V2Job'
          description: Jobs to be assigned and sequenced.
        options:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Options'
              description: Solver options; currently only `solvingTime` is honoured.
        relations:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/V2Relation'
          description: Optional ordering constraints between jobs.
        resources:
          type: array
          items:
            $ref: '#/components/schemas/V2Resource'
          description: Fleet of vehicles (called "resources" in V2).
    OnRouteResponse:
      type: object
      description: >-
        Top-level response body for `POST /v2/vrp/sync/solve`.


        Field set mirrors solver2's `OnRouteResponse` Kotlin DTO. All optional

        fields are omitted from the JSON when `None`, so adding them is
        wire-safe

        for existing clients.
      required:
        - trips
      properties:
        id:
          type:
            - string
            - 'null'
          description: >-
            Solver job ID — kept for SDK wire compatibility. Sync solves emit
            `None`

            because the request has no persistent job identity.
        messages:
          type:
            - array
            - 'null'
          items:
            type: string
          description: |-
            Free-text events emitted during the solve. Empty array on success;
            reserved for future warnings.
        status:
          type:
            - string
            - 'null'
          description: >-
            Sync solves always return `Some("SOLVED")` on the 200 path;
            async/error

            paths are not exercised by this endpoint.
        totalServiceTimeInSeconds:
          type:
            - integer
            - 'null'
          format: int64
          description: Total service time across all trips in seconds.
        totalTravelDistanceInMeters:
          type:
            - integer
            - 'null'
          format: int64
          description: Total travel distance across all trips in metres.
        totalTravelTimeInSeconds:
          type:
            - integer
            - 'null'
          format: int64
          description: Total travel time across all trips in seconds.
        totalWaitTimeInSeconds:
          type:
            - integer
            - 'null'
          format: int64
          description: Total wait time across all trips in seconds.
        trips:
          type: array
          items:
            $ref: '#/components/schemas/V2Trip'
          description: One trip per vehicle that has at least one visit.
        unserved:
          type:
            - array
            - 'null'
          items:
            type: string
          description: >-
            Job names that could not be assigned; `None` when all jobs are
            assigned.
        unservedReasons:
          type:
            - object
            - 'null'
          description: Maps each unserved job name to a list of reason strings.
          additionalProperties:
            type: array
            items:
              type: string
          propertyNames:
            type: string
    ErrorResponse:
      type: object
      description: >-
        Top-level error response body.


        Flat envelope matching the Spring Boot / Spring Cloud Gateway default,

        so clients see a single shape across the Solvice platform regardless of

        whether the gateway or the routing-solver produced the error.


        Example:

        ```json

        { "message": "At least one vehicle is required", "status": "BAD_REQUEST"
        }

        ```
      required:
        - message
        - status
      properties:
        code:
          type:
            - string
            - 'null'
          description: >-
            Stable machine-readable error code (e.g. `"UNSUPPORTED_FEATURE"`,

            `"VALIDATION_ERROR"`). Populated on the V3 validation-error path;
            `None`

            for endpoints that do not set a code.
        field:
          type:
            - string
            - 'null'
          description: >-
            JSON pointer to the offending request field, when the message names
            one

            (e.g. `"/vehicles/0/profile"`). `None` when not field-specific.
        message:
          type: string
          description: Human-readable error description.
        status:
          type: string
          description: Textual HTTP status (e.g. `"BAD_REQUEST"`, `"SERVICE_UNAVAILABLE"`).
        value:
          description: The offending value, when available.
    V2Job:
      type: object
      description: V2 job (delivery or pickup stop).
      required:
        - name
      properties:
        duration:
          type:
            - integer
            - 'null'
          format: int32
          description: Service duration at the job location in seconds.
        load:
          type:
            - array
            - 'null'
          items:
            type: integer
            format: int32
          description: Demand per capacity dimension.
        location:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: Geographic location of the job; required for conversion to V3.
        name:
          type: string
          description: Unique job identifier.
        tags:
          type: array
          items:
            $ref: '#/components/schemas/V2JobTag'
          description: |-
            V2 tags attached to this job. Used by `GROUP_SEQUENCE` relations to
            resolve per-job group membership: a tag whose `name` matches a label
            in the relation's `tags` list assigns the corresponding rank.
            Tags carried by jobs that match no `GROUP_SEQUENCE` relation are
            otherwise ignored by V3.
        windows:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/V2DateWindow'
          description: Feasible service time intervals as ISO 8601 datetime string pairs.
    V2Options:
      type: object
      description: V2 solver options.
      properties:
        solvingTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Maximum solve time in seconds (converted to milliseconds for V3).
          minimum: 0
    V2Relation:
      type: object
      description: V2 job sequencing or grouping relation.
      required:
        - type
      properties:
        jobs:
          type: array
          items:
            type: string
          description: >-
            Ordered list of job names participating in this relation.

            Optional in the JSON input: `GROUP_SEQUENCE` relations historically
            omit

            it (the grouping comes from job-side metadata). `map_v2_request`
            rejects

            empty `jobs` for relation types that require it.
        resource:
          type:
            - string
            - 'null'
          description: >-
            Optional resource name the relation is pinned to (currently
            unmapped).
        tags:
          type: array
          items:
            type: string
          description: |-
            Ordered list of group labels declaring rank order for
            `GROUP_SEQUENCE` relations. Each label is matched against
            `V2Job::tags[].name` to resolve per-job group membership.
            Unused for other relation types.
        type:
          type: string
          description: >-
            Relation type; `"SEQUENCE"` maps directly to the V3 SEQUENCE
            relation.
    V2Resource:
      type: object
      description: V2 vehicle / driver resource.
      required:
        - name
      properties:
        capacity:
          type:
            - array
            - 'null'
          items:
            type: integer
            format: int32
          description: Per-dimension capacity limits.
        end:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: Fallback end location when `shifts` is absent.
        name:
          type: string
          description: Unique resource identifier used as the vehicle ID.
        shifts:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/V2Shift'
          description: >-
            Working-time shifts; the first shift's `from`/`to` becomes the V3
            time window.
        start:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: Fallback start location when `shifts` is absent.
        tags:
          type:
            - array
            - 'null'
          items:
            type: string
          description: >-
            Arbitrary skill tags (currently unmapped — V2 does not enforce
            skills).
    V2Trip:
      type: object
      description: |-
        A single vehicle's trip in the V2 response.

        `start` and `end` are synthesized depot visits (V3 does not emit depot
        stops). `workTime = serviceTime + travelTime + waitTime`, matching the
        solver2 derivation.
      required:
        - resource
        - visits
      properties:
        date:
          type:
            - string
            - 'null'
          description: |-
            Trip date (RFC 3339), derived from the route start time normalised
            to midnight UTC of that day. `None` when there are no time windows.
        departureTime:
          type:
            - string
            - 'null'
          description: |-
            Departure time from the start depot (RFC 3339). `None` when there
            are no time windows.
        distance:
          type:
            - integer
            - 'null'
          format: int64
          description: Total trip distance in metres.
        end:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Visit'
              description: Synthesized depot-arrival visit at the end of the trip.
        resource:
          type: string
          description: The resource (vehicle) name serving this trip.
        serviceTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Sum of per-stop service time on this trip in seconds.
        start:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Visit'
              description: |-
                Synthesized depot-departure visit. Carries the snapped depot
                coordinate and the route start time.
        travelTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Total trip travel time in seconds.
        visits:
          type: array
          items:
            $ref: '#/components/schemas/V2Visit'
          description: Ordered job visits on this trip.
        waitTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Sum of per-stop wait time on this trip in seconds.
        workTime:
          type:
            - integer
            - 'null'
          format: int64
          description: '`serviceTime + travelTime + waitTime`, mirroring solver2.'
    V2Location:
      type: object
      description: |-
        Geographic coordinate in V2 format (latitude/longitude order).

        Note: the V3 API uses `[longitude, latitude]` arrays; this struct is
        in the opposite field order. Conversion must swap the fields.
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: number
          format: double
          description: WGS-84 latitude in decimal degrees.
        longitude:
          type: number
          format: double
          description: WGS-84 longitude in decimal degrees.
    V2JobTag:
      type: object
      description: |-
        A single tag on a V2 job. The `hard` flag is preserved for wire
        compatibility but the V3 layer treats every tag as a soft label.
      required:
        - name
      properties:
        hard:
          type:
            - boolean
            - 'null'
          description: V2 hard/soft flag; unused by V3, kept for wire compatibility.
        name:
          type: string
          description: Tag name; matched against `V2Relation::tags` to resolve group rank.
    V2DateWindow:
      type: object
      description: A time-window constraint in V2 date format.
      required:
        - from
        - to
      properties:
        from:
          type: string
          description: Window start as an ISO 8601 datetime string.
        hard:
          type:
            - boolean
            - 'null'
          description: >-
            Whether the window is a hard constraint; currently unused by the
            mapper.
        to:
          type: string
          description: Window end as an ISO 8601 datetime string.
    V2Shift:
      type: object
      description: A single working-time shift within a V2 resource.
      required:
        - from
        - to
      properties:
        breaks:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/BreakInput'
          description: >-
            Driver-break rules attached to this shift. The V2 wire shape is
            identical

            to V3's [`BreakInput`] (tagged enum with `WINDOWED`/`DRIVE`/`DUTY`/

            `UNAVAILABILITY` variants), so we reuse the V3 type directly. When

            absent or empty, the V3 shift gets `breaks: None`.
        end:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: End location for this shift; overrides the resource-level end.
        from:
          type: string
          description: Shift start time as an ISO 8601 datetime string.
        start:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: >-
                Start location for this shift; overrides the resource-level
                start.
        to:
          type: string
          description: Shift end time as an ISO 8601 datetime string.
    V2Visit:
      type: object
      description: |-
        A single job visit within a V2 trip.

        Field names and semantics mirror solver2's `VisitDto`. `location` is the
        user-provided input coordinate; `snappedLocation` and `latlon` are the
        same point matched to the routable graph. `latlon` is `[latitude,
        longitude]` per the solver2 contract — note the reversed order vs the
        V3 `[longitude, latitude]` convention.
      required:
        - job
      properties:
        activity:
          type:
            - string
            - 'null'
          description: >-
            `"job"`, `"pickup"`, `"delivery"`, `"departure"` (start depot) or

            `"arrival"` (end depot). Forwarded from V3 `StopOutput.stop_type`
            for

            job visits, synthesized for depot visits.
        arrival:
          type:
            - string
            - 'null'
          description: >-
            Arrival time as an ISO 8601 datetime string, if time windows are
            active.
        breakTime:
          type:
            - integer
            - 'null'
          format: int64
          description: >-
            Total break time (seconds) taken before arriving at this visit.


            Sums driver breaks of any kind — windowed lunch, drive-time,
            duty-time,

            or hard unavailability — scheduled on the leg preceding this visit.

            The mapper always sets `Some(value)`, so the wire always carries the

            field as an integer (typically `0` when no break was taken).


            We deliberately do **not** use `skip_serializing_if` here, even
            though

            the sibling V2 fields do: keeping the field explicit on the wire
            turns

            any future regression — e.g. someone refactoring the mapper to set

            `None` conditionally — into a visible `null` rather than a silently

            disappearing field, which is much easier to spot in snapshot tests

            and client code review.
        distance:
          type:
            - integer
            - 'null'
          format: int64
          description: >-
            Distance travelled to reach this stop from the previous stop in
            metres.
        job:
          type: string
          description: The job name served at this visit.
        latlon:
          type:
            - array
            - 'null'
          items:
            type: number
            format: double
          description: >-
            Snapped point as `[latitude, longitude]` (solver2 contract —
            reversed

            vs V3's `[longitude, latitude]`).
        location:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: Geographic location of this visit (input coordinate).
        serviceTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Service time at this stop in seconds.
        snappedLocation:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/V2Location'
              description: >-
                Snapped equivalent of `location` as `{latitude, longitude}`.
                Same data

                as [`Self::latlon`], different shape.
        travelTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Travel time to reach this stop from the previous stop in seconds.
        waitTime:
          type:
            - integer
            - 'null'
          format: int64
          description: Wait time at this stop in seconds.
    BreakInput:
      oneOf:
        - type: object
          description: Break that must be taken inside a fixed time window.
          required:
            - from
            - to
            - duration
            - type
          properties:
            deductPreviousBreaks:
              type:
                - boolean
                - 'null'
              description: When `true`, earlier breaks count toward this break's threshold.
            duration:
              type: integer
              format: int32
              description: Break length in seconds.
            from:
              type: string
              description: Earliest start of the break window (ISO 8601 / RFC 3339).
            location:
              oneOf:
                - type: 'null'
                - $ref: '#/components/schemas/BreakLocation'
                  description: Optional location at which the break must be taken.
            to:
              type: string
              description: Latest start of the break window (ISO 8601 / RFC 3339).
            type:
              type: string
              enum:
                - WINDOWED
        - type: object
          description: Break triggered after a maximum continuous drive time.
          required:
            - driveTime
            - duration
            - type
          properties:
            deductPreviousBreaks:
              type:
                - boolean
                - 'null'
              description: When `true`, earlier breaks count toward this break's threshold.
            driveTime:
              type: integer
              format: int32
              description: >-
                Maximum continuous driving time in seconds before this break
                fires.
            duration:
              type: integer
              format: int32
              description: Break length in seconds.
            type:
              type: string
              enum:
                - DRIVE
        - type: object
          description: Break triggered after a maximum on-duty time (drive + service).
          required:
            - workTime
            - duration
            - type
          properties:
            duration:
              type: integer
              format: int32
              description: Break length in seconds.
            type:
              type: string
              enum:
                - DUTY
            workTime:
              type: integer
              format: int32
              description: Maximum on-duty time in seconds before this break fires.
        - type: object
          description: A fixed unavailable interval (e.g. mandatory off-duty time).
          required:
            - from
            - to
            - type
          properties:
            from:
              type: string
              description: Start of the unavailable interval (ISO 8601 / RFC 3339).
            location:
              oneOf:
                - type: 'null'
                - $ref: '#/components/schemas/BreakLocation'
                  description: Optional location at which the driver is unavailable.
            to:
              type: string
              description: End of the unavailable interval (ISO 8601 / RFC 3339).
            type:
              type: string
              enum:
                - UNAVAILABILITY
      description: >-
        A driver-break rule attached to a [`ShiftInput`].


        Mirrors the v2 OnRoute API contract documented at

        <https://docs.solvice.io/guides/vrp/features/break-management>.


        Four break types are supported, distinguished by the `"type"`
        discriminator:


        - **`WINDOWED`** — break that must be taken within a fixed time window
          `[from, to]` for a given `duration`.
        - **`DRIVE`** — break triggered after the vehicle has been driving for
          `driveTime` seconds; lasts `duration` seconds.
        - **`DUTY`** — break triggered after the vehicle has been on duty
        (driving
          plus service) for `workTime` seconds; lasts `duration` seconds.
        - **`UNAVAILABILITY`** — fixed unavailable interval `[from, to]` at an
          optional location (e.g. mandatory off-duty period).

        The `deductPreviousBreaks` flag (only on `WINDOWED`/`DRIVE`/`DUTY`)
        tells

        the scheduler whether earlier breaks should count toward this break's

        threshold.


        Parsed and validated in this version of the solver; honoured by the
        solver

        in a follow-up release (PRD-1538).
    BreakLocation:
      type: object
      description: >-
        Location at which a [`BreakInput`] must be taken.


        Uses the v2 `{latitude, longitude}` shape for compatibility with
        existing

        v2 client payloads.
      required:
        - latitude
        - longitude
      properties:
        latitude:
          type: number
          format: double
          description: Latitude in decimal degrees.
        longitude:
          type: number
          format: double
          description: Longitude in decimal degrees.

````