Environment — entry 008 of 18
Luchtmeetnet
Luchtmeetnet is the Dutch national air-quality monitoring network (run by RIVM and partners), publishing measured and forecast pollutant levels from over a hundred stations across the Netherlands. It's a fully open government data feed — no key or registration needed.
Luchtmeetnet is the Dutch national air-quality network (RIVM and partners), exposing 102 monitoring stations (5 pages of `/stations`, counted live this run) and their measured pollutant readings as open, keyless JSON. A live GET this run against `/stations?page=1` returned a real paginated station list (25 stations on page 1 of 5, `access-control-allow-origin: *`), and a live GET against `/measurements?station_number=NL49565` returned genuine current NO2/PM10/NO readings for that station after following a redirect (see gotchas).
GreatAPIs Score
Auth quickstart
- No API key, signup, or credit card required -- live GETs this run against `/stations` and `/measurements` both returned real data with zero credentials and `access-control-allow-origin: *` on every response.
Your key is stored only in this browser (localStorage) and sent directly to the API — never to greatapis.
List monitoring stations
GEThttps://api.luchtmeetnet.nl/open_api/stations?page=1
{"pagination":{"last_page":5,"first_page":1,"prev_page":1,"current_page":1,"page_list":[1,2,3,4,5],"next_page":2},"data":[{"number":"NL49565","location":"Oude Meer-Aalsmeerderdijk"},{"...":"24 more stations on this page, 5 pages total"}]}Every list route wraps its results in this same `{pagination, data}` envelope, confirmed live this run -- `page_list` gives you every page number up front rather than just a boolean has-more flag.
Try it
Developer reference
https://api.luchtmeetnet.nl/open_api- GET/stations?page={n}
- GET/stations/{number}
- GET/measurements?station_number={number}&page={n}
Gotchas & limits
- `/measurements?station_number=...` doesn't return data directly -- a live GET this run got **HTTP 302** back with no body, redirecting to a URL the API itself constructs with an injected default 7-day window (`.../measurements?...&start=2026-07-24T12:10:46...&end=2026-07-31T12:10:46...&order_by=timestamp_measured`). A plain HTTP client must follow that redirect (`curl -L` or your library's default) to get the actual readings; a client that doesn't follow redirects silently gets an empty 302 response instead of data.
- Once followed, `/measurements` returns one row **per pollutant per hour**, not one row per station -- a live GET this run for a single station returned separate entries for `NO2`, `PM10`, and `NO` all sharing the same `timestamp_measured`, distinguished only by the `formula` field. Code that expects one combined reading object per timestamp will silently drop pollutants.
- An unknown station number 404s cleanly and predictably -- a live GET this run against `/stations/NOTASTATION` returned `{"reason":"not_found","message":"Not Found"}` with `access-control-allow-origin: *` still present, so a missing station is easy to distinguish from a CORS or auth failure.
- Station numbers are RIVM codes like `NL49565`, not free-text city names -- get them from `/stations` first; there's no `?city=` or geocoding shortcut on the measurements route itself.