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"
}
]
}