API cookbook

Copy-paste recipes for common tasks

A grab-bag of HTTP recipes for everyday operations. Examples are in shell + cURL by default; Python equivalents are in POST /v1/ingest and one block per recipe below.

Authentication setup

$ env

export OS_BASE="https://api.opensense.murzin.digital" export OS_TOKEN="ua_live_4f3c…" # user-scoped token export OS_DEVICE="ds_live_b1d2…" # device-scoped token

Send a single measurement

$ ingest one

curl -X POST $OS_BASE/v1/ingest
-H "Authorization: Bearer $OS_DEVICE"
-H "Content-Type: application/json"
-d '{ "device": "fridge01", "measurements": {"type":"temperature","value":4.2} }'

Send a batch

$ ingest batch

curl -X POST $OS_BASE/v1/ingest
-H "Authorization: Bearer $OS_DEVICE"
-H "Content-Type: application/json"
-d '{ "device": "panel1", "measurements": {"ts":"2026-05-17T08:00:00Z","type":"power","value":1240}, {"ts":"2026-05-17T08:00:01Z","type":"power","value":1255}, {"ts":"2026-05-17T08:00:02Z","type":"power","value":1268} }'

List all sites

$ list sites

curl -s $OS_BASE/v1/sites
-H "Authorization: Bearer $OS_TOKEN" | jq '.data | {id, name, vertical}'

List devices on a site

$ list devices

curl -s "$OS_BASE/v1/devices?site_id=site_4f3c"
-H "Authorization: Bearer $OS_TOKEN" | jq '.data | {local_id, online, last_seen_at}'

Rotate a device's ingest token

$ rotate token

curl -X POST $OS_BASE/v1/devices/dev_b1d2/rotate-token
-H "Authorization: Bearer $OS_TOKEN" | jq '.ingest_token'

Read last 24 h of a channel, 5-min mean

$ read 24h

curl -s "$OS_BASE/v1/channels/chn_a1b2/measurements?agg=5m&fn=mean&from=$(date -u -d '24 hours ago' +%FT%TZ)"
-H "Authorization: Bearer $OS_TOKEN" | jq '.data | length'

Read last week as CSV

$ csv export

curl -s -o week.csv "$OS_BASE/v1/channels/chn_a1b2/measurements?agg=1h&from=$(date -u -d '7 days ago' +%FT%TZ)&format=csv"
-H "Authorization: Bearer $OS_TOKEN"

Read multiple channels in one call

$ multi read

curl -s "$OS_BASE/v1/measurements?channel_ids=chn_a1b2,chn_a1b3,chn_a1b4&agg=1h&from=$(date -u -d '7 days ago' +%FT%TZ)"
-H "Authorization: Bearer $OS_TOKEN" | jq 'keys'

Edit a channel's operating range

$ retune range

curl -X PATCH $OS_BASE/v1/sensors/snr_a1b2
-H "Authorization: Bearer $OS_TOKEN"
-H "Content-Type: application/json"
-d '{"ok_min": -2, "ok_max": 6, "grace_min": 20}'

Acknowledge an alarm

$ ack alarm

curl -X POST $OS_BASE/v1/events/evt_4f3c/ack
-H "Authorization: Bearer $OS_TOKEN"
-H "Content-Type: application/json"
-d '{"note": "Door propped open during delivery; closed within 8 min."}'

Silence a channel for 4 hours

$ silence

FROM=$(date -u +%FT%TZ) TO=$(date -u -d '+4 hours' +%FT%TZ) curl -X POST $OS_BASE/v1/sensors/snr_a1b2/silence
-H "Authorization: Bearer $OS_TOKEN"
-H "Content-Type: application/json"
-d "{"from":"$FROM","to":"$TO","reason":"scheduled defrost"}"

Generate a monthly HACCP report

$ report

RPT=$(curl -X POST $OS_BASE/v1/reports
-H "Authorization: Bearer $OS_TOKEN"
-H "Content-Type: application/json"
-d '{ "site_id": "site_4f3c", "template": "haccp_monthly", "period": {"from":"2026-04-01T00:00:00+02:00","to":"2026-04-30T23:59:59+02:00"}, "language": "en" }' | jq -r .id)

while true; do STATE=$(curl -s $OS_BASE/v1/reports/$RPT -H "Authorization: Bearer $OS_TOKEN" | jq -r .state) "$STATE" = "ready" && break echo " state=$STATE waiting..."; sleep 5 done

curl -s -o report.pdf $OS_BASE/v1/reports/$RPT/file -H "Authorization: Bearer $OS_TOKEN" echo "report.pdf ($(wc -c < report.pdf) bytes)"

Verify a webhook signature (Python)

import hmac, hashlib, base64, time

def verify(secret: str, headers: dict, body: bytes) -> bool:
    sig = headers["X-OpenSense-Signature"]
    parts = dict(p.split("=", 1) for p in sig.split(","))
    t, v1 = parts["t"], parts["v1"]
    if abs(time.time() - int(t)) > 300:
        return False
    expected = base64.b64encode(
        hmac.new(secret.encode(), f"{t}.".encode() + body, hashlib.sha256).digest()
    ).decode()
    return hmac.compare_digest(v1, expected)

Get the audit log for the last 30 days

$ audit

curl -s "$OS_BASE/v1/accounts/me/audit?from=$(date -u -d '30 days ago' +%FT%TZ)"
-H "Authorization: Bearer $OS_TOKEN" | jq '.data | {ts, kind, by, target}'

Export everything

$ export

curl -X POST -o opensense-export.zip
$OS_BASE/v1/accounts/me/export
-H "Authorization: Bearer $OS_TOKEN"

The export is a single ZIP with measurements.csv, events.csv, audit.csv, plus a meta.json describing the schemas. See security/compliance.

In Python, with a session

import requests, os, datetime as dt

S = requests.Session()
S.headers.update({"Authorization": f"Bearer {os.environ['OS_TOKEN']}"})
BASE = "https://api.opensense.murzin.digital"

def list_devices(site_id):
    return S.get(f"{BASE}/v1/devices", params={"site_id": site_id}).json()["data"]

def last_value(channel_id):
    r = S.get(f"{BASE}/v1/channels/{channel_id}/measurements",
              params={"limit": 1, "fn": "last"}).json()
    return r["data"][0] if r["data"] else None

def ack(event_id, note):
    return S.post(f"{BASE}/v1/events/{event_id}/ack", json={"note": note}).json()