# Compare travel times with a matrix

Find the closest of several places by drive time with one call instead of many routes.

Before you start, you need an [API key](../start/quickstart.md). The matrix doesn't accept keyless calls from scripts.

## Send your sources and destinations

Each cell of the matrix costs about as much as one route, so one call is limited to 25 cells: `sources × destinations`. This asks for one origin and two destinations.

```bash
curl -s -X POST -H 'Content-Type: application/json' -H "X-API-Key: $QUADRUPER_KEY" \
  -d '{"sources":[[122.5621,10.7202]],"destinations":[[122.5444,10.6969],[122.53,10.70]]}' \
  https://quadruper.com/v2/matrix
```

## Read the rows and columns

Rows follow `sources`, and columns follow `destinations`. So `durations_s[0][1]` is the time from the first source to the second destination. This is an example response:

```json schema=matrix-response
{
  "sources": [{ "location": [122.5621, 10.7202], "snapped": true }],
  "destinations": [{ "location": [122.5444, 10.6969], "snapped": true }, { "location": [122.53, 10.7], "snapped": false }],
  "durations_s": [[690.0, null]],
  "distances_m": [[4210.0, null]],
  "conditions": { "assessed": false, "reason": "not_configured" },
  "attribution": [{ "source": "osm", "text": "© OpenStreetMap contributors", "license": "ODbL-1.0" }]
}
```

## Handle empty cells and pick a result

A `null` cell means there's no route, or that a point couldn't be snapped to a road. It isn't an error, so skip it and take the smallest remaining value. If a point has `snapped: false`, tell the user that location couldn't be used.

```javascript
const times = matrix.durations_s[0];
const reachable = times.flatMap((t, i) => (t === null ? [] : [{ i, t }]));
const closest = reachable.reduce((a, b) => (b.t < a.t ? b : a), reachable[0]);
```

`closest` is `undefined` when nothing could be reached, so check for that before you use it.

## Stay within the limit

The matrix has its own rate limit of 1 request per second per key, with a burst of 3. Over it, you get `429`. Don't build a matrix from many route calls. Cache results for pairs you ask for often.

See the [`POST /v2/matrix` reference](../reference/matrix.md) for every field.
