Map Matching API

The Map Matching API lets you match geographical coordinates, such as GPS tracks, to the existing road network.

You can choose between various transportation modes, including cars, buses, delivery trucks, bicycles, and walking.

The API returns the reconstructed route geometry as well as details about the road segments that make up a route, including speed limit, road surface, and more. This makes it an excellent choice for route visualization and analysis.

Map Matching API Live Demo



Authentication and API key

To use the Map Marching API, you'll need a Geoapify API key. You can register and get an API Key.

We'll never ask for money before you're ready. Try us for FREE and upgrade to a paid plan when the needs of your project increase. For more information on our plans, visit the Pricing page.

How to get Geoapify API key

  1. Register on Geoapify MyProjects page
  2. Create a new project.
  3. Go to the API Keys section. One API key is generated automatically. You can generate multiple API keys per project if required.
  4. Optionally, you can protect the API key by listing allowed IP addresses, HTTP referrers, origins, and CORS.
  5. Choose "Map Matching API" and an API key to generate a URL and programming code.
  6. Press the "Try" button to execute the API call and get the result object example.

API reference

The Map Matching API works via POST request that allows sending up to 1000 of location points in the request body.

API URL


POST https://api.geoapify.com/v1/mapmatching

HEADERS 'Content-Type: application/json'


Request parameters

Name Description
apiKey Your Geoapify API key

Request body parameters

Name Description
waypoints Array of waypoints
waypoints.location Location represented as an array of coordinates: [longitude, latitude]
waypoints.timestamp Optional field. ISO formatted timestamp. Helps to calculate effective speed and filter incorrect waypoints.
waypoints.bearing Optional field. Number [0, 360]. Helps to determine speed more accurately.
mode Transportation or travel mode. Possible values: "drive", "walk", "bicycle"

Below is an example of the API call:

POST https://api.geoapify.com/v1/mapmatching?apiKey=YOUR_API_KEY
Content-Type: application/json

{
  {
   "mode":"drive",
   "waypoints":[
      {
         "timestamp":"2019-11-04T07:09:34.000Z",
         "location":[
            10.694703,
            47.567028
         ]
      },
      {
         "timestamp":"2019-11-04T07:09:45.000Z",
         "location":[
            10.6950319,
            47.567783
         ]
      },
      ...
    ]
  } 
}

Response Object

The response contains a GeoJSON FeatureCollection object with the "MultiLineString" type feature, which represents the route. The FeatureCollection object properties contain detailed route legs, steps, and matched points.

By default, the API response FeatureCollection contains only one feature so that you can address it as the first element of the collection, for example, result.feature[0]. Here is the structure of the feature properties object:

Name Description
distance Distance in meters for the whole route
time Time in seconds for the whole route
mode Requested transportation or travel mode
waypoints An array of MatchedWaypoint
legs An array of RouteLeg. Each leg represents separate parts of the route.

MatchedWaypoint

Contains information about an original waypoint and matched location.

Name Description
original_index Original index of the waypoint in request
location Matched location. An array of the coordinates: [lon, lat]
original_location Original location. An array of the coordinates: [lon, lat]
match_type Matched type. Possible values: matched, unmatched, interpolated
match_distance Distance in meters between matched and original locations
leg_index Leg index, the waypoint belongs to
step_index Step point, the waypoint belongs to

RouteLeg

Contains information about a route between 2 locations.

Name Description
distance Length of the route in meters
time Time in seconds for the route
steps An array of LegStep. Steps of the route

LegStep

Contains information about a step or segment of a RouteLeg:

Name Description
name Route step name. Usually a street name
road_class Road class. Possible values: unclassified, motorway, trunk, primary, secondary, tertiary, unclassified, residential, service_other
surface Type of surface. Possible values: paved_smooth, paved, paved_rough, compacted, dirt, gravel, path, impassable
traversability Traversability of the road segment. Possible values: forward, backward, both
speed Actual (calculated) speed
speed_limit Speed limit for the road segment
lane_count Number of lanes
toll Indicates whether the step is a part of a toll route
tunnel Indicates whether the step is a part of a tunnel
bridge Indicates whether the step is a part of a bridge
time Time in seconds required to pass the road segment
distance Length of the route segment in meters
begin_bearing Starting bearing
end_bearing Final bearing
from_index An index of the starting point for the segment in the corresponding feature coordinates array
to_index An index of the end point for the segment in the corresponding feature coordinates array
osm_way_id OpenStreetMap way id. You can get additional route parameters from the OSM database by using the id parameter. Note that the OpenStreetMap ID is not static and may be changed in the future.

Here is an example of the response object:

{
   "type":"FeatureCollection",
   "features":[
      {
         "type":"Feature",
         "properties":{
            "distance":4609,
            "time":324,
            "legs":[
               {
                  "time":324,
                  "distance":4609,
                  "steps":[
                     {
                        "speed":40,
                        "speed_limit":50,
                        "surface":"paved_smooth",
                        "lane_count":1,
                        "road_class":"unclassified",
                        "from_index":0,
                        "to_index":1,
                        "name":"Morisse",
                        "traversability":"both",
                        "time":1,
                        "distance":9,
                        "begin_bearing":25,
                        "end_bearing":25
                     },
                     ...
                  ]
               }
            ],
            "mode":"drive",
            "waypoints":[
               {
                  "original_index":0,
                  "location":[ 10.694686, 47.567033 ],
                  "original_location":[ 10.694703, 47.567028 ],
                  "match_type":"matched",
                  "match_distance":1.369,
                  "leg_index":0,
                  "step_index":0
               },
               ...
            ]
         },
         "geometry":{
            "type":"MultiLineString",
            "coordinates":[...]
}

Code samples

Get route steps

By default, the resulting Map Matching Feature geometry contains the whole route. However, sometimes it's required to split the route info the steps and points between them. Here is an example of how this can be done.

We used Turf library to operate with GeoJSON objects. You can install the library by running npm install @turf/helpers.

import {
  FeatureCollection,
  multiPoint,
  lineString,
  point,
  featureCollection,
  Feature,
  LineString,
  Point,
  MultiLineString,
} from "@turf/helpers";

// mapMatchingData => the FeatureCollection object returned by Map Matching API
function splitMapMatchingResultIntoSteps(mapMatchingData: FeatureCollection) {
  const legSteps: Feature<LineString, any>[] = [];
  const pointsBetweenSteps: Feature<Point, any>[] = [];

  if (!mapMatchingData.features?.length) {
    return null;
  }

  mapMatchingData.features[0].properties.legs.forEach((leg, index) => {
    const points: number[][] = (mapMatchingData.features[0]
      .geometry as MultiLineString).coordinates[index];

    leg.steps.forEach((step, index) => {
      const stepCoords: number[][] = points.slice(
        step.from_index,
        step.to_index + 1
      );
      legSteps.push(lineString(stepCoords, step));

      if (index > 0) {
        pointsBetweenSteps.push(point(points[step.from_index]));
      }
    });
  });

  return {
    steps: legSteps,
    points: pointsBetweenSteps
  }
}

Pricing

We use credits to calculate the cost of an API call. Credits are a unified unit that keeps our pricing policy straightforward and simple.

We offer four different Pricing Plans depending on usage amounts. First, you can sign up for our Free plan, which gives you 3,000 credits per day. Once your usage exceeds this amount, you can upgrade to a more advanced plan.

The pricing model for the Map Matching API is as follows:

Rule Description Example
100 waypoint = 1 credit Every 100 matched waypoints costs 1 credit 567 waypoints cost 6 credits