Skip to content

Optimized Routing





Optimized routing helps you and your team save time and cut travel costs by finding an optimal route between multiple locations. It is similar to the normal route endpoint, but only the start and end point are guaranteed to be in order. This lets you make deliveries, sales calls, and more as quickly and cheaply as possible.

Optimized routing includes the same versatility as standard routing, with features including:

  • Vehicle attributes (weight, height, width, top speed, etc.)
  • Prefer or avoid highways, toll roads, and ferries
  • Number of passengers, for HOV lane usage
  • Hill avoidance for bicycles, motor scooters, and pedestrians
  • Support for guidance in over 25 languages


Example Code


Get started quickly with code samples using our official SDKs or cURL. Official SDKs include documentation of all request and response models, either as separate pages, or through docstrings and autocomplete in most IDEs. If you are building for another language or want to try out requests in a browser, refer to our interactive API reference.

import { RoutingApi, Configuration, OptimizedRouteRequest } from '@stadiamaps/api';

// If you are writing for a backend application or can't use domain-based auth,
// then you'll need to add your API key like so:
// const config = new Configuration({ apiKey: "YOUR-API-KEY" });
// You can also use our EU endpoint to keep traffic within the EU using the basePath option:
// const config = new Configuration({ basePath: "" });
// const api = new RoutingApi(config);
const api = new RoutingApi();

const locationA = {
    "lon": -76.306572,
    "lat": 40.042072
const locationB = {
    "lon": -76.781559,
    "lat": 39.992115
const locationC = {
    "lon": -76.6956,
    "lat": 39.984519
const req: OptimizedRouteRequest = {
    locations: [
    costing: "auto",
    costingOptions: {
        auto: {
            useHighways: 0.3
    directionsOptions: {
        units: DistanceUnit.Mi
const res = await api.optimizedRoute({ optimizedRouteRequest: req });
import os
import stadiamaps
from import ApiException

# You can also use our EU endpoint to keep traffic within the EU like so:
# configuration = stadiamaps.Configuration(host="")
configuration = stadiamaps.Configuration()

# Configure API key authentication (ex: via environment variable).
configuration.api_key['ApiKeyAuth'] = os.environ["API_KEY"]

with stadiamaps.ApiClient(configuration) as api_client:
    # Create an instance of the API class
    api_instance = stadiamaps.RoutingApi(api_client)

        location_a = {"lat": 40.042072, "lon": -76.306572}
        location_b = {"lat": 39.992115, "lon": -76.781559}
        location_c = {"lat": 39.984519, "lon": -76.6956}
        req = stadiamaps.OptimizedRouteRequest(
            costing_options=stadiamaps.CostingOptions(auto=stadiamaps.AutoCostingOptions(use_highways=0.3)),  # Take the scenic route ;)

        res = api_instance.optimized_route(req)
    except ApiException as e:
        # Add your error handling here
        print("Exception when calling the Stadia Maps API: %s\n" % e)
// Imports (at the top of your source file; we've used some wildcard imports for simplicity)
import com.stadiamaps.api.apis.*
import com.stadiamaps.api.auth.ApiKeyAuth
import com.stadiamaps.api.infrastructure.*
import com.stadiamaps.api.models.*

// Set your API key (from an environment variable in this case)
val apiKey = System.getenv("STADIA_API_KEY") ?: throw RuntimeException("API Key not set")

// Defining the host is optional and defaults to
// You can also use our EU endpoint to keep traffic within the EU like so:
// val client = ApiClient(baseUrl = "")
val client = ApiClient()
client.addAuthorization("ApiKeyAuth", ApiKeyAuth("query", "api_key", apiKey))

// Configure a service for the group of APIs we want to talk to
val service = client.createService(

// Set up the request. Note: if you're using Kotlin with coroutines, you can also await
// rather than executing synchronously when using suspend functions.
val locations = listOf(
    Coordinate(40.042072, -76.306572), Coordinate(39.992115, -76.781559), Coordinate(39.984519, -76.6956), Coordinate(40.042072, -76.306572)
val costingOptions = CostingOptions(auto = AutoCostingOptions(useHighways = 0.3))  // Take the scenic route ;)
val directionsOptions = DirectionsOptions(units = DistanceUnit.mi, language = ValhallaLanguages.enMinusGB)
val req = OptimizedRouteRequest(
    id = "route",
    locations = locations,
    costing =,
    costingOptions = costingOptions,
    directionsOptions = directionsOptions
val res = service.optimizedRoute(req).execute()

if (res.isSuccessful) {
    println("Found result: ${res.body()}")
} else {
    println("Request failed with error code ${res.code()}")
import StadiaMaps

// This setup code can go anywhere before you actually make an API call (typically in your app init)
func setupStadiaMapsAPI() {
    // Set your API key
    StadiaMapsAPI.customHeaders = ["Authorization": "Stadia-Auth YOUR-API-KEY"]
    // Optionally use our EU endpoint to keep traffic within the EU
    // StadiaMapsAPI.basePath = ""

// This function demonstrates how to call the Stadia Maps API.
// If you have not yet adopted async/await in your Swift codebase, you can use the Task API
// to call async functions in a non-async context:
func myFunction() async throws {
    let locationA = Coordinate(lat: 40.042072, lon: -76.306572)
    let locationB = Coordinate(lat: 39.992115, lon: -76.781559)
    let locationC = Coordinate(lat: 39.984519, lon: -76.6956)
    let req = OptimizedRouteRequest(id: "optimized_route",
                                    locations: [
                                    costing: .auto,
                                    costingOptions: CostingOptions(auto: AutoCostingOptions(useHighways: 0.3)),  // Take the scenic route :)
                                    directionsOptions: DirectionsOptions(units: .mi))
    let res = try await RoutingAPI.optimizedRoute(optimizedRouteRequest: req)

    // Do something with the response...
curl -X POST -H "Content-Type: application/json" -d '{
    "locations": [
            "lon": -76.306572,
            "lat": 40.042072
            "lon": -76.781559,
            "lat": 39.992115
            "lon": -76.6956,
            "lat": 39.984519
            "lon": -76.306572,
            "lat": 40.042072
    "costing": "auto",
    "costing_options": {
        "auto": {
            "use_highways": 0.3
    "directions_options": {
        "units": "miles"
}' ""

Complementary APIs

Optimized routing uses geographic coordinates to specify the locations. If you have human-readable addresses, you can use our forward geocoding and structured geocoding APIs to convert to latitude and longitude.

For certain logistics applications, the time/distance matrix may also be useful.

Next Steps