Skip to content

API

Everything the web interface does goes through the API, so a script can do it too. The API is served by heron-api behind heron-web, at http://<host>:8000/api/v1.

The OpenAPI document is generated from the code and served by every station:

http://<host>:8000/api/v1/openapi.json

It describes every route and type. This page is an overview.

  • Requests and responses are JSON.
  • Times are Unix time in milliseconds (*_unix_ms), durations in milliseconds (*_ms).
  • Errors are {"error": "<code>", "message": "…"}, with codes such as unauthorized (401), forbidden (403), not_found (404), conflict (409), invalid (422) and engine_unavailable (503).

Create a token from Account in the web interface (or POST /api/v1/tokens). It is shown once. Send it as a bearer token:

Terminal window
curl -H 'Authorization: Bearer heron_…' http://localhost:8000/api/v1/player

A token acts as its user, with that user’s role. Tokens can expire and be revoked.

POST /api/v1/auth/login with {"username", "password"} sets a session cookie. Requests that change something with a cookie must also send an X-Requested-With header (any value):

Terminal window
api=http://localhost:8000/api/v1
curl -c cookies -H 'Content-Type: application/json' \
-d '{"username": "admin", "password": "…"}' $api/auth/login
curl -b cookies $api/player
curl -b cookies -X POST -H 'X-Requested-With: curl' $api/player/skip

After 5 failed sign-ins, a username is locked for a minute.

GET /api/v1/status, /api/v1/library/status and /api/v1/openapi.json need no sign-in.

Area Examples
Player GET /player, POST /player/skip, /player/pause, /player/resume, POST /player/fx
Queue GET /queue, POST /queue ({"track_ids", "position"}), DELETE /queue/{entry_id}, PUT /queue/{entry_id}/position
Library GET /tracks (search, filters, sort), GET /tracks/{id}, GET /tracks/{id}/waveform
Buffer zone GET /staging, uploads, POST /staging/import
Rotation /clocks, /schedule, /restrictions, GET /rotation/picks, POST /rotation/simulate
History GET /history
Settings /settings/playout, /settings/rotation, /settings/station, /settings/library…
Outputs /encoder-profiles, /outputs (admins)
Users /users (admins), /tokens

Work that changes files (imports, tag edits, organizing, deletion) is queued as a library task: the route answers 202 with the task, and GET /library/tasks/{id} tells when it is done or failed.

/api/v1/live streams the station’s state. Each message has a type:

type When
state On connection, then whenever the decks, the queue, the outputs or the engine’s reachability change
positions Twice a second: each deck’s position
levels Ten times a second, unless the URL has ?levels=false
track Each track change, started or ended
Role Can
viewer Read everything except users and secrets
operator Also run the station: queue, transport, FX, programming, simulations
admin Also playout, analysis, library and station settings, outputs and users

Secrets (output passwords, the AcoustID key) are never sent back, to anyone.

Terminal window
docker compose exec heron-api heron-api user add <name> --role operator
docker compose exec heron-api heron-api user passwd <name>
docker compose exec heron-api heron-api user list