The Sonos Control API has been used to build some really great experiences. These range from big and ambitious, to smaller and more straightforward. But what if you want to start smaller still? What if you just want to dip your toe in, and get a feel for how things fit together? We’ll find out one way to do that in this post.
If you’re the type that likes to read the last page of a good book, scroll to the bottom, where I’ve included all the work done here in a pre-packaged project for you to use. But you should still read the rest of the post!
Getting Started
First, let’s collect our materials:
- A set-up and configured Sonos system, obviously. Make sure you can play some content on it.
- The username and password associated with that Sonos system.
- A few Sonos Favorites saved and showing up in My Sonos.
- A Control Integration, complete with a Client Key and Secret.
- An installed copy of Postman, the REST client.
- Some good hacking music. I’d suggest something by Matthew E. White.
Fire up Postman and look around. We’ll build the required Environment and Collection to generate Sonos API calls.
Set Up the Environment
Before we get started on actual API calls, we need to set up an Environment for our collection to use. An environment, in Postman, is a collection of variables that any collection has access to. So, for instance, you can use {{auth_url}}
instead of api.sonos.com. This lets you use the variable in multiple places, and only change the variable value in the environment definition if that value ever needs to change.
Let’s get our Environment set up. Click on the “Manage Environments” button in the upper right of the Postman window. It looks like a gear icon. Then, click on the big, orange “Add” button. Fill it out such that it looks like this:

Let’s go over each of the environment variables we’ve specified.
auth_host – The host that handles Sonos authorization calls.
api_host – The host that handles Sonos Control API calls.
client_key – The client key provided when you create a new Control Integration.
client_secret – The client secret provided when you create a new Control integration.
Once you’ve gotten everything set up as noted above, click on “Update”, then close the Environment window. We’re ready to start actually making calls.
Authorization
The next thing we’re going to want to do is create a new collection. A Postman collection is, well, a collection of related REST calls that can share resources. In our case, we’re going to build the authorization handling right in this collection. We’ll let the REST calls contained inside the collection use this authorization so we don’t have to reconfigure for every call.
Click the “New Collection” button in the left column of the Postman window.

Give your collection a name, and a description of you’d like.

Click on the “Authorization” tab. This is where we do the first really meaty, interesting part. Before we go any further, it’s a good idea to read over the Authorize section of our documentation. That’ll explain the details behind what we’re doing here, and will help make things more clear when you’re building an actual implementation and don’t simply have form fields to fill in.
On the “Authorization” window, select “OAuth 2.0” for the type, and “Request Header” for “Add auth data to”. As noted in our documentation, we employ a standard OAuth 2.0 3-legged OAuth flow, and require that the acquired token is included in request headers.

Now we’re going to click on the big orange “Get New Access Token” button on the right side of the window. Here, we’ll fill in the information required to actually get an access token. Fill in everything, so that it looks like this:

You’ll note a bunch of orange values, surrounded by double curly brackets. Those are the Postman environment variables, which you set up in the previous section.
Let’s run through these fields, one at a time.
Token Name – You can use whatever you want. This is just so that you can remember the token you fetched. I just leave it at the default
Grant Type – Sonos employs an Authorization Code flow, so you should select that here.
Callback URL – This is the URL that is called when the Sonos auth servers want to send the user back to your integration. This callback URL should be prepared to receive data involved in the auth flow, as described in our Authorization docs. This Callback Url must match the redirect uri you specified when you created your Control Integration on the developer portal. The “http://localhost” value included in this screenshot is for my specific integration, and should be changed to match your setup. Note that, while Postman calls it a Callback URL, it is more commonly referred to as a redirect uri. Sonos uses this name, and in fact has a separate, unrelated Control Integration parameter called “Callback URL” which is for player eventing.
Auth URL – This is the URL that an integration will call to get the initial Authorization Code
Access Token URL – An integration will call this URL, with the authorization code, to get access and refresh tokens.
Client ID – The client ID that was generated for you when you created your Control integration.
Client Secret – The client secret that was generated for you when you created your Control integration
Scope – The types of abilities your integration is requesting on behalf of the user. At the time of this writing, the only available scope for Sonos is “playback-control-all”.
State – A value built in the OAuth spec that is used to prevent cross-site forgeries. The {{$guid}}
value in the screenshot is a random value generator (more or less) provided by Postman.
Once this is all filled out, click on the big orange “Request Token” button. This will initiate an actual OAuth flow against the Sonos servers, exactly as a user would see inside an actual integration. You’ll be directed to the Sonos login page, told a bit about how to prepare your Sonos system to integrate with third parties, and then be prompted for your username and password.

Once you’ve successfully supplied your credentials, you’ll be told about the capabilities the integration is asking for. These are defined by the “scope” parameter in your Authorization calls.

Once you click “OK” here, the user is sent back to the redirect/callback URI specified above. Normally, your hypothetical integration would take over at this point, getting the authorization code, then exchanging it for the access token. In this case, though, Postman scrapes the redirect call, gathers the required data, and completes the OAuth flow itself, eventually presenting you with a token that you can choose to use.

Congratulations! You’ve successfully authenticated against the Sonos platform!
Making Your First Call
Now that Postman has the authentication information the Sonos requires for any API call, we can start building those calls. Before we can get to the really fun stuff, like music playback, we have to understand a bit about the user’s system. The user, in this case, is whoever logged in to the Sonos authorization page in the section above. We’ll want to get a list of available households first. Usually, there will be only a single household per user, but it’s quite possible for a user to have more than one. In either case, we need to get a householdId to use to make further calls. You can read a more high level description of this flow in the “Discover” section of our documentation.
Click on the ellipsis (“…”) button on the bottom right of your collection in Postman, then select “Add Folder”. I like to create folders for each namespace in the Sonos API, so I’ll call this one “households”. On the description tab, enter “households” as the Name.
Next select the Authorization tab. This is where Postman really comes in handy. Instead of rebuilding our authorization flow from scratch, we’ll simply select “Inherit Auth from parent” for the type.

Click the orange “Create” button to create the folder and to close this window. Now, let’s add our first request. Click the ellipsis button on the “households” folder. Sometimes you need to hover the mouse over the folder name for this menu to appear. Then, click the “Add Request” menu item. Let’s call this one “households”, since we’ll be doing a simple GET /households request.

You’ll notice that when you save it, it is conveniently labeled right inside the parent folder, with the http method (GET, in this case) helping us identify it. Select the request in the column on the left, and notice that request details page that becomes visible. This is where we’ll specify the command endpoint, as well as any body elements that are required. Fill out the request details as noted below

Notice again that we’re using environment variables, this time {{api_host}}, to build our request. Note also that we’ve once again specified that the request should inherit its auth from its parent. Auth flow from the top level collection is being passed down to the “households” folder, then down to this GET /households request.
For a simple GET /households request, this is all that’s required, so let’s make our very first call! Click on the big blue “Send” button. You should get back a JSON body that looks something like this:
1 2 3 4 5 6 7 |
{ "households": [ { "id": "Sonos_big_long_sonos_household_id" } ] } |
There you go! You’ve got your list of Sonos households available to the authenticated user. Note the household id returned above, as we’ll need that for the next section. If you’ve got more than one household available, just pick one of the ids returned.
Finding Out What Groups and Players are Available
Most commands on the Sonos Control API require either the householdId or the targeted groupId. We’ve got the hhid, so let’s make a call and get a target groupId. We’ll build a GET /groups request to return what we’re looking for. Just as above, we’ll make a new folder, this time for the “groups” namespace, and then a new request inside that new folder for the actual GET /groups call. To summarize:
- Create a new “groups” folder.
- Create a new “groups” command.
- Set the auth type to “inherit”, and enter the URL as such: https://{{api_host}}/control/api/v1/households/<< householdId from above >>/groups

If you click “Send” now, you should get back a groups response object that contains all of the players in the household, as well as a listing of how those players are currently grouped. It’ll look something like this
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
{ "groups": [ { "id": "RINCON_12345:54321", "name": "Kitchen", "coordinatorId": "RINCON_98765", "playbackState": "PLAYBACK_STATE_IDLE", "playerIds": [ "RINCON_98765" ] }, { "id": "RINCON_11111:12345", "name": "Office Speakers + 1", "coordinatorId": "RINCON_11111", "playbackState": "PLAYBACK_STATE_IDLE", "playerIds": [ "RINCON_11111", "RINCON_22222", ] }, ], "players": [ { "id": "RINCON_98765", "name": "Kitchen", "websocketUrl": "wss://192.168.55.207:1443/websocket/api", "softwareVersion": "46.1", "deviceIds": [ "RINCON_98765" ], "apiVersion": "1.7.00", "minApiVersion": "1.1.0", "capabilities": [ "PLAYBACK", "CLOUD", "AIRPLAY" ] }, { "id": "RINCON_11111", "name": "Office Speakers", "websocketUrl": "wss://192.168.55.81:1443/websocket/api", "softwareVersion": "46.1", "deviceIds": [ "RINCON_11111", "RINCON_121212", "RINCON_212121" ], "apiVersion": "1.7.0", "minApiVersion": "1.1.0", "capabilities": [ "PLAYBACK", "CLOUD", "AIRPLAY" ] }, { "id": "RINCON_22222", "name": "Playroom", "websocketUrl": "wss://192.168.55.114:1443/websocket/api", "softwareVersion": "46.1", "deviceIds": [ "RINCON_22222" ], "apiVersion": "1.7.0", "minApiVersion": "1.1.0", "capabilities": [ "PLAYBACK", "CLOUD" ] } ] } |
Just like before, we’re going to want to grab a groupId from one of these, so pick a group that looks interesting from the groups object in the response. Note the associated groupId. In the example above, there are two groups returned, so I might choose the “Office Speakers + 1” group, with the RINCON_11111:12345
id.
Get the Sonos Favorites
So we’ve gotten all the boring housekeeping out of the way; now it’s time to actually make our Sonos speakers do something. Let’s put a Sonos Favorite on the group you just selected. If you haven’t done so yet, make sure you’ve added something to “My Sonos”, which is the Sonos app container for favorites and playlists. We’ll use the favorites namespace to look for saved favorites, then play one back.
The first thing we’ll want to do is execute a GET /favorites command. You know the drill at this point:
- Create a new “favorites” folder underneath the top level collection.
- Create a new “favorite” command.
- Set the auth type to “inherit”, and enter the URL as such: https://{{api_host}}/control/api/v1/households/<< householdId from above >>/favorites
That’s it. If you hit “Send” now, you should get back a JSON body containing all of the Sonos Favorites you’ve saved. It should look something like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
{ "version": "RINCON_11223344550:274", "items": [ { "id": "84", "name": "Alternative Rewind Radio", "description": "iHeartRadio Station", "imageUrl": "http://i.iheart.com/v3/re/new_assets/c96abf74-4458-4a44-a19c-c1975926e1d9", "service": { "name": "iHeartRadio" } }, { "id": "37", "name": "Beats 1", "description": "Apple Music Station", "imageUrl": "http://is1.mzstatic.com/image/thumb/Features6/v4/7b/c3/0e/7bc30e7b-6099-acef-ebb9-3391d0e20d53/source/400x400cc.png", "service": { "name": "Apple Music" } }, { "id": "118", "name": "Classic Alternative", "description": "Apple Music Station", "imageUrl": "http://is1.mzstatic.com/image/thumb/Features122/v4/13/ff/47/13ff471a-2ef9-89d8-e778-355726fc004b/source/400x400cc.jpeg", "service": { "name": "Apple Music" } }, { "id": "119", "name": "Classic Indie", "description": "Apple Music Station", "imageUrl": "http://is1.mzstatic.com/image/thumb/Features122/v4/3f/ef/7b/3fef7b36-2be6-6f3b-2d7d-2e2f93416adf/source/400x400cc.jpeg", "service": { "name": "Apple Music" } }, { "id": "40", "name": "Discover Weekly", "description": "Spotify Playlist", "imageUrl": "https://pl.scdn.co/images/pl/default/cf69a273214001758dac729ed8102cd540cc0399" }, { "id": "138", "name": "KEXP-FM", "description": "TuneIn Station", "imageUrl": "http://cdn-profiles.tunein.com/s32537/images/logoq.png", "service": { "name": "TuneIn" } } ] } |
Pick your favorite Favorite, and note the id. We’ll be using that in the next section.
Finally, Let’s Play Some Music
We’ve gotten the household id. We’ve used that to get the list of available groups, and then picked a group id. We’ve gotten a favorite id. Not let’s put it all together and play that favorite on that group.
Inside the existing “favorites” folder, let’s create a new request, and call it “loadFavorites”. Have it inherit its parent’s auth, of course. But here’s where things get a little different. The first thing we’ll do is change the HTTP method from the default GET to POST. This means we’re sending data to the request endpoint instead of just asking for data. Check out the following screenshot of how you should get things configured.

You’ll note that this time, we’ve included a request body by clicking on the “Body” tab in the request. The JSON in that body tells Sonos which favorite id to play, and how to queue it up. Obviously, if the favorite you’ve selected is a streaming radio station, setting the play mode shuffle to TRUE doesn’t make any sense, and is ignored.
Hitting “Send” on this request should result in your selected Sonos Favorite playing on your selected Sonos group. Congratulations! You’ve built your first Sonos app. Of course, there’s no UX around it, and you’re doing all the heavy lifting instead of letting code do it, but make no mistake, this is an integration.
Wrap Up
We’ve learned here how to use Postman to authenticate against Sonos’ servers, and how to make requests to find out about the state of a user’s system. And finally, we actually made music play. From here, some great next steps would be to implement more commands, like volume or playback control, inside Postman. Get a feel for how things fit together.
A couple notes:
- Obviously, you can’t subscribe to any eventing with Postman.
- For whatever reason, Postman doesn’t implement support for refresh tokens, so you’ll have to go back in to the top collection’s Authorization screen and request a new token every 24 hours.
And finally, here’s a special treat. Clicking this button will import a new Postman Collection and Environment, all set up with a number of Sonos namespaces. In addition, I’ve created a number of post-request scripts that will parse the results, and do things like automatically populate groupIds into calls. All you need to do is open the enclosed Environment and set “target_player” to the name of a player in your household, and add your client key and secret. After that, every time you run the GET /groups command, Postman will look for your player in the response, find its current group, and use that groupId in other requests, like loadFavorite.
Thanks for reading, and we’re so excited that you’re building great things with us.