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
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
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
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
curl -s $OS_BASE/v1/sites
-H "Authorization: Bearer $OS_TOKEN" | jq '.data | {id, name, vertical}'
List devices on a site
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
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
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
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
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
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
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
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
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
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
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()