Evaluate
Score a fixed assignment — objective totals, timing, loads and constraint violations, without optimizing
curl --request POST \
--url https://api.solvice.io/v3/routing/evaluate \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"jobs": [
{
"demand": {
"weight": 10
},
"id": "job-1",
"location": {
"coordinate": [
3.725,
51.05
]
},
"service_duration_s": 300
}
],
"objective": {
"costs": {
"currency": "EUR",
"per_travel_hour": 3600
},
"minimize_vehicles": true
},
"options": {
"runtime": {
"seed": 42,
"time_limit_s": 5
}
},
"vehicles": [
{
"capacity": {
"weight": 500
},
"id": "v1",
"shifts": [
{
"end": {
"coordinate": [
3.7174,
51.0543
]
},
"from": "2026-07-01T08:00:00+02:00",
"start": {
"coordinate": [
3.7174,
51.0543
]
},
"to": "2026-07-01T17:00:00+02:00"
}
]
}
],
"routes": [
{
"job_ids": [
"job-1"
],
"vehicle": "v1"
}
]
}
'import requests
url = "https://api.solvice.io/v3/routing/evaluate"
payload = {
"jobs": [
{
"demand": { "weight": 10 },
"id": "job-1",
"location": { "coordinate": [3.725, 51.05] },
"service_duration_s": 300
}
],
"objective": {
"costs": {
"currency": "EUR",
"per_travel_hour": 3600
},
"minimize_vehicles": True
},
"options": { "runtime": {
"seed": 42,
"time_limit_s": 5
} },
"vehicles": [
{
"capacity": { "weight": 500 },
"id": "v1",
"shifts": [
{
"end": { "coordinate": [3.7174, 51.0543] },
"from": "2026-07-01T08:00:00+02:00",
"start": { "coordinate": [3.7174, 51.0543] },
"to": "2026-07-01T17:00:00+02:00"
}
]
}
],
"routes": [
{
"job_ids": ["job-1"],
"vehicle": "v1"
}
]
}
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: [
{
demand: {weight: 10},
id: 'job-1',
location: {coordinate: [3.725, 51.05]},
service_duration_s: 300
}
],
objective: {costs: {currency: 'EUR', per_travel_hour: 3600}, minimize_vehicles: true},
options: {runtime: {seed: 42, time_limit_s: 5}},
vehicles: [
{
capacity: {weight: 500},
id: 'v1',
shifts: [
{
end: {coordinate: [3.7174, 51.0543]},
from: '2026-07-01T08:00:00+02:00',
start: {coordinate: [3.7174, 51.0543]},
to: '2026-07-01T17:00:00+02:00'
}
]
}
],
routes: [{job_ids: ['job-1'], vehicle: 'v1'}]
})
};
fetch('https://api.solvice.io/v3/routing/evaluate', 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/evaluate",
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' => [
[
'demand' => [
'weight' => 10
],
'id' => 'job-1',
'location' => [
'coordinate' => [
3.725,
51.05
]
],
'service_duration_s' => 300
]
],
'objective' => [
'costs' => [
'currency' => 'EUR',
'per_travel_hour' => 3600
],
'minimize_vehicles' => true
],
'options' => [
'runtime' => [
'seed' => 42,
'time_limit_s' => 5
]
],
'vehicles' => [
[
'capacity' => [
'weight' => 500
],
'id' => 'v1',
'shifts' => [
[
'end' => [
'coordinate' => [
3.7174,
51.0543
]
],
'from' => '2026-07-01T08:00:00+02:00',
'start' => [
'coordinate' => [
3.7174,
51.0543
]
],
'to' => '2026-07-01T17:00:00+02:00'
]
]
]
],
'routes' => [
[
'job_ids' => [
'job-1'
],
'vehicle' => 'v1'
]
]
]),
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/evaluate"
payload := strings.NewReader("{\n \"jobs\": [\n {\n \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\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/evaluate")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"jobs\": [\n {\n \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.solvice.io/v3/routing/evaluate")
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 \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"routes": [],
"summary": {
"elapsed_ms": 12,
"jobs_assigned": 1,
"jobs_unassigned": 0,
"status": "feasible",
"total_distance_m": 8450,
"total_duration_s": 1980,
"total_violations": 0,
"vehicles_used": 1
},
"unassigned": []
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}Authorizations
Body
Request body for POST /v3/routing/evaluate.
Carries the same problem definition as [SolveRequest] (flattened in) plus
the imported routes. Computes objective totals, timing, loads, and
constraint violations without running the optimizer; jobs absent from every
route are reported as unassigned.
Solver-only knobs (options.runtime.time_limit_s, options.runtime.seed,
objective.minimize_vehicles) are accepted for solve-payload compatibility
and ignored — no search runs here.
Available vehicles.
Show child attributes
Show child attributes
Imported route assignments to evaluate.
Show child attributes
Show child attributes
Warm-start: route assignments the search starts from instead of
constructing from scratch (re-optimization). Unknown vehicle/job ids
are rejected with HTTP 400. See [RouteAssignment::locked_count] for
freezing a dispatched prefix. Accepted for solve-payload compatibility
on /v3/routing/evaluate and /v3/routing/suggest and ignored there
— routes is the input on those endpoints.
Show child attributes
Show child attributes
Single-stop visits to serve.
Show child attributes
Show child attributes
Objective configuration.
Show child attributes
Show child attributes
{ "costs": { "currency": "EUR", "per_travel_hour": 3600 }, "minimize_vehicles": true }
Solver runtime options.
Show child attributes
Show child attributes
{ "runtime": { "seed": 42, "time_limit_s": 5 } }
Ordering, grouping, and synchronization constraints.
A hard constraint between tasks. Tagged union; each variant carries only its valid fields.
All four variants are wired: ordered (via job_ids or groups),
same_resource, same_day, and synchronized. Member selection is
either explicit job_ids or a group tag (same_resource/
same_day; validated not-both) — ordered uses job_ids or the
cross-group groups list.
(The never-wired consecutive and same_route variants, the per-relation
id and soft violation_cost fields, ordered's group/min_interval_s/
max_interval_s/measure_from, and synchronized.tasks[*].vehicles were
removed: every one was rejected with HTTP 400 on any value. Each can return
as a new field/variant once its core primitive exists — relations are
hard-only until then.)
- Ordered
- Same resource
- Same day
- Synchronized
Show child attributes
Show child attributes
{ "job_ids": ["job-1", "job-2"], "type": "ordered" }
Bound pickup→delivery shipments to serve.
Show child attributes
Show child attributes
Response
Solution evaluated
Response body for POST /v3/routing/evaluate.
Same route/stop shape as the solve response ([Route], [StopOutput]), with
per-stop and per-route [Violation]s populated.
One entry per non-empty route, in vehicle order.
Show child attributes
Show child attributes
Aggregate statistics including the violation count.
Show child attributes
Show child attributes
{ "elapsed_ms": 12, "jobs_assigned": 1, "jobs_unassigned": 0, "status": "feasible", "total_distance_m": 8450, "total_duration_s": 1980, "total_violations": 0, "vehicles_used": 1 }
Jobs not assigned to any route, with structured reasons.
Show child attributes
Show child attributes
Was this page helpful?
curl --request POST \
--url https://api.solvice.io/v3/routing/evaluate \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"jobs": [
{
"demand": {
"weight": 10
},
"id": "job-1",
"location": {
"coordinate": [
3.725,
51.05
]
},
"service_duration_s": 300
}
],
"objective": {
"costs": {
"currency": "EUR",
"per_travel_hour": 3600
},
"minimize_vehicles": true
},
"options": {
"runtime": {
"seed": 42,
"time_limit_s": 5
}
},
"vehicles": [
{
"capacity": {
"weight": 500
},
"id": "v1",
"shifts": [
{
"end": {
"coordinate": [
3.7174,
51.0543
]
},
"from": "2026-07-01T08:00:00+02:00",
"start": {
"coordinate": [
3.7174,
51.0543
]
},
"to": "2026-07-01T17:00:00+02:00"
}
]
}
],
"routes": [
{
"job_ids": [
"job-1"
],
"vehicle": "v1"
}
]
}
'import requests
url = "https://api.solvice.io/v3/routing/evaluate"
payload = {
"jobs": [
{
"demand": { "weight": 10 },
"id": "job-1",
"location": { "coordinate": [3.725, 51.05] },
"service_duration_s": 300
}
],
"objective": {
"costs": {
"currency": "EUR",
"per_travel_hour": 3600
},
"minimize_vehicles": True
},
"options": { "runtime": {
"seed": 42,
"time_limit_s": 5
} },
"vehicles": [
{
"capacity": { "weight": 500 },
"id": "v1",
"shifts": [
{
"end": { "coordinate": [3.7174, 51.0543] },
"from": "2026-07-01T08:00:00+02:00",
"start": { "coordinate": [3.7174, 51.0543] },
"to": "2026-07-01T17:00:00+02:00"
}
]
}
],
"routes": [
{
"job_ids": ["job-1"],
"vehicle": "v1"
}
]
}
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: [
{
demand: {weight: 10},
id: 'job-1',
location: {coordinate: [3.725, 51.05]},
service_duration_s: 300
}
],
objective: {costs: {currency: 'EUR', per_travel_hour: 3600}, minimize_vehicles: true},
options: {runtime: {seed: 42, time_limit_s: 5}},
vehicles: [
{
capacity: {weight: 500},
id: 'v1',
shifts: [
{
end: {coordinate: [3.7174, 51.0543]},
from: '2026-07-01T08:00:00+02:00',
start: {coordinate: [3.7174, 51.0543]},
to: '2026-07-01T17:00:00+02:00'
}
]
}
],
routes: [{job_ids: ['job-1'], vehicle: 'v1'}]
})
};
fetch('https://api.solvice.io/v3/routing/evaluate', 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/evaluate",
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' => [
[
'demand' => [
'weight' => 10
],
'id' => 'job-1',
'location' => [
'coordinate' => [
3.725,
51.05
]
],
'service_duration_s' => 300
]
],
'objective' => [
'costs' => [
'currency' => 'EUR',
'per_travel_hour' => 3600
],
'minimize_vehicles' => true
],
'options' => [
'runtime' => [
'seed' => 42,
'time_limit_s' => 5
]
],
'vehicles' => [
[
'capacity' => [
'weight' => 500
],
'id' => 'v1',
'shifts' => [
[
'end' => [
'coordinate' => [
3.7174,
51.0543
]
],
'from' => '2026-07-01T08:00:00+02:00',
'start' => [
'coordinate' => [
3.7174,
51.0543
]
],
'to' => '2026-07-01T17:00:00+02:00'
]
]
]
],
'routes' => [
[
'job_ids' => [
'job-1'
],
'vehicle' => 'v1'
]
]
]),
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/evaluate"
payload := strings.NewReader("{\n \"jobs\": [\n {\n \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\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/evaluate")
.header("Authorization", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"jobs\": [\n {\n \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.solvice.io/v3/routing/evaluate")
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 \"demand\": {\n \"weight\": 10\n },\n \"id\": \"job-1\",\n \"location\": {\n \"coordinate\": [\n 3.725,\n 51.05\n ]\n },\n \"service_duration_s\": 300\n }\n ],\n \"objective\": {\n \"costs\": {\n \"currency\": \"EUR\",\n \"per_travel_hour\": 3600\n },\n \"minimize_vehicles\": true\n },\n \"options\": {\n \"runtime\": {\n \"seed\": 42,\n \"time_limit_s\": 5\n }\n },\n \"vehicles\": [\n {\n \"capacity\": {\n \"weight\": 500\n },\n \"id\": \"v1\",\n \"shifts\": [\n {\n \"end\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"from\": \"2026-07-01T08:00:00+02:00\",\n \"start\": {\n \"coordinate\": [\n 3.7174,\n 51.0543\n ]\n },\n \"to\": \"2026-07-01T17:00:00+02:00\"\n }\n ]\n }\n ],\n \"routes\": [\n {\n \"job_ids\": [\n \"job-1\"\n ],\n \"vehicle\": \"v1\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"routes": [],
"summary": {
"elapsed_ms": 12,
"jobs_assigned": 1,
"jobs_unassigned": 0,
"status": "feasible",
"total_distance_m": 8450,
"total_duration_s": 1980,
"total_violations": 0,
"vehicles_used": 1
},
"unassigned": []
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}{
"code": "VALIDATION_ERROR",
"field": "/vehicles",
"message": "At least one vehicle is required",
"status": "BAD_REQUEST"
}