Skip to main content

Optimal Routes API

Given an unordered list of stops, work out the most efficient order to visit them in.


Overview & Solution​

A driver with a dozen stops on their list, entered in whatever order they came in, ends up zig-zagging across town instead of working through them efficiently. Someone has to sit down and figure out a sensible visiting order - or the driver just wings it.

The Optimal Routes API does that ordering for you. Hand it a list of stops in any order, and it hands back the same stops resequenced into an efficient route to visit them in.


Industry Use Cases​

1. Field Sales & Van Delivery​

  • Daily stop sequencing - turn today's list of retailer or customer stops into an order that doesn't backtrack across the same area twice.

2. Field Service & Maintenance​

  • Technician visit order - sequence a technician's assigned jobs for the day into an efficient route instead of visiting them in ticket-creation order.

3. Local Pickup & Delivery​

  • Multi-stop run planning - sequence a batch of pickups or drop-offs assigned to one driver on one route.


API reference​

Route and Journey Intelligence APIs · API key only

Endpoints​

All requests need only your API key, as the api-key query parameter - no bearer token:

?api-key=<apiKey>

Reorder stops into the most efficient visiting sequence​

POST /routing/optimize

Base URL: https://api-gw.sovereignsolutions.com/gateway

Request Parameters

ParameterInTypeRequiredDescriptionExample
locationsbodyarrayNoStops to visit, in any order. The first stop is the start.
locations[]bodyobjectNo
locations[].lonbodynumberNoLongitude of the point, decimal degrees.
locations[].latbodynumberNoLatitude of the point, decimal degrees.
costingbodystringNoTravel mode used for costing. The examples use auto (driving) and pedestrian (walking).
unitsbodystringNoDistance unit: km.

Request body

{
"locations": [
{
"lon": 80.2675007,
"lat": 13.0355685
},
{
"lon": 80.267291,
"lat": 13.036289
},
{
"lon": 80.267437,
"lat": 13.03525
},
{
"lon": 80.267779,
"lat": 13.034928
},
{
"lon": 80.251724,
"lat": 13.032119
}
],
"costing": "auto",
"units": "km"
}

Response Schema

200 OK

{
"trip": {
"locations": [
{
"type": "break",
"lat": 13.035568,
"lon": 80.2675,
"side_of_street": "left",
"original_index": 0
},
{
"type": "break",
"lat": 13.034928,
"lon": 80.267779,
"side_of_street": "left",
"original_index": 3
},
{
"type": "break",
"lat": 13.03525,
"lon": 80.267437,
"side_of_street": "right",
"original_index": 2
},
{
"type": "break",
"lat": 13.036289,
"lon": 80.267291,
"side_of_street": "right",
"original_index": 1
},
{
"type": "break",
"lat": 13.032119,
"lon": 80.251724,
"side_of_street": "right",
"original_index": 4
}
],
"legs": [
{
"maneuvers": [
{
"type": 3,
"instruction": "Drive southwest on Subbarayan Salai.",
"verbal_succinct_transition_instruction": "Drive southwest.",
"verbal_pre_transition_instruction": "Drive southwest on Subbarayan Salai.",
"verbal_post_transition_instruction": "Continue for 400 meters.",
"street_names": [
"Subbarayan Salai"
],
"time": 39.918,
"length": 0.442,
"cost": 67.968,
"begin_shape_index": 0,
"end_shape_index": 11,
"travel_mode": "drive",
"travel_type": "car"
},
{
"type": 15,
"instruction": "Turn left onto Venkatesa Agraharam Road.",
"verbal_transition_alert_instruction": "Turn left onto Venkatesa Agraharam Road.",
"verbal_succinct_transition_instruction": "Turn left. Then Turn right onto Sathyani Muthu Street.",
"verbal_pre_transition_instruction": "Turn left onto Venkatesa Agraharam Road. Then Turn right onto Sathyani Muthu Street.",
"verbal_post_transition_instruction": "Continue for 50 meters.",
"street_names": [
"Venkatesa Agraharam Road"
],
"time": 11.643,
"length": 0.048,
"cost": 33.968,
"begin_shape_index": 11,
"end_shape_index": 14,
"verbal_multi_cue": true,
"travel_mode": "drive",
"travel_type": "car"
}
],
"summary": {
"has_time_restrictions": false,
"has_toll": false,
"has_highway": false,
"has_ferry": false,
"min_lat": 13.029259,
"min_lon": 80.263792,
"max_lat": 13.0357,
"max_lon": 80.268026,
"time": 253.396,
"length": 1.87,
"cost": 473.711
},
"shape": "gjszWiacbxCbGtDvSpMlZbUdDlG`NtYzGb_@jF~Q`Q|`@hD`FpS~YhCfCtC}DdI{HnBoCrJ~If]dAhTdArRTjACrJl@b\\fBrhBbQ`B}PXuKb@wVV_NLaGXsHLkZ@_ArAi]j@oT}u@gKqc@cEsZaDiD_@yMeCcJcDq`Aa^{AsDeBiBg~@sLoZiEuFy@eE[wCAcA@wAFsElCsKx@"
}
],
"summary": {
"has_time_restrictions": false,
"has_toll": false,
"has_highway": false,
"has_ferry": false,
"min_lat": 13.029259,
"min_lon": 80.25148,
"max_lat": 13.036045,
"max_lon": 80.268026,
"time": 549.848,
"length": 4.36,
"cost": 1762.634
},
"status_message": "Found route between points",
"status": 0,
"units": "kilometers",
"language": "en-US"
}
}
FieldTypeDescription
tripobject
trip.locationsarrayStops in the optimized visiting order.
trip.locations[]object
trip.locations[].typestring
trip.locations[].latnumber
trip.locations[].lonnumber
trip.locations[].side_of_streetstringSide of the street the stop is on.
trip.locations[].original_indexintegerPosition of this stop in your request - use it to map the new order back to your input.
trip.legsarrayOne leg between each pair of consecutive stops.
trip.legs[]object
trip.legs[].maneuversarrayTurn-by-turn instructions for the leg.
trip.legs[].maneuvers[]object
trip.legs[].maneuvers[].typeinteger
trip.legs[].maneuvers[].instructionstringHuman-readable instruction.
trip.legs[].maneuvers[].verbal_succinct_transition_instructionstring
trip.legs[].maneuvers[].verbal_pre_transition_instructionstring
trip.legs[].maneuvers[].verbal_post_transition_instructionstring
trip.legs[].maneuvers[].street_namesarray
trip.legs[].maneuvers[].street_names[]string
trip.legs[].maneuvers[].timenumberTime for this maneuver, seconds.
trip.legs[].maneuvers[].lengthnumberLength of this maneuver, in units.
trip.legs[].maneuvers[].costnumber
trip.legs[].maneuvers[].begin_shape_indexinteger
trip.legs[].maneuvers[].end_shape_indexinteger
trip.legs[].maneuvers[].travel_modestring
trip.legs[].maneuvers[].travel_typestring
trip.legs[].summaryobject
trip.legs[].summary.has_time_restrictionsboolean
trip.legs[].summary.has_tollboolean
trip.legs[].summary.has_highwayboolean
trip.legs[].summary.has_ferryboolean
trip.legs[].summary.min_latnumber
trip.legs[].summary.min_lonnumber
trip.legs[].summary.max_latnumber
trip.legs[].summary.max_lonnumber
trip.legs[].summary.timenumberLeg travel time, seconds.
trip.legs[].summary.lengthnumberLeg length, in units.
trip.legs[].summary.costnumber
trip.legs[].shapestringLeg geometry as an encoded polyline.
trip.summaryobject
trip.summary.has_time_restrictionsboolean
trip.summary.has_tollbooleantrue when the route uses a toll road.
trip.summary.has_highwaybooleantrue when the route uses a highway.
trip.summary.has_ferrybooleantrue when the route uses a ferry.
trip.summary.min_latnumber
trip.summary.min_lonnumber
trip.summary.max_latnumber
trip.summary.max_lonnumber
trip.summary.timenumberTotal travel time, seconds.
trip.summary.lengthnumberTotal length, in units.
trip.summary.costnumber
trip.status_messagestringResult message.
trip.statusinteger0 when a route was found.
trip.unitsstringDistance unit used in the response.
trip.languagestringLanguage of the instructions.

Example​

curl -X POST 'https://api-gw.sovereignsolutions.com/gateway/routing/optimize?api-key=$API_KEY' \
-H 'Content-Type: application/json' \
-d '{"locations": [{"lon": 80.2675007, "lat": 13.0355685}, {"lon": 80.267291, "lat": 13.036289}, {"lon": 80.267437, "lat": 13.03525}, {"lon": 80.267779, "lat": 13.034928}, {"lon": 80.251724, "lat": 13.032119}], "costing": "auto", "units": "km"}'

Notes​

The example response is shortened to the first leg; a real response has one leg between each pair of consecutive stops.