Skip to main content
POST
/
v2
/
vrp
/
sync
/
solve
Solve a routing problem (solver2-compatible V2 format)
curl --request POST \
  --url https://api.example.com/v2/vrp/sync/solve \
  --header 'Authorization: <api-key>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "jobs": [
    {
      "name": "<string>",
      "duration": 123,
      "load": [
        123
      ],
      "location": {
        "latitude": 123,
        "longitude": 123
      },
      "tags": [
        {
          "name": "<string>",
          "hard": true
        }
      ],
      "windows": [
        {
          "from": "<string>",
          "to": "<string>",
          "hard": true
        }
      ]
    }
  ],
  "resources": [
    {
      "name": "<string>",
      "capacity": [
        123
      ],
      "end": {
        "latitude": 123,
        "longitude": 123
      },
      "shifts": [
        {
          "from": "<string>",
          "to": "<string>",
          "breaks": [
            {
              "duration": 123,
              "from": "<string>",
              "to": "<string>",
              "type": "WINDOWED",
              "deductPreviousBreaks": true,
              "location": {
                "latitude": 123,
                "longitude": 123
              }
            }
          ],
          "end": {
            "latitude": 123,
            "longitude": 123
          },
          "start": {
            "latitude": 123,
            "longitude": 123
          }
        }
      ],
      "start": {
        "latitude": 123,
        "longitude": 123
      },
      "tags": [
        "<string>"
      ]
    }
  ],
  "options": {
    "solvingTime": 1
  },
  "relations": [
    {
      "type": "<string>",
      "jobs": [
        "<string>"
      ],
      "resource": "<string>",
      "tags": [
        "<string>"
      ]
    }
  ]
}
'
import requests

url = "https://api.example.com/v2/vrp/sync/solve"

payload = {
"jobs": [
{
"name": "<string>",
"duration": 123,
"load": [123],
"location": {
"latitude": 123,
"longitude": 123
},
"tags": [
{
"name": "<string>",
"hard": True
}
],
"windows": [
{
"from": "<string>",
"to": "<string>",
"hard": True
}
]
}
],
"resources": [
{
"name": "<string>",
"capacity": [123],
"end": {
"latitude": 123,
"longitude": 123
},
"shifts": [
{
"from": "<string>",
"to": "<string>",
"breaks": [
{
"duration": 123,
"from": "<string>",
"to": "<string>",
"type": "WINDOWED",
"deductPreviousBreaks": True,
"location": {
"latitude": 123,
"longitude": 123
}
}
],
"end": {
"latitude": 123,
"longitude": 123
},
"start": {
"latitude": 123,
"longitude": 123
}
}
],
"start": {
"latitude": 123,
"longitude": 123
},
"tags": ["<string>"]
}
],
"options": { "solvingTime": 1 },
"relations": [
{
"type": "<string>",
"jobs": ["<string>"],
"resource": "<string>",
"tags": ["<string>"]
}
]
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
jobs: [
{
name: '<string>',
duration: 123,
load: [123],
location: {latitude: 123, longitude: 123},
tags: [{name: '<string>', hard: true}],
windows: [{from: '<string>', to: '<string>', hard: true}]
}
],
resources: [
{
name: '<string>',
capacity: [123],
end: {latitude: 123, longitude: 123},
shifts: [
{
from: '<string>',
to: '<string>',
breaks: [
{
duration: 123,
from: '<string>',
to: '<string>',
type: 'WINDOWED',
deductPreviousBreaks: true,
location: {latitude: 123, longitude: 123}
}
],
end: {latitude: 123, longitude: 123},
start: {latitude: 123, longitude: 123}
}
],
start: {latitude: 123, longitude: 123},
tags: ['<string>']
}
],
options: {solvingTime: 1},
relations: [
{type: '<string>', jobs: ['<string>'], resource: '<string>', tags: ['<string>']}
]
})
};

fetch('https://api.example.com/v2/vrp/sync/solve', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/v2/vrp/sync/solve",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'jobs' => [
[
'name' => '<string>',
'duration' => 123,
'load' => [
123
],
'location' => [
'latitude' => 123,
'longitude' => 123
],
'tags' => [
[
'name' => '<string>',
'hard' => true
]
],
'windows' => [
[
'from' => '<string>',
'to' => '<string>',
'hard' => true
]
]
]
],
'resources' => [
[
'name' => '<string>',
'capacity' => [
123
],
'end' => [
'latitude' => 123,
'longitude' => 123
],
'shifts' => [
[
'from' => '<string>',
'to' => '<string>',
'breaks' => [
[
'duration' => 123,
'from' => '<string>',
'to' => '<string>',
'type' => 'WINDOWED',
'deductPreviousBreaks' => true,
'location' => [
'latitude' => 123,
'longitude' => 123
]
]
],
'end' => [
'latitude' => 123,
'longitude' => 123
],
'start' => [
'latitude' => 123,
'longitude' => 123
]
]
],
'start' => [
'latitude' => 123,
'longitude' => 123
],
'tags' => [
'<string>'
]
]
],
'options' => [
'solvingTime' => 1
],
'relations' => [
[
'type' => '<string>',
'jobs' => [
'<string>'
],
'resource' => '<string>',
'tags' => [
'<string>'
]
]
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: <api-key>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://api.example.com/v2/vrp/sync/solve"

payload := strings.NewReader("{\n \"jobs\": [\n {\n \"name\": \"<string>\",\n \"duration\": 123,\n \"load\": [\n 123\n ],\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n {\n \"name\": \"<string>\",\n \"hard\": true\n }\n ],\n \"windows\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"hard\": true\n }\n ]\n }\n ],\n \"resources\": [\n {\n \"name\": \"<string>\",\n \"capacity\": [\n 123\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"shifts\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"breaks\": [\n {\n \"duration\": 123,\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"type\": \"WINDOWED\",\n \"deductPreviousBreaks\": true,\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n \"<string>\"\n ]\n }\n ],\n \"options\": {\n \"solvingTime\": 1\n },\n \"relations\": [\n {\n \"type\": \"<string>\",\n \"jobs\": [\n \"<string>\"\n ],\n \"resource\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ]\n }\n ]\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "<api-key>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://api.example.com/v2/vrp/sync/solve")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"jobs\": [\n {\n \"name\": \"<string>\",\n \"duration\": 123,\n \"load\": [\n 123\n ],\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n {\n \"name\": \"<string>\",\n \"hard\": true\n }\n ],\n \"windows\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"hard\": true\n }\n ]\n }\n ],\n \"resources\": [\n {\n \"name\": \"<string>\",\n \"capacity\": [\n 123\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"shifts\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"breaks\": [\n {\n \"duration\": 123,\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"type\": \"WINDOWED\",\n \"deductPreviousBreaks\": true,\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n \"<string>\"\n ]\n }\n ],\n \"options\": {\n \"solvingTime\": 1\n },\n \"relations\": [\n {\n \"type\": \"<string>\",\n \"jobs\": [\n \"<string>\"\n ],\n \"resource\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ]\n }\n ]\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://api.example.com/v2/vrp/sync/solve")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"jobs\": [\n {\n \"name\": \"<string>\",\n \"duration\": 123,\n \"load\": [\n 123\n ],\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n {\n \"name\": \"<string>\",\n \"hard\": true\n }\n ],\n \"windows\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"hard\": true\n }\n ]\n }\n ],\n \"resources\": [\n {\n \"name\": \"<string>\",\n \"capacity\": [\n 123\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"shifts\": [\n {\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"breaks\": [\n {\n \"duration\": 123,\n \"from\": \"<string>\",\n \"to\": \"<string>\",\n \"type\": \"WINDOWED\",\n \"deductPreviousBreaks\": true,\n \"location\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"end\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n }\n }\n ],\n \"start\": {\n \"latitude\": 123,\n \"longitude\": 123\n },\n \"tags\": [\n \"<string>\"\n ]\n }\n ],\n \"options\": {\n \"solvingTime\": 1\n },\n \"relations\": [\n {\n \"type\": \"<string>\",\n \"jobs\": [\n \"<string>\"\n ],\n \"resource\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ]\n }\n ]\n}"

response = http.request(request)
puts response.read_body
{
  "trips": [
    {
      "resource": "<string>",
      "visits": [
        {
          "job": "<string>",
          "activity": "<string>",
          "arrival": "<string>",
          "breakTime": 123,
          "distance": 123,
          "latlon": [
            123
          ],
          "location": {
            "latitude": 123,
            "longitude": 123
          },
          "serviceTime": 123,
          "snappedLocation": {
            "latitude": 123,
            "longitude": 123
          },
          "travelTime": 123,
          "waitTime": 123
        }
      ],
      "date": "<string>",
      "departureTime": "<string>",
      "distance": 123,
      "end": {
        "job": "<string>",
        "activity": "<string>",
        "arrival": "<string>",
        "breakTime": 123,
        "distance": 123,
        "latlon": [
          123
        ],
        "location": {
          "latitude": 123,
          "longitude": 123
        },
        "serviceTime": 123,
        "snappedLocation": {
          "latitude": 123,
          "longitude": 123
        },
        "travelTime": 123,
        "waitTime": 123
      },
      "serviceTime": 123,
      "start": {
        "job": "<string>",
        "activity": "<string>",
        "arrival": "<string>",
        "breakTime": 123,
        "distance": 123,
        "latlon": [
          123
        ],
        "location": {
          "latitude": 123,
          "longitude": 123
        },
        "serviceTime": 123,
        "snappedLocation": {
          "latitude": 123,
          "longitude": 123
        },
        "travelTime": 123,
        "waitTime": 123
      },
      "travelTime": 123,
      "waitTime": 123,
      "workTime": 123
    }
  ],
  "id": "<string>",
  "messages": [
    "<string>"
  ],
  "status": "<string>",
  "totalServiceTimeInSeconds": 123,
  "totalTravelDistanceInMeters": 123,
  "totalTravelTimeInSeconds": 123,
  "totalWaitTimeInSeconds": 123,
  "unserved": [
    "<string>"
  ],
  "unservedReasons": {}
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}
{
"message": "<string>",
"status": "<string>",
"code": "<string>",
"field": "<string>",
"value": "<unknown>"
}

Authorizations

Authorization
string
header
required

Query Parameters

millis
integer<int64>

Time limit override in milliseconds

Required range: x >= 0

Body

application/json

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

jobs
object[]
required

Jobs to be assigned and sequenced.

resources
object[]
required

Fleet of vehicles (called "resources" in V2).

options
null | object

Solver options; currently only solvingTime is honoured.

relations
object[] | null

Optional ordering constraints between jobs.

Response

Solution found

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.

trips
object[]
required

One trip per vehicle that has at least one visit.

id
string | null

Solver job ID — kept for SDK wire compatibility. Sync solves emit None because the request has no persistent job identity.

messages
string[] | null

Free-text events emitted during the solve. Empty array on success; reserved for future warnings.

status
string | null

Sync solves always return Some("SOLVED") on the 200 path; async/error paths are not exercised by this endpoint.

totalServiceTimeInSeconds
integer<int64> | null

Total service time across all trips in seconds.

totalTravelDistanceInMeters
integer<int64> | null

Total travel distance across all trips in metres.

totalTravelTimeInSeconds
integer<int64> | null

Total travel time across all trips in seconds.

totalWaitTimeInSeconds
integer<int64> | null

Total wait time across all trips in seconds.

unserved
string[] | null

Job names that could not be assigned; None when all jobs are assigned.

unservedReasons
object | null

Maps each unserved job name to a list of reason strings.