Streaming measurements
How to read in real time
The OpenSense API is mostly request/response. For real-time downstream consumers, there are three options, in order of preference.
Option A — webhooks (recommended)
Configure a webhook integration for the event kinds you care about. We push to your URL within ~1 s of the event. This is the right answer for alarms, ack, clear, device state.
It is not the right answer for "raw measurements". We do not fire a webhook per measurement; the rate would be impractical and the use case rare.
Option B — MQTT subscribe (Team tier)
The MQTT bridge that ingests from customer brokers can also be configured to publish to customer brokers — measurements, events, and notifications mirrored in real time.
Today this is a Team-tier feature; the topic structure is:
opensense/<acc>/<device>/measurement QoS 1, retained: false
opensense/<acc>/<device>/event QoS 1, retained: false
opensense/<acc>/<device>/state QoS 1, retained: true
Authentication is the same mTLS as inbound. Direction is configured per topic family in the dashboard.
Option C — polling
For small-scale integrations, a 60-s poll of the
measurements API with agg=raw&limit=10 is
fine and explicitly supported. The 120-req/min/account rate budget
is generous enough that ~50 channels polling each 60 s is
comfortable.
Polling is the right answer for:
- Home Assistant dashboards.
- Bespoke Grafana panels (where you have not yet plugged the JSON datasource into our API).
- A 12-hour cron that grabs yesterday's data for a separate archive.
What we do not offer
- Server-Sent Events or WebSockets. We considered both; the webhook + MQTT pair covers everything they would address. Adding a third stream is overhead for no new capability.
- GraphQL subscriptions. We are not a GraphQL API.
- Long-polling. The 5-second budget on HTTP handlers makes long-polling awkward and we do not want to enlarge it.
Latency budget
Per layer of the pipeline:
| Step | p50 | p99 |
|---|---|---|
| Edge accept → ingest service | 2 ms | 25 ms |
| Ingest validation + DB write | 2 ms | 50 ms |
| Rule engine evaluation | 1 ms | 30 ms |
| Outbound dispatcher → Telegram | 200 ms | 2 s |
| Outbound dispatcher → Email (Postmark) | 1 s | 8 s |
| Outbound dispatcher → Webhook | 50 ms | 500 ms |
| Outbound dispatcher → MQTT publish | 5 ms | 30 ms |
End-to-end alarm-to-Telegram p99: ~3 s from the moment the device sends the breach to the moment the message appears in the chat.
Backpressure
If your subscribing system is slow:
- MQTT subscribe: if your broker's queue grows, we throttle. Our bridge will drop oldest queued messages above 10 000 per topic — you receive a small gap, not unbounded growth.
- Webhook: we retry with backoff; sustained failure removes the destination from the active set and we email you.
- Polling: it is your concern; we serve as fast as you ask, up to the rate-limit budget.