# Route

Get a route, distance and ETA between 2 to 10 points, optionally with turn-by-turn steps.

`POST /v2/route`. Auth: API key or our website.

## Request body

Send JSON with `Content-Type: application/json`. Bodies are limited to 32 KB. Unknown fields return `400 invalid_request`.

| Field | Required | Description |
|---|---|---|
| `points` | Yes | 2 to 10 `[lng, lat]` pairs, in travel order. Stops are not reordered. |
| `profile` | No | `car` (default) or `car_night`. `GET /v2/info` lists what this deployment offers. |
| `steps` | No | `true` returns turn-by-turn steps. Default `false`. |

## Example

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

This is an example response. Your numbers will differ, and a real `geometry` has many more coordinates.

```json schema=route-response
{
  "routes": [{
    "distance_m": 4210.0,
    "duration_s": 690.0,
    "geometry": { "type": "LineString", "coordinates": [[122.5621, 10.7202], [122.5444, 10.6969]] },
    "waypoints": [
      { "location": [122.5621, 10.7202], "snapped_distance_m": 3.1 },
      { "location": [122.5444, 10.6969], "snapped_distance_m": 7.4 }
    ],
    "legs": [{ "distance_m": 4210.0, "duration_s": 690.0, "steps": [] }]
  }],
  "conditions": { "assessed": false, "reason": "not_configured" },
  "attribution": [{ "source": "osm", "text": "© OpenStreetMap contributors", "license": "ODbL-1.0" }]
}
```

## Response fields

| Field | Description |
|---|---|
| `routes` | Always exactly one item. |
| `routes[].distance_m`, `duration_s` | Total metres and seconds, rounded to 1 decimal. |
| `routes[].geometry` | GeoJSON `LineString`, coordinates `[lng, lat]`, rounded to 6 decimals. |
| `routes[].waypoints` | One entry per input point. `location` is where it snapped. |
| `routes[].legs` | One entry per pair of consecutive points, so `points.length - 1`. |
| `conditions` | Always `{"assessed": false, "reason": "not_configured"}` in this version. Hazards are not assessed. |
| `attribution` | Credit to show wherever you show this route to people. |

## Turn-by-turn steps

Send `"steps": true` to fill each leg's `steps` list. A step has this shape:

```json
{
  "type": "turn_left",
  "instruction": "Turn left onto General Luna Street",
  "name": "General Luna Street",
  "distance_m": 180.0,
  "duration_s": 24.0,
  "location": [122.5621, 10.7202],
  "geometry_index": [0, 7]
}
```

- `type` is one of `depart`, `arrive`, `waypoint`, `continue`, `turn_left`, `turn_right`, `turn_slight_left`, `turn_slight_right`, `turn_sharp_left`, `turn_sharp_right`, `keep_left`, `keep_right`, `u_turn`, `roundabout`. A `roundabout` step also has `exit`, an integer of 1 or more.
- `instruction` is an English sentence you may display. Don't parse it.
- `name` is the street name or `null`.
- `geometry_index` is `[from, to]`, indexes into `geometry.coordinates`.

## Errors for this endpoint

| Status | `code` | What to do |
|---|---|---|
| 400 | `too_many_points` | Split the trip. |
| 400 | `unsupported_profile` | Read `routing.profiles` from `GET /v2/info`. |
| 422 | `point_not_snapped` | Move the point to within 1 km of a road. |
| 422 | `out_of_coverage` | Check the point and its `[lng, lat]` order. |
| 422 | `no_route` | Don't retry unchanged. Tell the user, or try nearer points. |

[Errors](errors.md) lists the codes every endpoint shares.
