Submit a run
Submit a routing problem to solve in the background
curl --request POST \
--url https://api.solvice.io/v3/routing/runs \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"options": {
"seed": 42,
"time_limit_s": 5
},
"problem": {
"depots": [
{
"id": "gent",
"location": [
3.7174,
51.0543
]
}
],
"jobs": [
{
"id": "job-1",
"location": [
3.725,
51.05
],
"pickup": {
"weight": 20
},
"service_duration_s": 300,
"skills": [
{
"name": "fridge"
}
],
"time_windows": [
{
"from": "2026-07-01T09:00:00+02:00",
"to": "2026-07-01T12:00:00+02:00"
}
]
},
{
"id": "job-2",
"location": [
3.71,
51.06
],
"pickup": {
"weight": 35
},
"service_duration_s": 600
}
],
"objective": {
"costs": {
"per_route_hour": 35,
"per_travel_km": 0.2
},
"currency": "EUR"
},
"vehicles": [
{
"capacity": {
"weight": 500
},
"id": "v1",
"profile": "car",
"shifts": [
{
"end": {
"depot": "gent"
},
"from": "2026-07-01T08:00:00+02:00",
"id": "mon",
"start": {
"depot": "gent"
},
"to": "2026-07-01T17:00:00+02:00"
}
],
"skills": [
{
"name": "fridge"
}
]
}
]
}
}
'import requests
url = "https://api.solvice.io/v3/routing/runs"
payload = {
"options": {
"seed": 42,
"time_limit_s": 5
},
"problem": {
"depots": [
{
"id": "gent",
"location": [3.7174, 51.0543]
}
],
"jobs": [
{
"id": "job-1",
"location": [3.725, 51.05],
"pickup": { "weight": 20 },
"service_duration_s": 300,
"skills": [{ "name": "fridge" }],
"time_windows": [
{
"from": "2026-07-01T09:00:00+02:00",
"to": "2026-07-01T12:00:00+02:00"
}
]
},
{
"id": "job-2",
"location": [3.71, 51.06],
"pickup": { "weight": 35 },
"service_duration_s": 600
}
],
"objective": {
"costs": {
"per_route_hour": 35,
"per_travel_km": 0.2
},
"currency": "EUR"
},
"vehicles": [
{
"capacity": { "weight": 500 },
"id": "v1",
"profile": "car",
"shifts": [
{
"end": { "depot": "gent" },
"from": "2026-07-01T08:00:00+02:00",
"id": "mon",
"start": { "depot": "gent" },
"to": "2026-07-01T17:00:00+02:00"
}
],
"skills": [{ "name": "fridge" }]
}
]
}
}
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({
options: {seed: 42, time_limit_s: 5},
problem: {
depots: [{id: 'gent', location: [3.7174, 51.0543]}],
jobs: [
{
id: 'job-1',
location: [3.725, 51.05],
pickup: {weight: 20},
service_duration_s: 300,
skills: [{name: 'fridge'}],
time_windows: [{from: '2026-07-01T09:00:00+02:00', to: '2026-07-01T12:00:00+02:00'}]
},
{
id: 'job-2',
location: [3.71, 51.06],
pickup: {weight: 35},
service_duration_s: 600
}
],
objective: {costs: {per_route_hour: 35, per_travel_km: 0.2}, currency: 'EUR'},
vehicles: [
{
capacity: {weight: 500},
id: 'v1',
profile: 'car',
shifts: [
{
end: {depot: 'gent'},
from: '2026-07-01T08:00:00+02:00',
id: 'mon',
start: {depot: 'gent'},
to: '2026-07-01T17:00:00+02:00'
}
],
skills: [{name: 'fridge'}]
}
]
}
})
};
fetch('https://api.solvice.io/v3/routing/runs', 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.solvice.io/v3/routing/runs",
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([
'options' => [
'seed' => 42,
'time_limit_s' => 5
],
'problem' => [
'depots' => [
[
'id' => 'gent',
'location' => [
3.7174,
51.0543
]
]
],
'jobs' => [
[
'id' => 'job-1',
'location' => [
3.725,
51.05
],
'pickup' => [
'weight' => 20
],
'service_duration_s' => 300,
'skills' => [
[
'name' => 'fridge'
]
],
'time_windows' => [
[
'from' => '2026-07-01T09:00:00+02:00',
'to' => '2026-07-01T12:00:00+02:00'
]
]
],
[
'id' => 'job-2',
'location' => [
3.71,
51.06
],
'pickup' => [
'weight' => 35
],
'service_duration_s' => 600
]
],
'objective' => [
'costs' => [
'per_route_hour' => 35,
'per_travel_km' => 0.2
],
'currency' => 'EUR'
],
'vehicles' => [
[
'capacity' => [
'weight' => 500
],
'id' => 'v1',
'profile' => 'car',
'shifts' => [
[
'end' => [
'depot' => 'gent'
],
'from' => '2026-07-01T08:00:00+02:00',
'id' => 'mon',
'start' => [
'depot' => 'gent'
],
'to' => '2026-07-01T17:00:00+02:00'
]
],
'skills' => [
[
'name' => 'fridge'
]
]
]
]
]
]),
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.solvice.io/v3/routing/runs"
payload := strings.NewReader("{\n \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\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.solvice.io/v3/routing/runs")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.solvice.io/v3/routing/runs")
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 \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "d28568b1-34cc-4f89-b10b-dc24b26a8275",
"status": "queued",
"links": {
"self": "/v3/routing/runs/d28568b1-34cc-4f89-b10b-dc24b26a8275",
"result": "/v3/routing/runs/d28568b1-34cc-4f89-b10b-dc24b26a8275/result"
}
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"message": "Failed to launch routing run",
"error": "GATEWAY_ERROR"
}Authorizations
Body
Request body for POST /v3/routing/solve.
The problem: tasks, fleet, depots, relations, objective, travel.
Show child attributes
Show child attributes
{
"depots": [
{
"id": "gent",
"location": [3.7174, 51.0543]
}
],
"jobs": [
{
"id": "job-1",
"location": [3.725, 51.05],
"pickup": { "weight": 20 },
"service_duration_s": 300
}
],
"vehicles": [
{
"capacity": { "weight": 500 },
"id": "v1",
"shifts": [
{
"end": { "depot": "gent" },
"from": "2026-07-01T08:00:00+02:00",
"id": "mon",
"start": { "depot": "gent" },
"to": "2026-07-01T17:00:00+02:00"
}
]
}
]
}
Solve options.
Show child attributes
Show child attributes
{
"polylines": "full",
"seed": 42,
"time_limit_s": 5
}
Warm start: the plan the search starts from instead of constructing
from scratch (re-optimization). A result's plan goes in as it stands.
See plan.routes[].locked_count for freezing a dispatched prefix.
A hint, not a guarantee: an unlocked stop that violates a hard
constraint (e.g. capacity, skills, eligibility, limits.*, or a time
window with no per_late_hour set) is left unassigned and the
search reinserts it wherever it legitimately fits, or it surfaces in
unassigned[] with a typed reason. An infeasible locked stop is a 400.
Show child attributes
Show child attributes
Response
Run accepted. It is queued until a worker starts it.
One async run.
The run id. Use it in the paths of the other endpoints.
"d28568b1-34cc-4f89-b10b-dc24b26a8275"
Where a run is. queued until a worker claims it, then running. succeeded, failed and cancelled are final.
queued, running, succeeded, failed, cancelled Paths of the run, relative to the API host.
Show child attributes
Show child attributes
Present when status is failed.
Show child attributes
Show child attributes
When a worker claimed the run, in UTC. Absent while the run is queued.
"2026-10-15T07:40:59Z"
When the run reached a final state, in UTC. Absent before then.
"2026-10-15T07:41:00Z"
When the run and its plan are deleted: finished_at plus 365 days. Absent before the run is final.
"2027-10-15T07:41:00Z"
Was this page helpful?
curl --request POST \
--url https://api.solvice.io/v3/routing/runs \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"options": {
"seed": 42,
"time_limit_s": 5
},
"problem": {
"depots": [
{
"id": "gent",
"location": [
3.7174,
51.0543
]
}
],
"jobs": [
{
"id": "job-1",
"location": [
3.725,
51.05
],
"pickup": {
"weight": 20
},
"service_duration_s": 300,
"skills": [
{
"name": "fridge"
}
],
"time_windows": [
{
"from": "2026-07-01T09:00:00+02:00",
"to": "2026-07-01T12:00:00+02:00"
}
]
},
{
"id": "job-2",
"location": [
3.71,
51.06
],
"pickup": {
"weight": 35
},
"service_duration_s": 600
}
],
"objective": {
"costs": {
"per_route_hour": 35,
"per_travel_km": 0.2
},
"currency": "EUR"
},
"vehicles": [
{
"capacity": {
"weight": 500
},
"id": "v1",
"profile": "car",
"shifts": [
{
"end": {
"depot": "gent"
},
"from": "2026-07-01T08:00:00+02:00",
"id": "mon",
"start": {
"depot": "gent"
},
"to": "2026-07-01T17:00:00+02:00"
}
],
"skills": [
{
"name": "fridge"
}
]
}
]
}
}
'import requests
url = "https://api.solvice.io/v3/routing/runs"
payload = {
"options": {
"seed": 42,
"time_limit_s": 5
},
"problem": {
"depots": [
{
"id": "gent",
"location": [3.7174, 51.0543]
}
],
"jobs": [
{
"id": "job-1",
"location": [3.725, 51.05],
"pickup": { "weight": 20 },
"service_duration_s": 300,
"skills": [{ "name": "fridge" }],
"time_windows": [
{
"from": "2026-07-01T09:00:00+02:00",
"to": "2026-07-01T12:00:00+02:00"
}
]
},
{
"id": "job-2",
"location": [3.71, 51.06],
"pickup": { "weight": 35 },
"service_duration_s": 600
}
],
"objective": {
"costs": {
"per_route_hour": 35,
"per_travel_km": 0.2
},
"currency": "EUR"
},
"vehicles": [
{
"capacity": { "weight": 500 },
"id": "v1",
"profile": "car",
"shifts": [
{
"end": { "depot": "gent" },
"from": "2026-07-01T08:00:00+02:00",
"id": "mon",
"start": { "depot": "gent" },
"to": "2026-07-01T17:00:00+02:00"
}
],
"skills": [{ "name": "fridge" }]
}
]
}
}
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({
options: {seed: 42, time_limit_s: 5},
problem: {
depots: [{id: 'gent', location: [3.7174, 51.0543]}],
jobs: [
{
id: 'job-1',
location: [3.725, 51.05],
pickup: {weight: 20},
service_duration_s: 300,
skills: [{name: 'fridge'}],
time_windows: [{from: '2026-07-01T09:00:00+02:00', to: '2026-07-01T12:00:00+02:00'}]
},
{
id: 'job-2',
location: [3.71, 51.06],
pickup: {weight: 35},
service_duration_s: 600
}
],
objective: {costs: {per_route_hour: 35, per_travel_km: 0.2}, currency: 'EUR'},
vehicles: [
{
capacity: {weight: 500},
id: 'v1',
profile: 'car',
shifts: [
{
end: {depot: 'gent'},
from: '2026-07-01T08:00:00+02:00',
id: 'mon',
start: {depot: 'gent'},
to: '2026-07-01T17:00:00+02:00'
}
],
skills: [{name: 'fridge'}]
}
]
}
})
};
fetch('https://api.solvice.io/v3/routing/runs', 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.solvice.io/v3/routing/runs",
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([
'options' => [
'seed' => 42,
'time_limit_s' => 5
],
'problem' => [
'depots' => [
[
'id' => 'gent',
'location' => [
3.7174,
51.0543
]
]
],
'jobs' => [
[
'id' => 'job-1',
'location' => [
3.725,
51.05
],
'pickup' => [
'weight' => 20
],
'service_duration_s' => 300,
'skills' => [
[
'name' => 'fridge'
]
],
'time_windows' => [
[
'from' => '2026-07-01T09:00:00+02:00',
'to' => '2026-07-01T12:00:00+02:00'
]
]
],
[
'id' => 'job-2',
'location' => [
3.71,
51.06
],
'pickup' => [
'weight' => 35
],
'service_duration_s' => 600
]
],
'objective' => [
'costs' => [
'per_route_hour' => 35,
'per_travel_km' => 0.2
],
'currency' => 'EUR'
],
'vehicles' => [
[
'capacity' => [
'weight' => 500
],
'id' => 'v1',
'profile' => 'car',
'shifts' => [
[
'end' => [
'depot' => 'gent'
],
'from' => '2026-07-01T08:00:00+02:00',
'id' => 'mon',
'start' => [
'depot' => 'gent'
],
'to' => '2026-07-01T17:00:00+02:00'
]
],
'skills' => [
[
'name' => 'fridge'
]
]
]
]
]
]),
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.solvice.io/v3/routing/runs"
payload := strings.NewReader("{\n \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\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.solvice.io/v3/routing/runs")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\n }\n ]\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.solvice.io/v3/routing/runs")
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 \"options\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n },\n \"problem\": {\n \"depots\": [\n {\n \"id\": \"gent\",\n \"location\": [\n 3.7174,\n 51.0543\n ]\n }\n ],\n \"jobs\": [\n {\n \"id\": \"job-1\",\n \"location\": [\n 3.725,\n 51.05\n ],\n \"pickup\": {\n \"weight\": 20\n },\n \"service_duration_s\": 300,\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ],\n \"time_windows\": [\n {\n \"from\": \"2026-07-01T09:00:00+02:00\",\n \"to\": \"2026-07-01T12:00:00+02:00\"\n }\n ]\n },\n {\n \"id\": \"job-2\",\n \"location\": [\n 3.71,\n 51.06\n ],\n \"pickup\": {\n \"weight\": 35\n },\n \"service_duration_s\": 600\n }\n ],\n \"objective\": {\n \"costs\": {\n \"per_route_hour\": 35,\n \"per_travel_km\": 0.2\n },\n \"currency\": \"EUR\"\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"profile\": \"car\",\n \"shifts\": [\n {\n \"end\": {\n \"depot\": \"gent\"\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"id\": \"mon\",\n \"start\": {\n \"depot\": \"gent\"\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ],\n \"skills\": [\n {\n \"name\": \"fridge\"\n }\n ]\n }\n ]\n }\n}"
response = http.request(request)
puts response.read_body{
"id": "d28568b1-34cc-4f89-b10b-dc24b26a8275",
"status": "queued",
"links": {
"self": "/v3/routing/runs/d28568b1-34cc-4f89-b10b-dc24b26a8275",
"result": "/v3/routing/runs/d28568b1-34cc-4f89-b10b-dc24b26a8275/result"
}
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"code": "invalid_request",
"errors": [
{
"code": "out_of_range",
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"pointer": "/problem/depots/0/service_duration_s"
}
],
"message": "depot 'gent': service_duration_s must be >= 0, got -60",
"request_id": "req_7f3a2c90d1e4b5a6",
"status": "BAD_REQUEST"
}{
"message": "Failed to launch routing run",
"error": "GATEWAY_ERROR"
}