Endpoints
Base URL¶
https://opt.route.optimiser.app/v2
Use this URL as the base for all requests on this page.
Synchronous Route Optimisation API¶
POST https://opt.route.optimiser.app/v2/vrp
A synchronous endpoint for Route Optimisation requests. The request blocks until the optimization completes and returns the full solution immediately. Multi-shift requests use this same endpoint; see Multi-Shift.
Example Request
{
"drivers": [
{
"uid": "drvid1",
"shift_start": 8,
"shift_end": 17,
"start": {"lat": -33.867798, "lon": 151.166256},
"end": "start"
}
],
"jobs": [
{
"uid": "uid1",
"duration": 2,
"location": {"lat": -33.849489, "lon": 151.127482}
},
{
"uid": "uid2",
"duration": 2,
"location": {"lat": -33.880661, "lon": 151.183096}
},
{
"uid": "uid3",
"duration": 2,
"location": {"lat": -33.913168, "lon": 151.262267}
}
],
"settings": {}
}
Example Response
{
"runs": [
{
"driver": {
"uid": "drvid1",
"shift_start": "08:00:00",
"shift_end": "17:00:00",
"run": 1,
"seq": 0,
"location": {
"lon": 151.166256,
"lat": -33.867798
},
"end_location": {
"lon": 151.166256,
"lat": -33.867798
}
},
"jobs": [
{
"uid": "uid1",
"duration": 120,
"eta": "08:09:45",
"etd": "08:11:45",
"run": 1,
"seq": 1,
"location": {
"lon": 151.127482,
"lat": -33.849489
}
},
{
"uid": "uid2",
"duration": 120,
"eta": "08:24:12",
"etd": "08:26:12",
"run": 1,
"seq": 2,
"location": {
"lon": 151.183096,
"lat": -33.880661
}
},
{
"uid": "uid3",
"duration": 120,
"eta": "08:42:32",
"etd": "08:44:32",
"run": 1,
"seq": 3,
"location": {
"lon": 151.262267,
"lat": -33.913168
}
}
]
}
],
"unserved_jobs": []
}
Asynchronous Route Optimisation API¶
Use this API for long-running optimization problems. It follows a Post and Poll pattern:
- POST to start the optimization and receive a unique ID
- GET the status endpoint to check progress
- GET the solution endpoint to retrieve the final solution
Start Optimisation¶
POST https://opt.route.optimiser.app/v2/polling/vrp
Starts an asynchronous optimization. Returns immediately with a 202 Accepted response containing URLs for polling status and retrieving the solution.
Request Body
Use the same RoutingProblem format as the synchronous endpoint. A multi-shift request uses this same body: put multi_shift on every Driver instead of shift_start / shift_end. See Multi-Shift.
{
"drivers": [
{
"uid": "drvid1",
"shift_start": 8,
"shift_end": 17,
"start": {"lat": -33.867798, "lon": 151.166256},
"end": "start"
}
],
"jobs": [
{
"uid": "uid1",
"duration": 2,
"location": {"lat": -33.849489, "lon": 151.127482}
},
{
"uid": "uid2",
"duration": 2,
"location": {"lat": -33.880661, "lon": 151.183096}
},
{
"uid": "uid3",
"duration": 2,
"location": {"lat": -33.913168, "lon": 151.262267}
}
],
"settings": {}
}
import json, os, requests, sys, time
from datetime import datetime
from zoneinfo import ZoneInfo
start_optimisation_url = 'https://opt.dev.route.optimiser.app/v0.40/polling/vrp'
auth_url = 'https://api.route.optimiser.app/api/auth/token'
headers = {'Content-Type': 'application/json'}
# Get a Token and put it in the Authorization header
body = {
'email': os.getenv('TAROT_EMAIL'),
'password': os.getenv('TAROT_PASSWORD'),
}
r = requests.post(auth_url, headers=headers, json=body)
token = r.json()['access_token']
headers['Authorization'] = f'Bearer {token}'
# Open Optimisation Problem File.
filename = sys.argv[1]
with open(filename) as f:
body = json.load(f)
# Make the Start Optimisation request
r = requests.post(start_optimisation_url, json=body, headers=headers)
# The response gives you the URLs you need to call for the remaining requests
resp = r.json()
status_url = resp['status_url']
solution_url = resp['solution_url']
# Start the Polling Loop
solving = True
while solving:
# Get the status, and leave the loop if the Optimiser has finished.
r = requests.get(status_url, headers=headers)
status = r.json()
solving = status['solving']
if not solving:
# The solver has finished, exit the loop
break
# If you're here, the Optimiser hasn't finished yet.
# Calculate the next time to check the status.
next_status_eta = datetime.fromisoformat(status['next_status_eta'])
delta = next_status_eta - datetime.now(tz=ZoneInfo('Europe/Paris'))
time_to_next_status = delta.total_seconds()
# Sleep until the next_status ETA,
# but if we've already passed it
# we'll just try again in 5 seconds.
time.sleep(time_to_next_status) if time_to_next_status > 0 else time.sleep(5)
# If you're here, the optimiser has finished solving.
# Let's get the Solution
r = requests.get(solution_url, headers=headers)
solution = r.json()
# Do something with it
with open(f'solution_{filename}', 'w') as f:
json.dump(f, solution)
Example Response (202 Accepted)
{
"uid": "01GG7AEX026F47CS4NK2JBCE5G",
"status_url": "https://opt.route.optimiser.app/v0.40/polling/vrp/01GG7AEX026F47CS4NK2JBCE5G/status",
"solution_url": "https://opt.route.optimiser.app/v0.40/polling/vrp/01GG7AEX026F47CS4NK2JBCE5G"
}
The response contains:
- uid: Unique identifier for this optimization request. Use this to poll status and retrieve results.
- status_url: URL to GET the current optimization status
- solution_url: URL to GET the final solution when complete
Get Status¶
GET https://opt.route.optimiser.app/v2/polling/vrp/{uid}/status
Polls the current status of an ongoing optimization.
Example Response (Solving in Progress)
{
"uid": "01GG7AEX026F47CS4NK2JBCE5G",
"timestamp": "2022-10-25T12:19:26.129294+02:00",
"message": "Started solving...",
"solving": true,
"cost": 0,
"next_status_eta": "2022-10-25T12:19:30.129134+02:00"
}
Example Response (Solving Complete)
{
"uid": "01GG7AEX026F47CS4NK2JBCE5G",
"timestamp": "2022-10-25T12:19:33.421031+02:00",
"message": "The Improvement Threshold has been reached.",
"solving": false,
"cost": 57516,
"next_status_eta": null
}
The response contains:
- uid: The unique identifier from the start request
- timestamp: When this status was recorded
- message: Human-readable description of the current state
- solving: Boolean flag indicating if optimization is still running
- cost: Current best solution cost. 0 while solving hasn't started computing costs
- next_status_eta: Recommended time to check status again (ISO 8601 format). null when solving is complete
Get Solution¶
GET https://opt.route.optimiser.app/v2/polling/vrp/{uid}
Retrieves the final optimization solution. Should be called after the status endpoint indicates solving: false.
Returns the same RoutingSolution format as the synchronous endpoint.
Example Response
{
"runs": [
{
"driver": {
"uid": "drvid1",
"shift_start": "08:00:00",
"shift_end": "17:00:00",
"run": 1,
"seq": 0,
"location": {
"lon": 151.166256,
"lat": -33.867798
},
"end_location": {
"lon": 151.166256,
"lat": -33.867798
}
},
"jobs": [
{
"uid": "uid1",
"duration": 120,
"eta": "08:09:45",
"etd": "08:11:45",
"run": 1,
"seq": 1,
"location": {
"lon": 151.127482,
"lat": -33.849489
}
},
{
"uid": "uid2",
"duration": 120,
"eta": "08:24:12",
"etd": "08:26:12",
"run": 1,
"seq": 2,
"location": {
"lon": 151.183096,
"lat": -33.880661
}
},
{
"uid": "uid3",
"duration": 120,
"eta": "08:42:32",
"etd": "08:44:32",
"run": 1,
"seq": 3,
"location": {
"lon": 151.262267,
"lat": -33.913168
}
}
]
}
],
"unserved_jobs": []
}