Skip to main content
GET
/
devices
/
{device_id}
/
readings
History for one device
import requests

url = "https://api.1st.app/v1/devices/{device_id}/readings"

headers = {"Authorization": "Bearer <token>"}

response = requests.get(url, headers=headers)

print(response.text)
{
  "data": [
    {
      "bucket_at": "2026-05-14T20:35:00Z",
      "co2_ppm": 920,
      "temp_c": 21.8,
      "humidity_pct": 51.2,
      "lux": 410,
      "spl_db": 52,
      "ingested_at": "2026-05-14T20:35:42Z"
    },
    {
      "bucket_at": "2026-05-14T20:30:00Z",
      "co2_ppm": 905,
      "temp_c": 21.7,
      "humidity_pct": 51,
      "lux": 415,
      "spl_db": 49.8,
      "ingested_at": "2026-05-14T20:30:38Z"
    }
  ],
  "next_cursor": "eyJ0ZWFtX2lkIjoi..."
}

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.

Authorizations

Authorization
string
header
required

Your API key. Create one at dashboard.1st.app/integrations/api-keys.

Path Parameters

device_id
string<uuid>
required

The UUID of the device you want. You get a device's ID from GET /v1/devices (look at the device_id field) or by copying it from the dashboard URL.

Example:

"8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b"

Query Parameters

from
string<date-time>

Optional. The earliest time you want readings from. Format: ISO 8601 UTC like 2026-05-10T00:00:00Z (the Z means UTC).

If you leave this off, the default range is the last 24 hours. To pull a different range, either set from and to, or use the simpler ?last=... shorthand below.

If your team thinks in local time, convert to UTC first.

Example:

"2026-05-10T00:00:00Z"

to
string<date-time>

Optional. The end time. Defaults to "now" if you set from and leave this off, so "everything from May 10 onwards" is just ?from=2026-05-10T00:00:00Z.

Same format as from: 2026-05-11T00:00:00Z.

Must be later than from. The total range can't be more than 90 days.

Example:

"2026-05-11T00:00:00Z"

last
string

Shorthand for "the last N minutes / hours / days, up to right now". Use this instead of from and to when you don't want to compute timestamps yourself.

Format: a number followed by m (minutes), h (hours), or d (days). Examples:

  • last=15m — last 15 minutes
  • last=24h — last 24 hours
  • last=7d — last 7 days
  • last=30d — last 30 days

Maximum 90 days. If you pass last, any from / to you also sent are ignored.

Example:

"30d"

assignment_id
string<uuid>

Optional. Scope readings to a single assignment's period (when that athlete owned the device, when that room used it). Get IDs from GET /v1/devices/{device_id}/assignments.

With this set, the time window defaults to the assignment's [started_at, ended_at). If you also pass ?from/?to/ ?last, the result is the intersection of your range and the assignment's window — a from outside the assignment period is valid but returns an empty page.

Returns assignment_not_found (404) if the ID isn't visible to your team or belongs to a different device on your team than the one in the URL. (The two cases are intentionally not distinguished — the response shape can't be used to enumerate which UUIDs map to which sensors within your team.)

Example:

"f4e9b8d2-1c3a-4f5b-9d6e-2a8b1c4d5e6f"

cursor
string

For long time ranges that return more than 1000 readings.

On your first call, leave this empty. If the response includes a next_cursor value, there are more readings waiting. Send that value back here on your next call to get the next batch. Repeat until next_cursor comes back as null.

Like a bookmark for the API: save your place, pick up where you left off. You don't need to understand the value itself, just send it back as-is.

Example:

"eyJ0ZWFtX2lkIjoiOWIzYTNi..."

Response

An array of readings and a next_cursor for the next page.

data
object[]
required
next_cursor
string | null

A bookmark for the next batch of readings. Send it back as ?cursor=... on your next call. null means you've got all the readings.