Quickstart
A working request in under two minutes, in curl, JavaScript or Python.
1. Get a key
Create one at your account. Free, instant, no card.
Read keys start with oaq_ and can only read. A key that ships in a browser
bundle can never forge readings, because sending data uses a different scope
entirely.
2. Ask about a place
curl -H "Authorization: Bearer $OPENAQI_KEY" \
"https://openaqi.net/api/v1/air?lat=37.3352&lon=-121.8811"import { createClient } from "openaqi";
const openaqi = createClient({ apiKey: process.env.OPENAQI_KEY });
const { data } = await openaqi.air({ lat: 37.3352, lon: -121.8811 });
for (const m of data.metrics) {
console.log(`${m.label}: ${m.value} ${m.unit} (${m.severity ?? "ungraded"})`);
}import requests
r = requests.get(
"https://openaqi.net/api/v1/air",
params={"lat": 37.3352, "lon": -121.8811},
headers={"Authorization": f"Bearer {key}"},
)
for m in r.json()["data"]["metrics"]:
print(m["label"], m["value"], m["unit"], m["severity"])req, _ := http.NewRequest("GET",
"https://openaqi.net/api/v1/air?lat=37.3352&lon=-121.8811", nil)
req.Header.Set("Authorization", "Bearer "+key)
res, err := http.DefaultClient.Do(req)
if err != nil { log.Fatal(err) }
defer res.Body.Close()3. Read the answer
{
"data": {
"cell": "608693241486770175",
"centre": { "lat": 37.3268, "lon": -121.9262 },
"coverage": { "exact": true, "rings": 0, "approx_km": 0, "sensors": 3 },
"metrics": [
{
"metric": "pm2p5",
"value": 8.1,
"unit": "µg/m³",
"severity": "good",
"threshold_source": "US EPA 24-hour PM2.5 breakpoints",
"updated_at": "2026-08-02T09:14:00.000Z",
"sensors": 3
}
]
},
"meta": { "notice": "Unvalidated readings from consumer-grade sensors…" }
}Three things to notice:
severitymay benull. Where no published standard exists we say so rather than inventing bands.threshold_sourcenames the standard the grade came from. Show it.coverage.exacttells you whether this is the cell you asked about.
4. Handle the boring cases
Cache responses. Current conditions carry max-age=60 and the data only moves
every minute or two — respecting it means most apps never come near the rate
limit.
Next: authentication if you are shipping to a browser, or errors for what to do when it does not work.