Skip to main content
GET
/
readings.csv
Python
import os, requests

params = {
    "from": "2026-05-01T00:00:00Z",
    "to":   "2026-05-08T00:00:00Z",
    "shape": "wide",
}
with requests.get(
    "https://api.1st.app/v1/readings.csv",
    params=params,
    headers={"Authorization": f"Bearer {os.environ['ST_API_KEY']}"},
    stream=True,
) as r:
    r.raise_for_status()
    with open("readings.csv", "wb") as f:
        for chunk in r.iter_content(chunk_size=8192):
            f.write(chunk)
"bucket_at,device_id,display_name,co2_ppm,temp_c,humidity_pct,lux,spl_db,valid_mask\n2026-05-14T20:35:00Z,8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b,Locker Room North,920,21.8,51.2,410,52.0,55\n2026-05-14T20:35:00Z,b3f9d2e8-7a4c-4e6f-8d1b-0c5a9e7b3d2f,Recovery Pool Deck,685,24.1,58.4,220,38.5,55"

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.

Query Parameters

from
string<date-time>
required

The earliest time you want readings from. The reading right at this exact moment is included.

Format the timestamp like 2026-05-10T00:00:00Z. That's ISO 8601 with a Z on the end to mean UTC. To pull "all of May 10 in UTC", use 2026-05-10T00:00:00Z.

If your team is on UK time and you want "May 10 local", convert it to UTC first.

Example:

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

to
string<date-time>
required

The end time. Readings at this exact moment are not included, so to pull a full day, set from to midnight on day 1 and to to midnight on day 2.

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

Must be later than from. The total range can't be more than 90 days; split longer pulls into multiple calls.

Example:

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

devices
string

Optional. Limit the export to specific devices. Pass a comma-separated list of device IDs (the UUIDs you get from GET /v1/devices).

Example: ?devices=8a72a1c7-3c91-...,b3f9d2e8-7a4c-...

Leave this off to export every device on your team.

Example:

"8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b,b3f9d2e8-7a4c-4e6f-8d1b-0c5a9e7b3d2f"

shape
enum<string>
default:long

How to organize the rows.

long (default), one row per reading. Each row tells you "at this time, this device measured these values." Easy to filter and group by device or by metric.

wide, one row per timestamp. The row has one column per (device × metric), like locker_north.co2_ppm, locker_north.temp_c, recovery_pool.co2_ppm. This is the layout Google Sheets and Excel charts want.

Available options:
long,
wide
key
string

Your API key, passed in the URL. Use this only when you're calling from Google Sheets =IMPORTDATA() or Excel's "From Web" connector, those tools can't set a custom Authorization header. For every other case, use the Authorization: Bearer ... header instead.

URLs with ?key=... show up in your browser history, anyone you share the sheet with, and any HTTP log along the way. Treat them like passwords. Create a separate dedicated key per spreadsheet so rotating it costs you one feed instead of all of them.

Example:

"1st_sk_abcdwxyz23456789.qrstuvwxyz23456789abcdefghijklmn"

Response

The CSV body. Save it to a file.

The response is of type string.

Example:

"bucket_at,device_id,display_name,co2_ppm,temp_c,humidity_pct,lux,spl_db,valid_mask\n2026-05-14T20:35:00Z,8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b,Locker Room North,920,21.8,51.2,410,52.0,55\n2026-05-14T20:30:00Z,8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b,Locker Room North,905,21.7,51.0,415,49.8,55\n2026-05-14T20:25:00Z,8a72a1c7-3c91-4f5b-b39e-1d2c4e3f5a7b,Locker Room North,890,21.6,50.8,420,48.2,55\n2026-05-14T20:35:00Z,b3f9d2e8-7a4c-4e6f-8d1b-0c5a9e7b3d2f,Recovery Pool Deck,685,24.1,58.4,220,38.5,55\n2026-05-14T20:30:00Z,b3f9d2e8-7a4c-4e6f-8d1b-0c5a9e7b3d2f,Recovery Pool Deck,690,24.0,58.6,225,37.9,55"