sonn docs GitHub

api reference

Commands

All return 204 No Content on success. The resulting state arrives over /api/v1/events.

POST /api/v1/zones/{id}/play    {"uri": "…"}   or  no body to resume
POST /api/v1/zones/{id}/pause
POST /api/v1/zones/{id}/stop
POST /api/v1/zones/{id}/next
POST /api/v1/zones/{id}/previous

PUT  /api/v1/zones/{id}/volume     {"volume": 40}   or  {"delta": -5}
PUT  /api/v1/zones/{id}/position   {"position": 90}
PUT  /api/v1/zones/{id}/power      {"power": "on"}
PUT  /api/v1/zones/{id}/input      {"input": "linein-ms3h9f42"}
PUT  /api/v1/zones/{id}/equalizer  {"bands": [3,3,2,1,0,0,-1,-2,-2,-3]}
PUT  /api/v1/zones/{id}/repeat     {"repeat": "off" | "all" | "one"}
PUT  /api/v1/zones/{id}/shuffle    {"shuffle": true}

POST   /api/v1/zones/{id}/queue    {"uri": "…"}            add to the end
POST   /api/v1/zones/{id}/queue    {"uri": "…", "next": true}   add after what is playing
PATCH  /api/v1/zones/{id}/queue    {"play": "<item id>"}    jump to an entry
PATCH  /api/v1/zones/{id}/queue    {"move": "<id>", "before": "<id>"}   reorder (omit `before` for the end)
DELETE /api/v1/zones/{id}/queue    {"id": "<item id>"}      remove one entry
DELETE /api/v1/zones/{id}/queue    {"all": true}            clear it
DELETE /api/v1/zones/{id}/queue    {"undo": true}           revert the last edit

POST   /api/v1/zones/{id}/handoff  {"targetZoneId": 7}      move playback to another zone

POST   /api/v1/zones/{id}/alert      {"kind": "tts", "text": "…"}   say or play something
DELETE /api/v1/zones/{id}/alert      {"kind": "alarm"}              stop it

POST   /api/v1/zones/{id}/favorites  {"uri": "…", "name": "…"}   add (name optional)
PATCH  /api/v1/zones/{id}/favorites  {"id": 1, "name": "…"}      rename
PATCH  /api/v1/zones/{id}/favorites  {"order": [3,1,2]}          reorder
PATCH  /api/v1/zones/{id}/favorites  {"play": 1}                 start it
DELETE /api/v1/zones/{id}/favorites  {"id": 1}                   remove
DELETE /api/v1/zones/{id}/recents                                clear the history

PUT    /api/v1/zones/{id}/group      {"members": [7, 9]}   group these behind this zone
PUT    /api/v1/zones/{id}/group      {"members": []}       ungroup

powerState.power is the current physical amplifier/player power. powerState.target is the desired signal, and powerState.idleTimeoutMs reports the automatic idle timeout. The explicit power command still uses {"power":"off"} and switches the configured power action immediately; it does not wait for the automatic offDelayMs. It also stops playback. The automatic switch-off caused by a normal playback state transition keeps using the configured delay.

pause keeps the zone's place and stop gives it up: after pause, play resumes where it was; after stop it starts over. Both let the zone's power management switch an amplifier off, since by default only play counts as active.

Live radio is the exception — it has no position to resume, so pause tears the stream down and play reconnects live. Expect position to restart at 0 there rather than continue.

play without a body resumes whatever the zone already has queued. With {"uri": "…"} it starts something: either a stream URL, or a source.id this API gave you earlier — that is what makes the id worth storing. Resolving it and rebuilding the queue happens server-side, so you do not need to know anything about how content is modelled.

# Start a stream, then a track this zone reported playing earlier
curl -X POST http://server:7090/api/v1/zones/3/play -d '{"uri":"http://example/stream.mp3"}'
curl -X POST http://server:7090/api/v1/zones/3/play -d '{"uri":"library://track/9"}'

handoff is a server-side queue transfer. It moves the complete queue, including its order, current index, repeat/shuffle settings and current position, to the target zone. The source is stopped and cleared only as part of the same operation; the client must not rebuild the queue itself. Both zones must exist and must be different, and the source must have a queue. A successful handoff returns 204; an impossible transfer returns 404 with {"error":"handoff-not-possible"}.

curl -X POST http://server:7090/api/v1/zones/3/handoff \
  -H 'Content-Type: application/json' \
  -d '{"targetZoneId":7}'

Audioservers

GET /api/v1/audio-servers lists the audioservers known from the installation configuration. selfId is the MAC id of the current server. Each entry identifies whether it is a sonn core or a regular Loxone audioserver. This is a discovery resource, not a playback target: use /destinations and /zones for audio routing.

{
  "selfId": "001122AABBCC",
  "servers": [
    {
      "id": "001122AABBCC",
      "name": "Living room server",
      "host": "sonn-living",
      "self": true,
      "kind": "sonn-core"
    }
  ]
}
This chapter is rendered from INTEGRATING.md in sonn-audio/core — the API's single source of truth, kept next to the code it describes.