Cells in a box
GET /v1/cells — every reporting area in a bounding box, for building your own map.
GET
/v1/cellscurl -H "Authorization: Bearer $OPENAQI_KEY" \
"https://openaqi.net/api/v1/cells?bbox=-122.6,37.2,-121.7,37.9&metric=pm2p5"Parameters
| Name | Type | Default | Notes |
|---|---|---|---|
bbox | string | — | west,south,east,north in degrees. Required. Max 30° per side. |
metric | string | pm2p5 | Which metric to return. |
window | integer | 60 | Minutes to average over. |
limit | integer | 1000 | Max 5000. |
The response
{
"data": {
"metric": "pm2p5",
"unit": "µg/m³",
"cells": [
{
"cell": "608693243097382911",
"centre": { "lat": 37.4752, "lon": -121.7375 },
"value": 12.4,
"severity": "moderate",
"sensors": 2,
"updated_at": "2026-08-02T09:10:00.000Z"
}
]
}
}Centres and numbers rather than our polygons, so you can render it your way. Compute the hexagon from the H3 index with any H3 library:
import { cellToBoundary } from "h3-js";
const ring = cellToBoundary(BigInt(cell).toString(16), true); // [lng, lat] pairsColouring it
Use severity rather than interpolating over the values you received. Severity
is anchored to published thresholds, so an all-green map means the air really is
fine — a relative scale would paint the worst cell in a clean city red.
The band colours are in /v1/meta.
Notes
- A box crossing the antimeridian is rejected rather than half-answered. Split it into two requests.
- Exactly
limitcells returned means there may be more;meta.truncatedsays so.