api reference
Integrating with sonn
How to read and control sonn core from your own software — a home-automation system, a script, a wall display, a plugin.
The API below is the server's own: versioned in the path, additive within a version, and it speaks its own vocabulary. You do not need to know anything about Loxone to use it, and it works whether or not the Loxone integration is enabled.
Base URL: http://<server>:7090/api/v1
/admin/api. That is the back end of this server's own admin UI: it is UI-shaped, changes freely, and is not a contract. Build your integrations on /api/v1.SONN player is built on nothing else. It uses this API and only this API — no /admin/api, no loxone api, so everything described here is exercised by a real client rather than merely offered.
Coming from /admin/api?
Before this API existed, /admin/api/zones/states was the only way to read what a zone was playing, so integrations polled it. It is now what it was always meant to be — diagnostics for our own Admin UI — and the now-playing fields have moved here:
| was | now |
|---|---|
title, artist, album | track.title, track.artist, track.album |
coverUrl / coverurl | track.coverUrl |
station, sourceName | source.name (with source.kind telling you which) |
state (play/pause) | state (playing/paused/stopped) |
powerState | powerState.power (on/off) |
tech, system | stayed — engine internals, not part of this contract |
tech.player moved as well: it is output.device here, with mac renamed to the protocol-neutral id. Same value, same guarantee that an idle zone still reports it.
PUT/GET /admin/api/zones/{id}/equalizer moved too, to /api/v1/zones/{id}/equalizer. The old path is gone rather than aliased, because nothing outside our own Admin UI should have to touch /admin/api. The request body is unchanged ({"bands": [ …10 ]}); the response drops ok and equalizerSettings — a 2xx already means it worked, and the comma-joined string was only ever there for the Loxone app.
POST/DELETE /admin/api/zones/browser is gone as well — that was how a browser tab used to register itself as somewhere audio goes, and it needed an admin session to do it. It is POST /api/v1/destinations/local now, needs no session, and hands back the client id and socket url the old route never did. See Destinations.
GET /admin/api/transports/squeezelite/clients has an answer here too, if you were using it to work out which of your players ended up on which zone. output.device.id is that same MAC and output.device.connected that same link state, per zone, from one read of /api/v1/zones — see the zone object. No session, no credentials.
That last part is the point of all of this: /admin/api needs a session and /api/v1 does not. If you are logging in — with local accounts or with Miniserver credentials — to read state or steer playback, you are on the wrong surface, and the login can go with it. /admin/api is the back end of our own Admin UI: it is UI-shaped, it changes without notice, and nothing in it is a promise to you.
And you no longer need to poll: subscribe to /api/v1/events and the same data arrives on every change.