# Get your first route

Go from no account to a real route on your screen. You need a terminal and an idea of what you're building.

## Request an API key

Open the [key request form](/keys/request) and tell us your name, a contact email, your app or organisation, a client identifier such as `partner-acme`, and what you're building.

Staff review each request and contact you to arrange delivery. The key is never sent by email and can't be shown again, so save it as soon as you get it.

> **Want to look around first?** The [test map](test-map.md) runs calls in your browser without a key.

## Store the key outside your code

Put the key in an environment variable. Keep it out of URLs, and out of any code that ships to a browser.

```bash
export QUADRUPER_KEY="qdp_your_key_here"
```

## Send a request

This asks for a car route between two points in Iloilo City. Coordinates are `[lng, lat]`.

```bash tab=curl
curl -X POST https://quadruper.com/v2/route \
  -H "X-API-Key: $QUADRUPER_KEY" \
  -H "Content-Type: application/json" \
  -d '{"points": [[122.5642, 10.6968], [122.5587, 10.7201]], "profile": "car"}'
```

```javascript tab=JavaScript
const res = await fetch("https://quadruper.com/v2/route", {
  method: "POST",
  headers: {
    "X-API-Key": process.env.QUADRUPER_KEY,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    points: [[122.5642, 10.6968], [122.5587, 10.7201]],
    profile: "car",
  }),
});
const { routes } = await res.json();
console.log(routes[0].distance_m, routes[0].duration_s);
```

```python tab=Python
import os, requests

res = requests.post(
    "https://quadruper.com/v2/route",
    headers={"X-API-Key": os.environ["QUADRUPER_KEY"]},
    json={"points": [[122.5642, 10.6968], [122.5587, 10.7201]], "profile": "car"},
)
route = res.json()["routes"][0]
print(route["distance_m"], route["duration_s"])
```

## Read the response

A `200` response holds exactly one route. This is an example: 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.5642, 10.6968], [122.5587, 10.7201]] },
    "waypoints": [
      { "location": [122.5642, 10.6968], "snapped_distance_m": 3.1 },
      { "location": [122.5587, 10.7201], "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" }]
}
```

That example is 4.21 km and about 11.5 minutes. You now have a working integration.

## If the request fails

| Status and `code` | Likely cause | Fix |
|---|---|---|
| `401 unauthorized` | Key missing or wrong | Check that `QUADRUPER_KEY` is set in this shell |
| `422 out_of_coverage` | Point outside the covered area | Check you sent `[lng, lat]`, not `[lat, lng]` |
| `429 rate_limited` | Too many requests | Wait for `Retry-After`, then retry |

[Errors](../reference/errors.md) lists every code.

## Where to go next

- [Geocode an address, then route to it](../guides/geocode-then-route.md) connects two endpoints.
- [`POST /v2/route`](../reference/route.md) covers multi-stop routes and turn-by-turn steps.
- [Integrate with AI](integrate-with-ai.md) shows how to have a coding agent build this for you.
