Directions API

Route service allows to make the fastest and the most efficient route between two or more locations (up to 50 waypoints). Nevertheless, trip service solves the Traveling Salesman problem, optimizing routes with up to 50 waypoints.

We use the OSRM as the routing engine, however, instead of the OSM data, our own road network - the most comprehensive road network for Latvia - is used. Directions API currently suppports profiles for both pedestrians and drivers of automobiles. You can read the full documentation here.

If you are interested in using other types of OSRM services (table, nearest, match, tile), e-mail us!

API URL

The request URL should match the following pattern:

https://api.kartes.lv/v3//directions/{profile}/{service}/{coordinates}?

The response is given in JSON

The HTTP GET and POST request methods are used.

Route service

The request URL should match the following pattern:

https://api.kartes.lv/v3//directions/{profile}/route/{coordinates}?

Query parameters

The query might consist of the following GET parameters:

Parameter Description Values
profile Mode of transportation. For now, there are two profiles. Mandatory
  • driving - car
  • walking - pedestrian
coordinates String of format {longitude},{latitude};{longitude},{latitude} (up to 50 points) or polyline({polyline}) or polyline6({polyline6}) x1,y1;x2,y2;…;xn,yn, where:
  • x1 - the x-coordinate of the starting point.
  • y1 - the y-coordinate of the starting point;
  • x2 - the x-coordinate of the next waypoint;
  • y2 - the y-coordinate of the next waypoint;
  • xn - the x-coordinate of the last waypoint;
  • yn - the y-coordinate of the last waypoint.
alternatives Searches for alternative routes.
  • true or 1 - gives a single alternative route;
  • false or 0 - no alternatives (default value);
geometries Returned route geometry format.
  • polyline (default value)
  • polyline6
  • geojson
steps Returns route steps for each route leg.
  • true
  • false (default value)
overview Adds overview geometry either full, simplified (according to highest zoom level it could be displayed on), or not at all
  • simplified - simplified geometry (default value))
  • full - detailed geometry
  • false - none
summary Summary of the route taken as a string. Names of the two major roads are used (e.g., "Daugavgrīvas iela, Krišjāņa Valdemāra iela"). Active if steps=true
  • true - returns names of the major roads (if the route is too short, gives empty result)
  • false
annotations Returns additional metadata (see below) for each coordinate along the route geometry.
  • true;
  • false (default value).
continue_straight Forces the route to keep going straight at waypoints constraining uturns there even if it would be faster. By default, uturns are constrained.
  • true - continues straight at a waypoint (default value);
  • false - can make a uturn if faster.
skip_waypoints Skip waypoints information.
  • true;
  • false (default value).
generate_hints Generate hints (uuid).
  • true (default value);
  • false
approaches Will respect the sides of the road at the terminus Format:
terminus 1;terminus 2
  • unrestricted (default value);
  • curb .

Response parameters

The response consists of the following parameters and objects:

Parametrs Skaidrojums
code Request success. Ok if successful.
waypoints Object used to describe waypoint on a route.
hint uuid.
distance The distance from the given coordinates to the destination coordinates in meters.
location The coordinates of the location (waypoint, intersection, maneuver) that are used instead of the given coordinates.
name Terminus street name (if any).
routes Object used to describe routes.
legs The legs between the given waypoints, an array of RouteLeg objects. The leg or legs are being followed by distance, duration, weight, summary parameters.
  steps Object used to describe steps. There are more parameters for leg (look at OSRM API documantation).
  weight Weight (for prioritization).
  distance Length (meters).
  summary Descriptive name (for example, "Daugavgrīvas iela, Krišjāņa Valdemāra iela").
  duration Duration (sec).
weight_name Weight name.
geometry The whole geometry of the route value depending on overview parameter, format depending on the geometries parameter.
weight The calculated weight of the route.
distance Length (meters).
duration Duration (sec).

Error codes

Status code Description
200 Wrong input data. Server can’t respond due to client error.
404 No location found. The URL is not recognized; the resource does not exist.
5xx Server error.

Examples

Input:

https://api.kartes.lv/v3//directions/driving/route/24.106237,56.964682;24.094009,56.960553?overview=full&annotations=true&steps=true&geometries=geojson

Response:

{
    "code": "Ok",
    "routes": [
        {
            "geometry":
                {
                "coordinates": [
                    [
                        24.106207,
                        56.964683
                    ],
                    ...
                    [
                        24.09501,
                        56.95942
                    ]
                ],
                    "type":"LineString"
                },
            "legs": [
                {
                    "steps": [
                        {
                            "geometry": "g|tzIyfcrCbBFpBF|@BlAPf@H",
                            "maneuver": {
                                "bearing_after": 182,
                                "bearing_before": 0,
                                 "location": [
                                    24.106207,
                                    56.964683
                                ],
                                "type": "depart"
                            },
                            "mode": "driving",
                            "ref": "P1",
                            "driving_side": "right",
                            "name": "Pulkveža Brieža iela",
                            "intersections": [
                                {
                                    "out": 0,
                                    "entry": [
                                        true
                                    ],
                                    "location": [
                                        24.106207,
                                        56.964683
                                    ],
                                    "bearings": [
                                        182
                                    ]
                                },
                                {
                                    "out": 1,
                                    "in": 0,
                                    "entry": [
                                        false,
                                        true,
                                        true
                                    ],
                                    "bearings": [
                                        0,
                                        180,
                                        270
                                    ],
                                    "location": [
                                        24.10617,
                                        56.96418
                                    ]
                                }
                            ],
                            "weight": 26.1,
                            "duration": 29.3,
                            "distance": 220.1
                        },...
                    ],
                    "summary": "Hanzas iela, Eksporta iela",
                    "weight": 208.1,
                    "duration": 220,
                    "annotation": {
                        "speed": [
                            13.7,
                            13.8,
                            ...
                        ],
                        "metadata": {
                            "datasource_names": [
                                "lua profile"
                            ]
                        },
                        "nodes": [
                            4777473,
                            3090436,
                            ...
                        ],
                        "duration": [
                            4.1,
                            4.6,
                            ...
                        ],
                        "distance": [
                            55.991795,
                            63.44537,
                            ...
                        ],
                        "weight": [
                            3.6,
                            4.1,
                           ...
                        ],
                        "datasources": [
                            0,
                            0,
                            ...
                        ]
                    },
                    "distance": 1631.1
                }
            ],
            "weight_name": "routability"
            "weight": 208.1,
            "duration": 220,
            "distance": 1631.1
        }
    ],
    "waypoints": [
        {
            "hint": "aC0AgP___38DAAAAJwAAAAAAAAAAAAAAupanQDs9YEIAAAAAAAAAAAMAAAAsAAAAAAAAAAAAAAAgAAAA39RvAUs2ZQP91G8BSjZlAwAAbwsqWsg3",
            "distance": 1.827851,
             "name": "Pulkveža Brieža iela",
            "location": [
                24.106207,
                56.964683
            ]
        },
        {
            "hint": "Wm8KgHNvCoAAAAAACQAAABwCAAB-AQAAAAAAAJEqrUA5zG1Dpi5fQwAAAAAKAAAANwIAAJEBAAAgAAAAIqlvAbwhZQM5pW8BKSZlAwIAfw4qWsg3",
            "distance": 140.090272,
            "name": "",
            "location": [
                24.09501,
                56.95942
            ]
        }
    ]
}

Use examples

Example of implementing the Directions API in a Leaflet map.

First, you need to include the Leaflet library in your HTML code (you should use the latest version of the library, according to the official documentation):

<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
    integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
    crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
    integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
    crossorigin=""></script>

You can create a map element in HTML:

<div id="map" style="width: 100%; height: 100vh;"></div>

Then, you can initialize the map in JavaScript and create a class for the Directions API:

const api_key = 'your_api_key_here'; // Replace with your actual API key

const map = L.map('map', {
    layers: [
        L.tileLayer.wms(`https://wms{s}.kartes.lv/${api_key}/wgs/15bw/`, {
            subdomains: ['', '1', '2', '3', '4'],
            attribution: '<a href="https://balticmaps.eu" target="_blank">Jāņa sēta</a>',
        }),
    ],
    center: [56.96, 24.11],
    zoom: 12,
})

class DirectionsApi {
    constructor() {
        this.apiKey = api_key;
        this.baseUrl = 'https://api.kartes.lv/v3';
    }

    // Method to fetch directions
    async getDirections(coordinates, options = {}) {
        const coords = coordinates.map(innerArray => innerArray.join(',')).join(';');

        // Allow various options to be passed to the API
        const queryString = new URLSearchParams({
            overview: options.overview || 'full',
            annotations: options.annotations || 'true',
            steps: options.steps || 'true',
            geometries: options.geometries || 'geojson',
            source: options.source || 'first',
            destination: options.destination || 'last',
            roundtrip: options.roundtrip || 'false',
        }).toString();

        const url = `${this.baseUrl}/${this.apiKey}/directions/driving/route/${coords}?${queryString}`;

        try {
            const response = await fetch(url);

            // Check if the response is ok (status code 200-299)
            if (!response.ok) {
                throw new Error(`Error fetching data: ${response.statusText}`);
            }

            const data = await response.json();
            return { success: true, data };
        } catch (error) {
            console.error('Fetch error:', error);
            return { success: false, error: error.message };
        }
    }
}

To display the route in a Leaflet map, you need to convert the route to GeoJSON format. You can do it using a function like this, which writes the entire route, its legs, and waypoints in GeoJSON format:

const convertToGeoJSON = (data) => {
    if (data.code !== "Ok") {
        throw new Error("Invalid data");
    }

    const geojson = {
        type: "FeatureCollection",
        features: []
    };

    // Convert trips to GeoJSON features
    data.trips.forEach(trip => {
        // Add the main trip route as a LineString
        geojson.features.push({
            type: "Feature",
            geometry: trip.geometry,
            properties: {
                type: "trip",
                summary: trip.legs.map(leg => leg.summary).join(", "),
                weight: trip.weight,
                duration: trip.duration,
                distance: trip.distance
            }
        });

        // Add each step in the trip as a separate feature
        trip.legs.forEach(leg => {
            leg.steps.forEach(step => {
                geojson.features.push({
                    type: "Feature",
                    geometry: step.geometry,
                    properties: {
                        type: "step",
                        mode: step.mode,
                        maneuver: step.maneuver,
                        name: step.name,
                        duration: step.duration,
                        distance: step.distance,
                        drivingSide: step.driving_side,
                        intersections: step.intersections
                    }
                });
            });
        });
    });

    // Convert waypoints to GeoJSON features
    data.waypoints.forEach(waypoint => {
        geojson.features.push({
            type: "Feature",
            geometry: {
                type: "Point",
                coordinates: waypoint.location
            },
            properties: {
                type: "waypoint",
                waypoint_index: waypoint.waypoint_index,
                trips_index: waypoint.trips_index,
                hint: waypoint.hint,
                distance: waypoint.distance,
                name: waypoint.name
            }
        });
    });

    return geojson;
}

Finally, you can use the DirectionsAPI class to fetch the route and display it on the map:

// Instantiate the DirectionsAPI class with your API key
const api = new DirectionsAPI(api_key);

// Example stops
const coordinates = [
    [24.12, 56.92],
    [24.13, 56.95],
    [24.11, 56.91],
    [24.16, 56.98]
];

api.getDirections(coordinates)
    .then(result => {
        if (!result.success) {
            console.error('Error:', result.error); // Handle the error
            return;
        }

        // Add the route in GeoJSON format to the map
        L.geoJSON(convertToGeoJSON(result.data), {
            style: (feature) => {
                color: "rgba(20, 137, 255, 0.7)",
                weight: 5
            }
        }).bindPopup((layer) => `${layer.feature.properties.distance} m`}).addTo(map);
    });

The result will be a map with the route displayed on it.

Route example in Leaflet map

Trip service

The trip service solves the Traveling Salesman Problem, providing the most efficient route and order between up to 50 points. Note that all input coordinates have to be connected for the trip service to work. The trip service is enabled by using the trip value (instead of route) as the service parameter.

Additional query parameters

Parameter Description Possible values
roundtrip Returned route is a roundtrip (route returns to the first location).
  • true - returns (default value). The first location is repeated in the response.
  • false - doesn't return
source Returned route starts at any or first coordinate.
  • any - can start at any of the given coordinates (default value)
  • first - starts at the first coordinates
destination Returned route ends at any or last coordinate.
  • any - can end at any of the given coordinates (default value);
  • last - ends at the last waypoint.

If source=any&destination=any, the returned roundtrip will still start at the first input coordinate by default.

Additional response parameters

Parameter Description
code If the request was successful, Ok.
waypoints Array of Waypoint objects representing all waypoints in input order.
trip_index Index to trips of the sub-trip the point was matched to.
waypoint_index Index of the point in the trip.
trips An array of Route objects that assemble the trace.

Examples

Input (not active with DEMO key):

https://api.kartes.lv/v3//directions/driving/trip/24.12,56.92;24.13,56.95;24.11,56.91;24.16,56.98?overview=full&annotations=true&steps=true&geometries=geojson&source=first&destination=last

Response:

{
    "code": "Ok",
    "waypoints": [
        {
            "waypoint_index": 0,
            "trips_index": 0,
            "hint": "Ev8JgE3_CYAiAAAAGQAAAF8AAADFAAAAmvGaQZ47V0EvUFNCIdLbQiIAAAAZAAAAXwAAAMUAAAAgAAAAoQtwAfGIZAPACnABwIdkAwMAPxIqWsg3",
            "distance": 36.624429,
            "location": [
                24.120225,
                56.920305
            ],
            "name": ""
        },
        {
            "waypoint_index": 2,
            "trips_index": 0,
            "hint": "ym0KgDVuCoBLAAAAAAAAAAAAAAA9AAAAVEIuQgAAAAAAAAAANckPQk4AAAAAAAAAAAAAAEAAAAAgAAAANDJwAcj8ZAPQMXAB8PxkAwAArxUqWsg3",
            "distance": 7.544916,
            "location": [
                24.1301,
                56.94996
            ],
            "name": ""
        },
        {
            "waypoint_index": 1,
            "trips_index": 0,
            "hint": "iB4BgKgeAYAeAAAAAAAAAPsAAAAFAAAA4KXHQQAAAAAhDlJDgfyMQB4AAAAAAAAA-wAAAAUAAAAgAAAAAuJvAQRiZAOw428BsGBkAw4Afw4qWsg3",
            "distance": 46.035301,
            "location": [
                24.10957,
                56.91034
            ],
            "name": "Tumes iela"
        },
        {
            "waypoint_index": 3,
            "trips_index": 0,
            "hint": "3WQKgPNkCoANAAAABwAAAGEBAAC0AAAAzD8DQab_YEAlWk5DVMvSQg4AAAAHAAAAcQEAAL4AAAAgAAAA_qZwASByZQMAp3ABIHJlAwgAXxUqWsg3",
            "distance": 0.12163,
            "location": [
                24.159998,
                56.98
            ],
            "name": ""
        }
    ],
    "trips": [
      {
        "legs": [
            {
            "steps": [
                {
                  "intersections": [
                    {
                      "classes": [
                        "unpaved"
                      ],
                      "out": 0,
                      "entry": [
                          true
                      ],
                      "location": [
                        24.120225,
                        56.920305
                      ],
                      "bearings": [
                        292
                      ]
                    },...
                  ],
                  "driving_side": "right",
                  "geometry": {
                    "coordinates": [
                      [
                        24.120225,
                        56.920305
                      ],...
                    ],
                    "type": "LineString"
                  },
                  "duration": 138.3,
                  "distance": 737.7,
                  "name": "",
                  "weight": 138.3,
                  "mode": "driving",
                  "maneuver": {
                    "bearing_after": 292,
                    "location": [
                      24.120225,
                      56.920305
                    ],
                    "type": "depart",
                    "bearing_before": 0,
                    "modifier": "left"
                  },
                },...
              ],
            "weight": 434.5,
            "distance": 3852.5,
            "annotation": {
              "speed": [
                5.4,
                5.6,
                ...
              ],
              "metadata": {
                "datasource_names": [
                  "lua profile"
                ]
              },
              "nodes": [
                4539416,
                5195632,
                ...
              ],
              "duration": [
                2.5,
                19.7,
                ...
              ],
              "distance": [
                13.413894,
                109.603385,
                ...
              ],
              "weight": [
                2.5,
                19.7,
                ...
              ],
              "datasources": [
                0,
                0,
                ...
              ]
            },
            "summary": "Mūkusalas iela, Tumes iela",
            "duration": 465.8,
          },...
        ],
        "weight_name": "routability",
        "geometry": {
            "coordinates": [
              [
                24.120225,
                56.920305
              ],
              ...
              [
                24.120225,
                56.920305
              ]
            ],
            "type": "LineString"
          },
        "weight": 2680.1,
        "distance": 26133.8,
        "duration": 2885.3
      }
    ]
  }