Routific Route Optimization API

Routific's Route Optimization API solves the Vehicle Routing Problem (VRP) and Pickup-and-Delivery Problem (PDP) for last-mile delivery fleets. It supports time-windows, capacity constraints, multi-depot fleets, driver shifts, balanced routes, traffic simulation, polyline output, toll avoidance, and Google or Here geocoding. Synchronous /v1/vrp handles small problems; asynchronous /v1/vrp-long and /v1/pdp-long process up to 2,500 visits per call via a job_id polling pattern. /v1/fix and /v1/fix-pdp insert new visits into existing solutions without re-solving.

Routific Route Optimization API is published by Routific on the APIs.io network, described by a machine-readable OpenAPI specification.

This API exposes 3 machine-runnable capabilities that can be deployed as REST, MCP, or Agent Skill surfaces via Naftiko and 5 JSON Schema definitions.

Tagged areas include RouteOptimization, VRP, PickupAndDelivery, Logistics, and Delivery. The published artifact set on APIs.io includes API documentation, an OpenAPI specification, a JSON-LD context, sample payloads, 3 Naftiko capability specs, and 5 JSON Schemas.

Documentation

Specifications

Examples

Schemas & Data

Other Resources

OpenAPI Specification

routific-route-optimization-api-openapi.yml Raw ↑
openapi: 3.1.0
info:
  title: Routific Route Optimization API
  description: |
    Routific's Route Optimization API solves the vehicle routing problem (VRP)
    and the pickup-and-delivery problem (PDP) for last-mile delivery fleets.
    It supports time-windows, capacity constraints, driver shifts, multi-depot
    fleets, balanced routes, traffic simulation, and polyline output.

    The API offers four solving surfaces:

    - `POST /v1/vrp` — synchronous vehicle routing for small problems (< 60 visits).
    - `POST /v1/vrp-long` — asynchronous vehicle routing for problems up to 2,500 visits.
    - `POST /v1/pdp-long` — asynchronous pickup-and-delivery routing.
    - `POST /v1/fix` and `POST /v1/fix-pdp` — insert new visits into an
      existing optimized solution without re-solving the whole problem.

    Asynchronous endpoints return a `job_id` immediately; clients poll
    `GET /jobs/{job_id}` until the job reaches `finished` or `error`.
  version: '1.11'
  contact:
    name: Routific Support
    email: [email protected]
    url: https://docs.routific.com
  termsOfService: https://routific.com/terms
  license:
    name: Routific Terms of Service
    url: https://routific.com/terms
  x-logo:
    url: https://routific.com/favicon.ico

servers:
  - url: https://api.routific.com
    description: Production Server

security:
  - BearerAuth: []

tags:
  - name: VRP
    description: Vehicle Routing Problem — assign and order visits across a fleet.
  - name: PDP
    description: Pickup and Delivery Problem — paired pickup/dropoff routing.
  - name: Jobs
    description: Asynchronous long-running optimization jobs.
  - name: Fix
    description: Insert new visits into an existing optimized solution.

paths:
  /v1/vrp:
    post:
      summary: Solve Vehicle Routing Problem
      description: |
        Synchronously solve a vehicle routing problem. Send the addresses of
        your visits and your fleet; the API returns the optimal allocation and
        the order in which each vehicle should visit them. Use for small problems
        (< 60 visits). Larger problems should use `/v1/vrp-long`.
      operationId: solveVrp
      tags:
        - VRP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VrpRequest'
            examples:
              minimalExample:
                $ref: '#/components/examples/VrpRequestExample'
      responses:
        '200':
          description: Optimized route solution
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VrpSolution'
        '400':
          $ref: '#/components/responses/InputError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '408':
          $ref: '#/components/responses/RequestTimeout'
        '412':
          $ref: '#/components/responses/NoSolution'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'

  /v1/vrp-long:
    post:
      summary: Solve Vehicle Routing Problem (Async)
      description: |
        Submit a vehicle routing problem for asynchronous processing. Returns
        a `job_id` immediately; poll `GET /jobs/{job_id}` for status and result.
        Hard limit of 2,500 visits per call.
      operationId: solveVrpLong
      tags:
        - VRP
        - Jobs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/VrpRequest'
      responses:
        '202':
          description: Job accepted for asynchronous processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobAccepted'
        '400':
          $ref: '#/components/responses/InputError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /v1/pdp-long:
    post:
      summary: Solve Pickup And Delivery Problem (Async)
      description: |
        Submit a pickup-and-delivery routing problem for asynchronous processing.
        Each visit pairs a pickup and a dropoff location with their own
        time-windows and durations. Returns a `job_id` immediately.
      operationId: solvePdpLong
      tags:
        - PDP
        - Jobs
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/PdpRequest'
      responses:
        '202':
          description: Job accepted for asynchronous processing
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/JobAccepted'
        '400':
          $ref: '#/components/responses/InputError'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '429':
          $ref: '#/components/responses/RateLimited'

  /jobs/{job_id}:
    get:
      summary: Get Optimization Job Status
      description: |
        Retrieve the status and result of an asynchronous routing job submitted
        via `/v1/vrp-long` or `/v1/pdp-long`. Statuses are `pending`,
        `processing`, `finished`, or `error`. When `finished`, the response
        payload is in `output`.
      operationId: getJob
      tags:
        - Jobs
      parameters:
        - name: job_id
          in: path
          required: true
          schema:
            type: string
          description: Identifier returned by `/v1/vrp-long` or `/v1/pdp-long`.
      responses:
        '200':
          description: Current job state
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Job'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          description: Job not found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'

  /v1/fix:
    post:
      summary: Insert New Visits Into VRP Solution
      description: |
        Insert one or more new visits into an existing optimized VRP solution
        without re-solving the entire problem. Pass the current `solution`,
        the remaining `visits`, and the new visit IDs in `unserved`.
      operationId: fixVrp
      tags:
        - Fix
        - VRP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FixRequest'
      responses:
        '200':
          description: Updated solution
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/VrpSolution'
        '400':
          $ref: '#/components/responses/InputError'
        '401':
          $ref: '#/components/responses/Unauthorized'

  /v1/fix-pdp:
    post:
      summary: Insert New Visits Into PDP Solution
      description: |
        Insert one or more new pickup-and-delivery visits into an existing
        optimized PDP solution without re-solving the entire problem.
      operationId: fixPdp
      tags:
        - Fix
        - PDP
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FixPdpRequest'
      responses:
        '200':
          description: Updated solution
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PdpSolution'
        '400':
          $ref: '#/components/responses/InputError'
        '401':
          $ref: '#/components/responses/Unauthorized'

components:
  securitySchemes:
    BearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
      description: |
        Routific issues per-account JWT tokens. Send as
        `Authorization: bearer <token>`.

  schemas:
    Location:
      type: object
      description: Geocoded address for a visit, pickup, dropoff, or depot.
      required: [lat, lng]
      properties:
        id:
          type: string
          description: Optional location identifier (e.g. `depot`).
        name:
          type: string
          description: Human-readable address.
        lat:
          type: number
          format: double
          description: Latitude in decimal degrees.
        lng:
          type: number
          format: double
          description: Longitude in decimal degrees.

    Visit:
      type: object
      description: A single visit with location, time-window, and service duration.
      required: [location]
      properties:
        location:
          $ref: '#/components/schemas/Location'
        start:
          type: string
          description: Earliest time the visit can begin (`hh:mm` or UNIX seconds).
          example: '9:00'
        end:
          type: string
          description: Latest time the visit can begin (`hh:mm` or UNIX seconds).
          example: '12:00'
        duration:
          type: integer
          description: Service duration in minutes.
          minimum: 1
        load:
          oneOf:
            - type: number
            - type: object
              additionalProperties:
                type: number
          description: Load contributed by this visit (single value or per-dimension object).
        priority:
          type: integer
          description: Optional priority level.
        type:
          oneOf:
            - type: string
            - type: number
            - type: array
              items:
                oneOf:
                  - type: string
                  - type: number
          description: Compatibility type(s) the assigned vehicle must support.

    PickupDeliveryVisit:
      type: object
      description: Paired pickup and dropoff entry for the pickup-and-delivery problem.
      required: [pickup, dropoff]
      properties:
        pickup:
          $ref: '#/components/schemas/Visit'
        dropoff:
          $ref: '#/components/schemas/Visit'

    Vehicle:
      type: object
      description: A single vehicle/driver in the fleet.
      required: [start_location]
      properties:
        start_location:
          $ref: '#/components/schemas/Location'
        end_location:
          $ref: '#/components/schemas/Location'
        shift_start:
          type: string
          description: Earliest time the driver can begin (`hh:mm` or UNIX seconds).
          example: '8:00'
        shift_end:
          type: string
          description: Latest time the driver must finish (`hh:mm` or UNIX seconds).
          example: '17:00'
        capacity:
          oneOf:
            - type: number
            - type: object
              additionalProperties:
                type: number
          description: Vehicle capacity (single value or per-dimension object).
        min_visits:
          type: integer
          description: Minimum number of visits the vehicle must handle.
        type:
          oneOf:
            - type: string
            - type: number
            - type: array
              items:
                oneOf:
                  - type: string
                  - type: number
          description: Compatibility type(s) the vehicle supports.

    Options:
      type: object
      description: Tunable parameters that adjust how the optimization engine runs.
      properties:
        traffic:
          type: string
          enum: [faster, fast, normal, slow, 'very slow']
          default: faster
          description: Traffic simulation level.
        min_visits_per_vehicle:
          type: integer
          minimum: 1
          description: Minimum number of visits per vehicle.
        balance:
          type: boolean
          description: Keep variance across driver shift times as small as possible.
        visit_balance_coefficient:
          type: number
          minimum: 0
          maximum: 1
          description: Trade off route balance vs efficiency (0.0 = efficient, 1.0 = balanced). Available on `/vrp-long` v1.10+.
        min_vehicles:
          type: boolean
          default: false
          description: Minimize the number of vehicles used.
        shortest_distance:
          type: boolean
          default: false
          description: Optimize for shortest distance rather than total driving time.
        squash_durations:
          type: integer
          minimum: 1
          description: Squash subsequent visit durations at the same address to this many minutes.
        max_vehicle_overtime:
          type: integer
          minimum: 0
          description: Maximum minutes a driver is allowed to work overtime.
        max_visit_lateness:
          type: integer
          minimum: 0
          description: Maximum minutes a stop is allowed to be late.
        polylines:
          type: boolean
          default: false
          description: Return encoded polylines and per-stop distances.
        avoid_tolls:
          type: boolean
          default: false
          description: Avoid toll roads when calculating routes.
        geocoder:
          type: string
          enum: [google, here]
          default: google
          description: Geocoding provider for address strings.

    VrpRequest:
      type: object
      description: Vehicle routing problem request.
      required: [visits, fleet]
      properties:
        visits:
          type: object
          description: Map of visit ID to visit definition.
          additionalProperties:
            $ref: '#/components/schemas/Visit'
        fleet:
          type: object
          description: Map of vehicle ID to vehicle definition.
          additionalProperties:
            $ref: '#/components/schemas/Vehicle'
        options:
          $ref: '#/components/schemas/Options'

    PdpRequest:
      type: object
      description: Pickup-and-delivery problem request.
      required: [visits, fleet]
      properties:
        visits:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/PickupDeliveryVisit'
        fleet:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Vehicle'
        options:
          $ref: '#/components/schemas/Options'

    StopAssignment:
      type: object
      description: A single stop in a vehicle's route.
      properties:
        location_id:
          type: string
        arrival_time:
          type: string
        finish_time:
          type: string
        type:
          type: string
          enum: [pickup, dropoff]
        too_late:
          type: boolean
        late_by:
          type: integer
          description: Minutes by which the stop is late (when overtime/lateness options used).
        distance:
          type: number
          description: Meters from the previous stop (when `polylines` is true).

    VrpSolution:
      type: object
      description: Optimized solution returned by the engine.
      properties:
        status:
          type: string
          enum: [success, error]
        total_travel_time:
          type: integer
          description: Total travel time across all vehicles in minutes.
        total_idle_time:
          type: integer
        total_working_time:
          type: integer
        total_visit_lateness:
          type: integer
        num_late_visits:
          type: integer
        total_overtime:
          type: integer
        vehicle_overtime:
          type: object
          additionalProperties:
            type: integer
        num_unserved:
          type: integer
        unserved:
          oneOf:
            - type: array
              items:
                type: string
            - type: object
              additionalProperties:
                type: string
          description: Visits that could not be scheduled (or a map of visit-id to reason).
        solution:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/StopAssignment'
        polylines:
          type: object
          additionalProperties:
            type: string
          description: Encoded polyline per vehicle (when `options.polylines` is true).

    PdpSolution:
      allOf:
        - $ref: '#/components/schemas/VrpSolution'

    FixRequest:
      type: object
      required: [visits, fleet, solution, unserved]
      properties:
        visits:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Visit'
        fleet:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Vehicle'
        options:
          $ref: '#/components/schemas/Options'
        solution:
          type: object
          description: Existing solution — map of vehicle ID to ordered list of visit IDs.
          additionalProperties:
            type: array
            items:
              type: string
        unserved:
          type: array
          description: New visit IDs to insert into the existing solution.
          items:
            type: string

    FixPdpRequest:
      type: object
      required: [visits, fleet, solution, unserved]
      properties:
        visits:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/PickupDeliveryVisit'
        fleet:
          type: object
          additionalProperties:
            $ref: '#/components/schemas/Vehicle'
        options:
          $ref: '#/components/schemas/Options'
        solution:
          type: object
          additionalProperties:
            type: array
            items:
              $ref: '#/components/schemas/StopAssignment'
        unserved:
          type: array
          items:
            type: string

    JobAccepted:
      type: object
      required: [job_id]
      properties:
        job_id:
          type: string

    Job:
      type: object
      description: Asynchronous optimization job state.
      required: [status]
      properties:
        job_id:
          type: string
        status:
          type: string
          enum: [pending, processing, finished, error]
        created_at:
          type: string
          format: date-time
        finished_at:
          type: string
          format: date-time
        output:
          oneOf:
            - $ref: '#/components/schemas/VrpSolution'
            - type: string
          description: Solution payload when status is `finished`; error message when `error`.

    ErrorResponse:
      type: object
      properties:
        error:
          type: string
          description: Routific error code (e.g. `ERR_DRIVER_NOT_SAME_REGION`).
        message:
          type: string
          description: Human-readable error message.

  examples:
    VrpRequestExample:
      summary: Minimal VRP request
      value:
        visits:
          order_1:
            location:
              name: '6800 Cambie'
              lat: 49.227107
              lng: -123.1163085
            start: '9:00'
            end: '12:00'
            duration: 10
        fleet:
          vehicle_1:
            start_location:
              id: depot
              name: '800 Kingsway'
              lat: 49.2553636
              lng: -123.0873365
            shift_start: '8:00'
            shift_end: '12:00'

  responses:
    InputError:
      description: Input error — see the error message and code for details.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    Unauthorized:
      description: Missing or invalid bearer token.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RequestTimeout:
      description: Request was too large for the synchronous endpoint — use `/v1/vrp-long` or `/v1/pdp-long`.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    NoSolution:
      description: No solution could be found — usually due to incorrect time-windows.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    RateLimited:
      description: Daily request limit exceeded or problem size larger than account limits.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'
    InternalError:
      description: Internal server error.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorResponse'