# Quickstart

> Make a first map request in test mode, read the response, turn the Map API on and draw the result with the map library you already use. About five minutes.

- **HTML:** https://offendersearch.app/docs/map/quickstart
- **Base URL:** https://api.offendersearch.app
- **Authentication:** `X-API-Key` request header
- **Map API reference as markdown:** https://offendersearch.app/docs/map.md

## 1. Make a request in test mode

Use the API key you already have. `sandbox=true` puts the request in test mode: it needs no plan and is never billed. The box is `west,south,east,north` in degrees.

GET /v1/map/viewport

```bash
curl -G https://api.offendersearch.app/v1/map/viewport \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -d bbox=-83.2,39.8,-82.8,40.1 \
  -d zoom=10 \
  -d sandbox=true
```

## 2. Read the response

At this zoom the view is answered as clusters. Each one has a position, a count, the extent of the people in it, and the zoom at which it comes apart.

200 OK

```json
{
  "mode": "clusters",
  "zoom": 10,
  "bbox": [-83.2, 39.8, -82.8, 40.1],
  "datasetVersion": "2026-10-12",
  "total": 508,
  "breakdown": {
    "street": 508, "housed": 247, "homeless": 96, "incarcerated": 0
  },
  "clusters": [
    {
      "id": "c10_1103_1551",
      "lat": 39.9612, "lng": -82.9988,
      "count": 412,
      "bbox": [-83.06, 39.91, -82.97, 39.98],
      "expansionZoom": 11,
      "breakdown": {
        "street": 412, "housed": 201, "homeless": 77, "incarcerated": 0
      }
    }
  ],
  "markers": [],
  "areas": [],
  "unplaced": {"count": 96, "states": ["OH"]},
  "notice": "A pin shows a registered address, not a person's current location.",
  "sandbox": true
}
```

- `mode` tells you what to draw: `clusters`, `pins` or `markers`.
- `total` is the number of people in the view.
- `clusters[]` are the circles. Draw `count` inside each one.
- `markers[]` and `areas[]` fill in when the view is closer.
- `notice` is a sentence to show on the map.
- `sandbox: true` marks a test-mode answer.

Send the same request with a higher `zoom` and a smaller box. From zoom 13 you get pins. From zoom 15 the pins carry names.

## 3. Turn it on

Any paying account can turn the Map API on. Turning it on charges the $300 minimum that day, and it covers the rest of that calendar month.

Turn it on in the dashboard under Map API, or with one call:

POST /v1/map/enable

```bash
curl -X POST https://api.offendersearch.app/v1/map/enable \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -H "Content-Type: application/json" \
  -d '{"acceptMinimum": true}'
```

The plan is active at once, on the same key. [Turn it on](https://offendersearch.app/docs/map/turn-it-on.md) has the details.

## 4. Make a live request

Drop `sandbox=true`. The request and the response shape are the same.

curl

```bash
curl -G https://api.offendersearch.app/v1/map/viewport \
  -H "X-API-Key: $OFFENDERSEARCH_KEY" \
  -d bbox=-83.2,39.8,-82.8,40.1 \
  -d zoom=10
```

Python

```python
import os, requests

r = requests.get(
    "https://api.offendersearch.app/v1/map/viewport",
    headers={"X-API-Key": os.environ["OFFENDERSEARCH_KEY"]},
    params={
        "bbox": "-83.2,39.8,-82.8,40.1",
        "zoom": 10,
    },
    timeout=30,
)
view = r.json()
for c in view["clusters"]:
    print(c["count"], c["lat"], c["lng"])
```

Node

```javascript
const query = new URLSearchParams({
  bbox: '-83.2,39.8,-82.8,40.1',
  zoom: '10',
});
const res = await fetch(
  'https://api.offendersearch.app/v1/map/viewport?' + query,
  {
    headers: {
      'X-API-Key': process.env.OFFENDERSEARCH_KEY,
    },
  },
);
const { mode, clusters, markers } = await res.json();
```

## 5. Draw it

1. When the map stops moving, call the viewport route with the box and the zoom.
2. Draw `clusters` as circles with their `count`. On click, fit the map to the cluster’s `bbox` at its `expansionZoom`.
3. Draw `markers` as pins. When a pin has a `label`, show it.
4. For a pin with a `groupId`, call the groups route and show the list.
5. When a person is chosen, call the records route with the marker `id` and show the record.

There is a complete, working map for each library: [MapLibre](https://offendersearch.app/docs/map/maplibre.md), [Leaflet](https://offendersearch.app/docs/map/leaflet.md), [Google Maps](https://offendersearch.app/docs/map/google-maps.md). [The click sequence](https://offendersearch.app/docs/map/click-sequence.md) lists every step with its call and its charge.

---

## Related

- Next: [Turn it on](https://offendersearch.app/docs/map/turn-it-on.md)
- Index: [Map API reference](https://offendersearch.app/docs/map.md)
