Sonos Music API - Getting Started Guide

Requests and responses

As a Sonos music service developer, it is up to you to decide exactly which features your service supports. However, regardless of those choices, your service must send reasonable, expected responses to each request supported by SMAPI. Those responses may provide information about your service or the user, information on the tracks or streams to play, an indication that the user is not allowed to make a given request, or that your service does not support the requested feature.

What to Expect from a SMAPI Request

Each SMAPI request consists of an HTTP method, HTTP headers, and an HTTP request body. The HTTP body will contain a SOAP envelope divided into a SOAP header and a SOAP body formatted using XML.

HTTP Method and Headers

All requests are sent as HTTP POST requests. The type of request is set in the SOAPAction HTTP header. This header specifies the address of the Sonos XML namespace definition and the SMAPI version number (1.1). Following the version number is # and the name of the method being called. For example, getMetadata calls use the following header:

SOAPAction: "http://www.sonos.com/Services/1.1#getMetadata"

Your SMAPI service must be able to interpret the SOAPAction value and use it to determine how to process the supplied request body.

LANGUAGE HEADER

Sonos apps send an Accept-Language HTTP header in their SMAPI requests. The Sonos app sets the Accept-Language HTTP header to the ISO 639-1 two digit code representing the language used in the Sonos app that is generating the request. This indicates which of the 13 supported languages you should used to respond to this request. For example, a controller using French will set this header to fr as follows:

Accept-Language: "fr"

Sonos players do not send Accept-Language headers.

USER-AGENT

In addition, the User-Agent HTTP header will identify the Sonos build number and the type of Sonos app or player sending the request. For example, a CONNECT:AMP™ running build 26.7-48310 will send the following header with its requests:

User-Agent: "Linux UPnP/1.0 Sonos/26.7-48310 (ZP120)"

"(ZP120)" shows that this is a request from a Sonos player. All Sonos players will send a string that starts with "ZP". 

The User-Agent HTTP header that a Sonos app sends includes device and operating system information. For example, the Sonos app for iOS running on an iPhone 6 Plus with iOS version 8.2 would send the following header with its requests:

User-Agent: "Linux UPnP/1.0 Sonos/29.3-87071 (ICRU_iPhone7,1); iOS/Version 8.2 (Build 12D508)"

Note that you can't tell one iOS device from another if the device and OS are the same from the User-Agent heading. For example, if two listeners are both using iPhone 6 Pluses with iOS version 8.2 in the same household you won't be able to identify them from the User-Agent header.

Here is a list of what different Sonos apps send to identify themselves in the User-Agent heading of a request:

Sonos app Shown in User-Agent HTTP header 
Sonos app for iOS ICRU
Sonos app for Android ACR
Sonos app for Mac MDCR
Sonos app for PC WDCR

Soap Envelope

In addition to being the container around the SOAP headers and SOAP body, the SOAP envelope for SMAPI requests also typically defines an XML namespace pointing to the public URI of the Sonos namespace. This URI is:

http://www.sonos.com/Services/1.1

Sonos typically assigns the prefix ns to this namespace, but does not guarantee its use in all SMAPI requests.

For example, the SOAP envelope for a SMAPI request might be defined as follows:

<soap:Envelope 
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:ns="http://www.sonos.com/Services/1.1">
...
</soap:Envelope>

or the completely equivalent:

<soapenv:Envelope 
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
xmlns:sonos="http://www.sonos.com/Services/1.1">
...
</soapenv:Envelope>

SOAP Header

The SOAP specification requires that the SOAP header is included within the SOAP envelope before the SOAP body if one is included at all. SMAPI supports one SOAP header with elements supplying credentials and context information.

Credentials element

The <credentials> element contains all of the information needed to authenticate the user making the API call. It consists of the following sub-elements:

  • <deviceId> This is deprecated; your service can ignore it. This was an identifier equivalent to a Sonos device registered by an authenticated user when they set up their household.  
  • <deviceCert> The X.509 certificate for the player sending the request. This is optional and requires that you turn on the "Requires Device Certificate" capability, described in the customSD documentation. See Encrypting content for digital rights management (DRM) for how this is used.
  • <zonePlayerId> The Sonos player ID for the player sending the request. This is optional and requires that you turn on the "Include Zone Player IDs in credentials header" capability, see the customSD documentation for details.
  • <deviceProvider> The device provider. This value is always "Sonos".
  • <loginToken> The authentication information for the user making the request. For more information, see Processing authentication credentials for API requests.

The expected syntax for the <credentials> element is:

    <[ns]:credentials>
         <[ns]:deviceId>[deviceId]</[ns]:deviceId>
         <[ns]:deviceCert>[deviceCert]</deviceCert>
         <[ns]:zonePlayerId>[zonePlayerId]</zonePlayerId>
         <[ns]:deviceProvider>Sonos</[ns]:deviceProvider>
         <[ns]:loginToken>
            <[ns]:token>[authenticationToken]</[ns]:token>
            <[ns]:key>[refreshToken]</[ns]:key>
            <[ns]:householdId>[householdId]</[ns]:householdId>
         </[ns]:loginToken>
      </[ns]:credentials>

 

Context element

Sonos will send context in the header so that you can customize the browse experience based on it. Currently we offer two contexts, the time zone of the player or controller, and content filtering.

The <timeZone> sub-element reports the time zone of the player or controller that is sending the request. With this context, your service could customize featured playlists based on the user's location and time of day. 

Currently the only option we offer for <contentFiltering> is <explicit>.  See Tag and filter explicit content for details. 

Set the “Include SMAPI context headers with all requests” capability flag when developing or submitting your service for validation. See SMAPI capabilities for details.

Name Type Description
timeZone string Hour and minute offset from UTC, such as +hh:mm or -hh:mm. If the region that the user is in uses Daylight Savings Time, we incorporate this into the time offset that we send.
contentFiltering complex  Used for flagging content that the listener has requested not be playable on their system. <contentFiltering> is only included if the associated capability flag is turned on. Currently, the only flag we offer is <explicit>.
  • <explicit> is a boolean that if set to true signals that the Sonos system sending the request has chosen to filter out explicit content. All filtering defaults to false/off when it is not present in the <context> header. Sonos players and apps will not include <explicit> or <contentFiltering> in requests if listeners have not enabled explicit filtering.

Example:

<s:Envelope
        xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
  <s:Header>
    <credentials
            xmlns="http://www.sonos.com/Services/1.1">
      <deviceId>
        XX-BB-33-55-66-77:H
      </deviceId>
      <deviceProvider>
        Sonos
      </deviceProvider>
    </credentials>
  </s:Header>
  <s:Header>
    <context
            xmlns="http://www.sonos.com/Services/1.1">
      <timeZone>
        -05:00
      </timeZone>
      <contentFiltering>
        <explicit>
          true
        </explicit>
      </contentFiltering>
    </context>
  </s:Header>
  <s:Body>
  ...
  </s:Body>
</s:Envelope>    

Note that while the <timeZone> sub-element is included in the WSDL, additional contextual elements will not be bound to the WSDL, as specified by the "any" element within the "context" complexType element. Therefore, you should design your SMAPI implementation to use or ignore any context sub-elements that Sonos sends.

SOAP Body

In general, the request body of a call includes some sort of identifier indicating what the server should take the requested action against (for instance, getMetadata requests include an <id> element indicating a node in the item tree for the service and expects a list of direct children of that item returned in the response). Some requests that do not act directly on content may not include an <id> element. Requests that create new content typically return an <id> element for that content in the response.

Each request has its own format as defined in the Sonos WSDL file; you'll need to reference the definition of each call to determine what to expect. In general, the content is all inside an element matching the call name. For example, the SOAP body for getMediaMetadata is defined as follows:

<[soap]:Body>
  <[ns]:getMediaMetadata>
    <[ns]:id>[itemId]</[ns]:id>
  </[ns]:getMediaMetadata>
</[soap]:Body>

where [itemId] is the ID of the item being requested.

The following elements are found in many SMAPI request bodies:

  • <id> The item ID of the item being processed by the request. See the identifiers documentation for more information.
  • <index> Indicates the entry point into the 0-based list of possible responses. See the pagination documentation for more information.
  • <count> Indicates the maximum number of items to return in the response. See the pagination documentation for more information.

What to Send in a SMAPI Response

Each SMAPI response consists of an HTTP status code, HTTP headers, and an HTTP response body. The HTTP body must contain a SOAP envelope with a SOAP body formatted using XML.

HTTP Status Code

All SMAPI responses that successfully fulfill the related request should return HTTP status code 200, success. Responses that do not successfully fulfill the related request should return HTTP status code 500 regardless of the cause of failure. Responses returning 500 for their status code should always use a SOAP body containing a fault element.

HTTP Headers

Responses may be compressed using gzip software. If so, the content-encoding HTTP header must be present and set to gzip. The content-type header should be set to text/xml; charset=utf-8 to indicate that the body of the response uses XML with UTF-8 encoding (note that, unlike for JSON, UTF-8 is not the default encoding for XML so you must specify the encoding explicitly). Other standard headers should be used as appropriate to accurately describe the returned data and behaviors. For example, the response headers for a SMAPI call might look like the following:

Content-Encoding: gzip
Content-Type: text/xml; charset=utf-8
Content-Length: 1455
Connection: keep-alive

SOAP Header

Sonos does not expect a SOAP header in any response to SMAPI calls. Your SOAP envelope should only contain a SOAP body. If you do send a SOAP header in a response, Sonos will ignore it.

SOAP Body

The SOAP body in the response is dependent on the SMAPI call. Your response should match the response defined in the Sonos WSDL file. In general, the following conventions are used in response formats for successful requests:

  • Responses to specific elements in the request body are returned using an element of the format <[requestElementName]Response>, for example, <getMetadataResponse>. The [requestElementName] is the name of the element in the request body requiring a response, which is typically the name of the SMAPI method being processed by your music service, such as getMetadata.
  • The <[requestElementName]Response> element includes an xmlns attribute pointing to the public URI http://www.sonos.com/Services/1.1, for the Sonos namespace.
  • The <[requestElementName]Response> element has a child element named <[requestElementName]Result>. Typically this will be its only child element, although there are a few exceptions.
  • The <[requestElementName]Result> element contains <index>, <count>, and <total> elements if pagination is expected for the method. See Pagination for more information.
  • The <[requestElementName]Result> element contains the requested data in the structure defined in the Sonos WSDL, often as a list of repeated elements, where each represents a single item in the sorted list of possible results.


For example, a getMetadata response body might look like the following:

<soap:Body>
  <getMetadataResponse
  xmlns="http://www.sonos.com/Services/1.1">
    <getMetadataResult>
      <index>0</index>
      <count>4</count>
      <total>4</total>
      <mediaMetadata>
        <id>Track::1</id>
        <itemType>track</itemType>
        <title>Gone Jazz Crazy</title>
        <mimeType>audio/mpeg</mimeType>
        <trackMetadata>
          <artistId>Artist::212</artistId>
          <artist>Richmond Starlight Quartette</artist>
          <albumId>Album::3132</albumId>
          <album>Gone Jazz Crazy</album>
          <duration>185</duration>
          <albumArtURI>http://Art44423</albumArtURI>
          <canPlay>true</canPlay>
          <canSkip>true</canSkip>
          <canAddToFavorites>true</canAddToFavorites>
          <trackNumber>1</trackNumber>
        </trackMetadata>
      </mediaMetadata>
      <mediaMetadata>
        <id>Track::2013</id>
        <itemType>track</itemType>
        <title>Wont Be Worried No More</title>
        <mimeType>audio/mpeg</mimeType>
        <trackMetadata>
          <artistId>Artist::212</artistId>
          <artist>Richmond Starlight Quartette</artist>
          <albumId>Album::3132</albumId>
          <album>Gone Jazz Crazy</album>
          <duration>189</duration>
          <albumArtURI>http://Art44423</albumArtURI>
          <canPlay>true</canPlay>
          <canSkip>true</canSkip>
          <canAddToFavorites>true</canAddToFavorites>
          <trackNumber>2</trackNumber>
        </trackMetadata>
      </mediaMetadata>
      <mediaMetadata>
        <id>Track::391</id>
        <itemType>track</itemType>
        <title>Oh, You Better Mind</title>
        <mimeType>audio/mpeg</mimeType>
        <trackMetadata>
          <artistId>Artist::212</artistId>
          <artist>Richmond Starlight Quartette</artist>
          <albumId>Album::3132</albumId>
          <album>Gone Jazz Crazy</album>
          <duration>190</duration>
          <albumArtURI>http://Art44423</albumArtURI>
          <canPlay>true</canPlay>
          <canSkip>true</canSkip>
          <canAddToFavorites>true</canAddToFavorites>
          <trackNumber>3</trackNumber>
        </trackMetadata>
      </mediaMetadata>
      <mediaMetadata>
        <id>Track::5929</id>
        <itemType>track</itemType>
        <title>Monkey Man Blues</title>
        <mimeType>audio/mpeg</mimeType>
        <trackMetadata>
          <artistId>Artist::212</artistId>
          <artist>Richmond Starlight Quartette</artist>
          <albumId>Album::3132</albumId>
          <album>Gone Jazz Crazy</album>
          <duration>189</duration>
          <albumArtURI>http://Art44423</albumArtURI>
          <canPlay>true</canPlay>
          <canSkip>true</canSkip>
          <canAddToFavorites>true</canAddToFavorites>
          <trackNumber>4</trackNumber>
        </trackMetadata>
      </mediaMetadata>
    </getMetadataResult>
  </getMetadataResponse>
</soap:Body>

Requests that are not successfully processed should return a <Fault> element in the response instead of the normal response body. See Error Handling for more information.