Use our app, or build your own on top.
Devices speak MQTT or HTTP. Your systems speak REST with scoped keys, and every route is in an OpenAPI document. Webhooks come back with a body you can parse.
Quickstart
- 01Add a device
Its MQTT username and password are shown once.
- 02Add a measure
Owned by that device; note its ID.
- 03Publish a reading
It's on the device page and every open dashboard.
One credential, two topics
A device publishes readings on devices/{deviceID}/data, or on …/process to run them through a process first. The payload names the measure; organization and branch come from the device, never from the message.
- · The broker checks the login on every connection
- · A device may only publish on its own topics
- Commands arrive on a sub-topic you choose, such as commands/unload
# publish a reading mosquitto_pub -h mqtt.kowiste.com -p 8883 \ -i dev_01J8F2K7QX -u dev_01J8F2K7QX -P "$DEVICE_PASSWORD" \ -t devices/dev_01J8F2K7QX/data \ -m '{"measureID":"m_cmp04_discharge", "time":"2026-10-21T10:13:08Z", "data":{"pressure":9.42,"oilTemp":78.6}}' # listen for commands mosquitto_sub … -t devices/dev_01J8F2K7QX/commands/#
When MQTT isn't an option
Give the device an ingest key and it posts the same payload over HTTPS. The key authenticates the device, not a user; the same ownership rules and a per-device rate limit apply.
curl -X POST https://api.kowiste.com/api/ingest \
-H "Authorization: Bearer $INGEST_KEY" \
-H "Content-Type: application/json" \
-d '{"measureID":"m_cmp04_discharge",
"data":{"pressure":9.42}}'Decoders in JavaScript
A process gets the reading and a state object for its measure, and returns the reading you want stored. It runs in a V8 sandbox; save it and the next message uses it.
How processes fit into automation →A contract, not a guess
Every route is declared in the OpenAPI document and checked against it in our tests. Answers have one shape you can rely on.
- Success
- {"data": …}, lists paged with meta
- Invalid input
- 422, naming the field
- Dates
- RFC 3339
- Names
- camelCase; IDs end in ID
- Empty
- [] and {}, never null
GET /api/incidents?status=active
Authorization: Bearer kw_live_••••4f2a
{
"data": [{
"incidentID": "inc_01J9A3…",
"severity": "critical",
"peakSeverity": "critical",
"deviceID": "dev_01J8F2K7QX",
"openedAt": "2026-10-21T09:11:04Z"
}],
"meta": { "page": 1, "total": 1 }
}Keys with only the access they need
An organization admin creates a key with a name, the permissions it carries and an optional expiry. It acts in one branch. The secret is shown once; we keep only its hash.
Alerts into your own systems
A webhook action posts the alarm — policy, binding, trigger, asset, states, severity, time and readings — with your own payload alongside. Only public hosts on 80 and 443 are reachable; redirects aren't followed.
See it in automation →POST https://maint.example.com/api/tickets
Content-Type: application/json
{ "policy": "Compressor overpressure",
"severity": "critical",
"readings": { "pressure": 9.42 },
"payload": { "priority": "P1" } }