Skip to content

Talking to the API

An API is a set of web addresses that programs use to talk to each other. The agent uses the API to send data. The web app uses the API to show data. You can use it too, with a tool like curl.

Most addresses start with /api/v1. The v1 means “version 1.” If we ever change things a lot, we can make a v2 and not break old programs.

The API has two groups of callers:

  1. Devices. A controller proves who it is with an API key. An API key is like a password for a machine. The controller sends it in a header named X-API-Key.
  2. People. A person logs in with an email and password. They get a token back. A token is a signed pass that says “this is me.” They send it in a header named Authorization: Bearer ....
  • POST /api/v1/devices/register — sign up a new device and get its API key.
  • POST /api/v1/telemetry — send a telemetry report.
  • GET /api/v1/commands — ask for any commands waiting for it.
  • POST /api/v1/commands/{id}/result — say what happened with a command.
  • GET /api/v1/config/{device_id} — get its settings.
  • GET /api/v1/ota/latest — ask if there is a new software version for it.

People can sign up, log in, and manage their buildings and devices. They can read charts, set up alerts, pull reports, and pay for a plan. Each request is checked two ways:

  • Is the role high enough? A “viewer” can look but not change things. An “operator” can act. An “org admin” can manage the team.
  • Is it their organization? People can only see their own company’s data. They cannot peek at another company. If they try, the server acts like the data does not exist.

With the backend running, register a device:

Terminal window
curl -X POST localhost:8000/api/v1/devices/register \
-H 'content-type: application/json' \
-d '{"device_id":"my-first-device"}'

You will get back an API key. Save it. Now send one telemetry report with that key:

Terminal window
curl -X POST localhost:8000/api/v1/telemetry \
-H "X-API-Key: PASTE_YOUR_KEY_HERE" \
-H 'content-type: application/json' \
-d '{"device_id":"my-first-device","ts":"2026-06-30T12:00:00+00:00","readings":{"supply_temp_c":71},"health":{}}'

A 202 reply means the backend accepted it. You just spoke the same language the real controller speaks.

The full list of addresses is in docs/api.md, and the live, clickable version is at /docs on any running backend.