List readings
GEThttps://api.compostiq.win/research/readings
Anonymised readings, one row per bin per hour, oldest first. Filter by country, method, phase or time, and page through the results with a cursor.
No key needed60 requests / minuteUp to 5000 rows per page
Query parameters
All optional. Combine as many as you like.
countrystringISO 3166-1 alpha-2 code, for example ID.methodenumtakakura, bokashi or aerated_static_pile.stageinteger 0–4Only hours labelled with this phase. See the phase definitions.bin_refstringOne bin's readings. References come from /research/bins.fromdate-timeEarliest hour to include, UTC. Inclusive.todate-timeLatest hour to include, UTC. Exclusive.limitintegerRows per page. Default 500, maximum 5000.cursorstringThe next_cursor from the previous page.Response
itemsarrayReadings. Each field is described in the data dictionary.next_cursorstring | nullPass this as cursor to get the next page. null on the last page.Rate limits & errors
Every client IP can make 60 requests a minute. Errors share one shape: {"detail": "A sentence you can show to a person."}
| Status | When |
|---|---|
| 400 | A parameter isn't recognised, for example method=compost. |
| 422 | A value is out of range, for example limit=9000. |
| 429 | Over 60 requests in a minute. Wait for the number of seconds in Retry-After. |
| 503 | Down for maintenance. Try again shortly, or use the bulk files. |
curl -G https://api.compostiq.win/research/readings \ -d method=takakura \ -d from=2026-08-26T00:00:00Z \ -d limit=2
import requests resp = requests.get( "https://api.compostiq.win/research/readings", params={ "method": "takakura", "from": "2026-08-26T00:00:00Z", "limit": 2, }, timeout=30, ) resp.raise_for_status() for row in resp.json()["items"]: print(row["recorded_at"], row["temperature_c"])
library(httr2) resp <- request("https://api.compostiq.win/research/readings") |> req_url_query( method = "takakura", from = "2026-08-26T00:00:00Z", limit = 2 ) |> req_perform() readings <- resp_body_json(resp, simplifyVector = TRUE)$items head(readings[, c("recorded_at", "temperature_c")])
Response · 200
{
"items": [
{
"bin_ref": "b_1d0ca7",
"country": "ID",
"method": "takakura",
"recorded_at": "2026-08-26T00:00:00Z",
"temperature_c": 61.58,
"moisture_pct": 52.46,
"oxygen_pct": 3.26,
"co2_pct": 8.61,
"nh3_relative": 0.889,
"mq135_composite_ppm": 602.15,
"stage_id": 2,
"stage_name": "Peak Decomposition",
"faults": []
},
{ … }
],
"next_cursor": "eyJ0IjoiMjAyNi0wOC0yNlQwMjowMFoifQ"
}
Other endpoints
GET /public/statsTotals: bins, countries, active devices, readings in the last 24 hours.
GET /public/bins-by-countryNumber of bins in each country.
GET /public/trends30-day daily means of temperature and moisture across all bins.
GET /research/binsOne row per bin: reference, country, method, first and last reading.
GET /research/stagesThe phase ranges used to label every reading.
GET /openapi.jsonThe machine-readable spec, for code generators and Postman.
Changelog
[DATE] · v1First public release of the
/public and /research endpoints.