> ## Documentation Index
> Fetch the complete documentation index at: https://docs.justrouting.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Map Matching

> Snap noisy GPS traces to the real road network and get back the actual driven route.

## Overview

Map Matching API snaps a GPS trace to the real roads: send a timestamped coordinate sequence, get back the matched route (geometry, distance, duration) plus where each point landed on the network. Useful for cleaning delivery traces, analyzing actual driven paths, and mileage accounting.

Powered by the OSRM Match service.

## Endpoint

```
GET https://api.justrouting.tech/match/v1/{profile}/{coordinates}
```

| URL parameter | Description |
| - | - |
| `profile` | `driving` or `motorcycle` |
| `coordinates` | Trace points `{lng},{lat};{lng},{lat};...` — requires the `timestamps` parameter |

## Request Parameters

### Service options

| Parameter | Type | Default | Description |
| - | - | - | - |
| `timestamps` | string | — | UNIX timestamps in seconds for each point, **monotonically increasing**, one per coordinate |
| `radiuses` | string | `5` | Standard deviation of GPS precision in meters per point — use device-reported accuracy. The search area is sized so the correct candidate is found 99.9% of the time; larger radii mean more candidates and far-away candidates are penalized less |
| `steps` | bool | `false` | Return turn-by-turn steps |
| `geometries` | string | `polyline` | Same as [Directions](/api-reference/directions) |
| `overview` | string | `simplified` | Same as [Directions](/api-reference/directions) |
| `annotations` | string | `false` | Per-coordinate metadata along the route geometry: `true`, or a comma-separated list of `nodes`, `distance`, `duration`, `datasources`, `weight`, `speed` |
| `gaps` | string | `split` | Split into sub-traces on large timestamp jumps (`split` / `ignore`) |
| `tidy` | bool | `false` | Allow removing noisy points to improve matching quality |
| `waypoints` | string | all | Indices of trace points to treat as waypoints in the response, e.g. `0;3`. Default is to treat all trace points as waypoints |

### General options

These options apply to all routing services. Options that take one value per coordinate use the array-like encoding `{option}={element};{element}[;...]` — the number of elements must match the number of coordinates (except `generate_hints` and `exclude`). Pass an empty element to use the default for that coordinate, e.g. `bearings=;90,20;`.

| Parameter | Type | Default | Description |
| - | - | - | - |
| `bearings` | string | — | Limit snapping to segments with the given bearing; each element is `{value},{range}` with value 0–360° clockwise from true north and range 0–180° |
| `radiuses` | string | — | Limit snapping to the given radius in meters per coordinate, `unlimited` for no limit. For match, prefer the GPS-accuracy semantics in the Service options table above |
| `generate_hints` | bool | `true` | Add a `hint` to each response waypoint for reuse in later requests via `hints` |
| `hints` | string | — | Base64 `hint` from a previous response; speeds up snapping significantly |
| `approaches` | string | — | Restrict the road direction at a waypoint; per element `curb` / `opposite` / `unrestricted` (default) |
| `exclude` | string | — | Additive list of road classes to avoid, e.g. `exclude=motorway` |
| `snapping` | string | `default` | `any` snaps to any edge in the graph; `default` avoids edges that cannot be used as start/end points |
| `skip_waypoints` | bool | `false` | Remove waypoints from the response (they are still calculated, just not serialized) |

<Info>
  Large timestamp gaps (>60s) or improbable jumps **split the trace automatically** into multiple sub-traces — that's a feature, not a bug: one request can return several `matchings`.
</Info>

## Quickstart

<CodeGroup>
  ```bash curl theme={null}
  curl "https://api.justrouting.tech/match/v1/driving/103.71,1.35;103.72,1.35;103.73,1.35?timestamps=1694500000;1694500030;1694500060&radiuses=10;10;10&geometries=geojson" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```python Python theme={null}
  import justrouting

  client = justrouting.Client("YOUR_API_KEY")

  matching = client.match.get(justrouting.MatchRequest(
      coordinates=[[103.71, 1.35], [103.72, 1.35], [103.73, 1.35]],
      timestamps=[1694500000, 1694500030, 1694500060],
      radiuses=[10, 10, 10],
  ))

  for route in matching.matchings:
      print(f"confidence: {route.confidence:.2f}, distance: {route.distance:.0f} m")
  ```
</CodeGroup>

## Response

```json response-example.json theme={null}
{
  "code": "Ok",
  "tracepoints": [
    { "location": [103.7099, 1.3501], "matchings_index": 0, "waypoint_index": 0, "alternatives_count": 0 },
    { "location": [103.72, 1.35], "matchings_index": 0, "waypoint_index": 1, "alternatives_count": 2 },
    null
  ],
  "matchings": [
    {
      "confidence": 0.984,
      "geometry": "...",
      "distance": 2230.0,
      "duration": 300.0
    }
  ]
}
```

### Response fields

| Field | Description |
| - | - |
| `tracepoints[]` | One entry per input point, in input order; `null` marks dropped outliers |
| `tracepoints[].matchings_index` | Index of the entry in `matchings` this sub-trace was matched to |
| `tracepoints[].waypoint_index` | Position of the point inside the matched route |
| `tracepoints[].alternatives_count` | Number of probable alternative matchings; `0` means matched unambiguously — split the trace at these points for incremental map matching |
| `matchings[]` | Array of Route objects that assemble the trace, one per sub-trace |
| `matchings[].confidence` | Matching confidence, `0-1`; `1` is very confident |
| `matchings[].geometry` / `distance` / `duration` | The matched route that was actually driven (full Route object incl. `legs` and optional `steps`) |

## Best practices

* Use device-reported accuracy for `radiuses`: `Location.getAccuracy()` (Android) / `CLLocation.horizontalAccuracy` (iOS)
* High-frequency sampling (1–5s) gives the best traces; slow-speed drift points get dropped automatically
* All input coordinates must be in the same country (see [Coverage](/coverage))

## Related

* [Directions API](/api-reference/directions)
* [Errors](/errors)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.