Documentation Index
Fetch the complete documentation index at: https://dev.1st.app/llms.txt
Use this file to discover all available pages before exploring further.
All timestamps are UTC
Every timestamp the API accepts or returns is ISO 8601 UTC with an explicitZ suffix.
Missing fields are NULL, not zero
Per-bucket, each metric is independently nullable. A sensor that fails to read CO2 in a bucket will haveco2_ppm: null for that row, while temp /
humidity still populate.
”Stale” sensors are not necessarily broken
Thestatus field on /sensors:
| Status | last_seen_at age |
|---|---|
online | < 1 hour |
stale | 1–24 hours |
offline | > 24 hours or never |
stale then offline. Buffered readings DO
arrive when the device reconnects — they just land in a burst, with old
bucket_at timestamps. So a sensor in offline status today may still
deliver yesterday’s data tomorrow.
Rate-limit timing
The 600-per-10-minutes budget is per API key, not per IP and not per integration. If two scripts share the same key, they share the budget. After a 429, theRetry-After header tells you how many seconds to wait.
Worst case: 600 seconds (a full window). Cheap option: throttle to 1 req/sec
average and you’ll never hit the limit.
For nightly bulk pulls, prefer GET /v1/readings.csv over a /readings
loop — one streaming request instead of hundreds of paginated calls,
and one rate-limit hit instead of many.
Cursor expiry
Cursors are issued for the moment-in-time of the request. If you save a cursor and resume hours later, the underlying anchor row may have been deleted (sensor archived, retention policy applied) and the cursor returnscursor_invalid. Walk pagination in a single loop, not across runs.
Confirming your team
The docs don’t ask you to substitute ateam_id anywhere — the API key
already binds you to your team. Call GET /v1/team to see which team
your key is scoped to (returns the team’s id and name).
Notecard vs sensor_id
A sensor has TWO IDs:sensor_id— UUID assigned by the platform at factory provisioning. Stable across firmware/hardware changes.hardware_id— Notecard device UID (e.g.dev:868050050000123). Stable across firmware changes but tied to specific physical hardware.
sensor_id everywhere in the API. hardware_id is informational
(useful for matching against your physical inventory list).
Buffered data is delivered eventually
When a sensor’s cellular link fails, data accumulates in the device’s flash buffer and arrives when connectivity returns — sometimes hours or days later. Theingested_at field tells you WHEN the row reached our backend;
bucket_at tells you WHEN the bucket was measured.
For “did we get last night’s data” queries, filter on bucket_at. For
“what landed in the last 5 minutes” cron jobs, filter on ingested_at.