Add favorites

Listeners can have two ways to save their favorites: Sonos favorites and your own service favorites.

ServiceDescription
My Sonos favoritesListeners can save favorite songs, albums, and stations from any service to My Sonos. Listeners can then select My Sonos in the lower left of the Sonos app to manage their favorites. Listeners add content to their Sonos favorites by selecting default actions such as Add Song to My Sonos or Add Album to My Sonos. Listeners choose these actions from the Info View, accessible from list views. Sonos automatically enables listeners to save content to Sonos favorites without any extra work from you. You can, however, prevent listeners from saving content to favorites, if, for example, the content is short-lived. See isEphemeral in SMAPI object types for details.
My favoritesListeners can save favorites selected exclusively from your service when you integrate your own service-specific favorites. This allows you to keep listener favorites synchronized when users access your service favorites by a variety of methods including the Sonos app, your app, or other methods. Your favorites can include tracks, albums, streaming radio stations, and other items.

Listeners add favorites from the Info View, as shown below:

To add your favorites to Sonos you must enable listeners to:


Add and remove favorites

Whether the listener is browsing your content or viewing the current playing item, they add or remove a favorite from the Info View. You provide the listener with HTTP request actions to add or remove favorites in your responses to getExtendedMetadata. Then, when the user chooses the action from the Info View, Sonos makes the HTTP REST request to your service, which implements the method to add or remove the favorite. You should become familiar with the Info View by reading the introduction to Add actions.

We'll describe the following tasks:

  1. Provide HTTP request actions for the Info View
  2. Implement a REST method to add a favorite
  3. Implement a REST method to remove a favorite

Provide HTTP request actions for the Info View

You will need to provide the listener with a control to add or remove the current item they are viewing or listening to. Do so by including the HTTP request action in your response to getExtendedMetadata, when the listener uses the Info View. The following images are examples of the Info View for the situations when the current item is not a favorite and when it is a favorite.

The following steps describe how to set the Info View:

  1. Define the text strings in Localization Resources that will display for the HTTP requests in the Info View. You can also define optional success and failure error strings. The localization text values as shown in the following example are up to you. These text values will be referenced in the following sections. For more about the Localization Resources file, see Localization.

    {
        "en-US":{
          "common":{
              ...
              },
          "integration":{
            "ADD_MUSIC": "Save to My Acme Music",
            "DELETE_MUSIC": "Remove from My Acme Music",
            "ADD_SUCCESS": "Saved to your Acme Music favorites",
            "ADD_FAILED": "Failed to save to your Acme Music favorites",
            "DELETE_SUCCESS": "Removed from your Acme Music favorites",
            "DELETE_FAILED": "Failed to remove from your Acme Music favorites"
            ...
          }
        },
    }
    
  2. Sonos sends a getExtendedMetadata request. When the listener is browsing a container or listening to a track or station, they can select the ellipsis (...) to view more about the current container or item. When this happens, Sonos sends your service a getExtendedMetadata request. The following request example is for a track.

    <s:Envelope
      xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
      <s:Header>
      ...
      </s:Header>
      <s:Body>
        <getExtendedMetadata xmlns="http://www.sonos.com/Services/1.1">
          <id>tr:15</id>
        </getExtendedMetadata>
      </s:Body>
    </s:Envelope>
    
  3. Your service checks to see if the current item (tr:15 in this example) is already in the listener's favorites.

  4. Your service responds to getExtendedMetadata. Use an HTTP request action in your getExtendedMetadata response to implement adding or removing a favorite.

See REST request for details about HTTP request actions.

Provide an HTTP request action to add a favorite

If the listener's current item is not in their favorites, provide in your getExtendedMetadata response an HTTP request to add the item to favorites. Be sure to include all the custom actions for the Info View in your response. To simplify this example, we show only the HTTP request action.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <getExtendedMetadataResponse xmlns="http://www.sonos.com/Services/1.1">
            <getExtendedMetadataResult>
                <mediaMetadata>
                    <id>tr:15</id>
                    <itemType>track</itemType>
                    <title>Man in the Mirror (2003 Edit)</title>
                    <mimeType>audio/mp3</mimeType>
                    <trackMetadata>
                        <artistId>QltoGrsHWgT0yA</artistId>
                        <artist>Michael Jackson</artist>
                        <composer/>
                        <albumId>fYpMChhFbjwT0yA</albumId>
                        <album>Number Ones</album>
                        <genre1980s Pop</genre>
                        <duration>303</duration>
                        <albumArtURI>http://cdn.acme.com/fYpMChhFbjwT0yA</albumArtURI>
                        <canPlay>true</canPlay>
                    </trackMetadata>
                    . . .
                </mediaMetadata>
                <relatedActions>
                    <action>
                        <id>add_item_to_favorites_id</id>
                        <title>SAVE_MUSIC</title>
                        <actionType>simpleHttpRequest</actionType>
                        <simpleHttpRequestAction>
                            <url>https://192.168.0.10:8223/v2/favorites?itemId=tr:15</url>
                            <method>PUT</method>
                            <httpHeaders>
                                <httpHeader>
                                    <header>clientid</header>
                                    <value>sonos-to-acme-client</value>
                                </httpHeader>
                            </httpHeaders>
                            <refreshOnSuccess>true</refreshOnSuccess>
                        </simpleHttpRequestAction>
                        <showInBrowse>true</showInBrowse>
                        <failureMessageStringId>ADD_FAILED</failureMessageStringId>
                    </action>
                . . . Details of other actions not shown . . .
                </relatedActions>
                . . . Details for other custom actions in the Info View not shown . . .
            </getExtendedMetadataResult>
        </getExtendedMetadataResponse>
    </soap:Body>
</soap:Envelope>

Note the following when you provide action and its sub-elements for an HTTP request action to add a favorite. For complete details see relatedActions.

  • The title value SAVE_MUSIC corresponds to a text value in your Localization Resources.
  • The actionType value for an HTTP request action must be simpleHttpRequest.
  • The simpleHttpRequestAction element requires the following:
    • url—The URL of the HTTP REST request to your service.
    • method—The HTTP method to execute on your service. Use PUT to add a favorite.

Provide an HTTP request action to remove a favorite

If the listener's current item is in their favorites, provide in your getExtendedMetadata response an HTTP request to remove the favorite. Be sure to include all the custom actions for the Info View in your response. To simplify this example, we show only the HTTP request action.

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <getExtendedMetadataResponse xmlns="http://www.sonos.com/Services/1.1">
            <getExtendedMetadataResult>
                <mediaMetadata>
                    <id>tr:15</id>
                    <itemType>track</itemType>
                    <title>Man in the Mirror (2003 Edit)</title>
                    <mimeType>audio/mp3</mimeType>
                    <trackMetadata>
                        <artistId>QltoGrsHWgT0yA</artistId>
                        <artist>Michael Jackson</artist>
                        <composer/>
                        <albumId>fYpMChhFbjwT0yA</albumId>
                        <album>Number Ones</album>
                        <genre1980s Pop</genre>
                        <duration>303</duration>
                        <albumArtURI>http://cdn.acme.com/fYpMChhFbjwT0yA</albumArtURI>
                        <canPlay>true</canPlay>
                    </trackMetadata>
                    <dynamic>
                        <property>
                            <name>ratings</name>
                            <value>0</value>
                        </property>
                    </dynamic>
                </mediaMetadata>
                <relatedActions>
                    <action>
                        <id>remove_item_from_favorites_id</id>
                        <title>DELETE_MUSIC</title>
                        <actionType>simpleHttpRequest</actionType>
                        <simpleHttpRequestAction>
                            <url>https://192.168.0.10:8223/v2/favorites?itemId=tr:15</url>
                            <method>DELETE</method>
                            <httpHeaders>
                                <httpHeader>
                                    <header>clientid</header>
                                    <value>sonos-to-acme-client</value>
                                </httpHeader>
                            </httpHeaders>
                            <refreshOnSuccess>true</refreshOnSuccess>
                        </simpleHttpRequestAction>
                        <showInBrowse>true</showInBrowse>
                        <failureMessageStringId>DELETE_FAILED</failureMessageStringId>
                    </action>
                . . . Details of other actions not shown . . .
                </relatedActions>
                . . . Details for other custom actions in the Info View not shown . . .
            </getExtendedMetadataResult>
        </getExtendedMetadataResponse>
    </soap:Body>
</soap:Envelope>

Note the following when you provide action and its sub-elements for an HTTP request action to remove a favorite. For complete details, see relatedActions.

  • The title value DELETE_MUSIC corresponds to a text value in your Localization Resources.
  • The actionType value for an HTTP request action must be simpleHttpRequest.
  • The simpleHttpRequestAction element requires the following:
    • url—The URL of the HTTP REST request to your service.
    • method—The HTTP method to execute on your service. Use DELETE to remove a favorite.
  • (Optional) Set the showInBrowse value to true if you want the listener to be able to remove a favorite either when browsing or playing the item in the Sonos app. Set this value to false if you do not want the listener to be able to remove the favorite when browsing.

Implement a REST method to add a favorite

The following steps describe how to add a favorite on your service when the listener has chosen the HTTP request action from the Info View.

  1. Sonos sends the HTTP REST request using the PUT method and URL you provided in your getExtendedMetadata response.
  2. Sonos also includes the current authentication token in an Authorization header as an OAuth Bearer token. For example:
    PUT https://192.168.0.10:8223/v2/favorites?trackId=tr:15  
    Host: music.acme.com  
    clientid: sonos-to-acme-client  
    Authorization: Bearer 614e6c9ce07be03ece09a8639ea40dcbd
    

For more about authorization and authentication tokens, see Use authentication tokens.

  1. Your service implementation of the REST API adds the item to the listener's favorites list.

  2. Your service sends a response to the Sonos app that provides a new action in the Info View that allows the listener to change their mind and remove the favorite if they wish.

    HTTP/1.1 201  
    Content-Type: application/json;charset=UTF-8  
    Transfer-Encoding: chunked  
    Connection: close
    
    {  
        "relatedActions": [  
            {  
                "actionType": "simpleHttpRequest",  
                "id": "remove_item_from_favorites_id",  
                "title": "DELETE_MUSIC",  
                "simpleHttpRequestAction": {  
                    "httpHeaders": [  
                        {  
                            "name": "clientid",  
                            "value": "sonos-to-acme-client"  
                        }  
                    ],  
                    "method": "DELETE",  
                    "refreshOnSuccess": true,  
                    "url": "<https://192.168.0.10:8223/v2/favorites?itemId=tr:15>"  
                },  
                "showInBrowse": true,  
                "successMessageStringId": "DELETE_SUCCESS",  
                "failureMessageStringId": "DELETE_FAILED"  
            },  
            {  
                "actionType": "openUrl",  
                "failureMessageStringId": "OPEN_URL_ACTION_FAILED",  
                "id": "concerts_action_id",  
                "openUrlAction": {  
                    "url": "<https://www.acme.com/concerts/?artistId=a:12345678&tracker=foo>"  
                },  
                "showInBrowse": true,  
                "title": "CONCERTS_STRING"  
            }  
        ],  
        "successMessageStringId": "ADD_SUCCESS"  
    }
    

The JSON relatedActions object provides a new HTTP request to remove the favorite that was just added as well as any other related actions you might require. See The relatedActions structure for full details. Note the following:

First action

  • The title value, DELETE_MUSIC, corresponds to the stringId value in your Localization Resources.
  • The simpleHttpRequestAction can include the following in any order:
    • method—The required HTTP method to execute for the new HTTP action. Use DELETE to remove a favorite.
    • url—The required URL of the new HTTP request that Sonos would send if the listener decides to selects the new HTTP action.
    • refreshOnSuccess—(Optional) Set this option to true so that the Sonos app will send a request to update the current container after removing the item.
  • (Optional) Use a showInBrowse value of true if you want the listener to be able to remove a favorite when browsing their favorites from the Sonos app.
  • (Optional) you can supply string ID values for successMessageStringId and failureMessageStringId that Sonos would display to the listener depending on the results of the new HTTP request. The values correspond to text values in your Localization Resources.

Second action

  • (Optional) An openUrl action is included in this example. You can include more than one action in your response to the original HTTP request. See Web page for detail.
  • (Optional) This final successMessageStringId refers to a success message for the original add favorite HTTP request. This message would override a successMessageStringId value if it was supplied in the original getExtendedMetadata response.

Implement a REST method to remove a favorite

The following steps describe how to remove a favorite from your service when the listener has chosen the HTTP request action from the Sonos Info View.

  1. Sonos sends the HTTP REST request using the DELETE method and URL you provided in your getExtendedMetadata response.
  2. Sonos also includes the current authentication token in an Authorization header as an OAuth Bearer token. For example:
    DELETE https://192.168.0.10:8223/v2/favorites?trackId=tr:15  
    Host: music.acme.com  
    clientid: sonos-to-acme-client  
    Authorization: Bearer 614e6c9ce07be03ece09a8639ea40dcbd
    

For more about authorization and authentication tokens, see Use authentication tokens.

  1. Your service implementation of the REST API removes the item from the listener's favorites list.

  2. Your service sends a response to the Sonos app that provides a new action in the Info View that allows the listener to change there mind and add the favorite back if they wish.

    HTTP/1.1 201  
    Content-Type: application/json;charset=UTF-8  
    Transfer-Encoding: chunked  
    Connection: close
    
    {  
        "relatedActions": [  
            {  
                "actionType": "simpleHttpRequest",  
                "id": "add_item_to_favorites_id",  
                "title": "SAVE_MUSIC",  
                "simpleHttpRequestAction": {  
                    "httpHeaders": [  
                        {  
                            "name": "clientid",  
                            "value": "sonos-to-acme-client"  
                        }  
                    ],  
                    "method": "PUT",  
                    "refreshOnSuccess": true,  
                    "url": "<https://192.168.0.10:8223/v2/favorites?itemId=tr:15>"  
                },  
                "showInBrowse": true,  
                "successMessageStringId": "ADD_SUCCESS",  
                "failureMessageStringId": "ADD_FAILED"  
            },  
            {  
                "actionType": "openUrl",  
                "failureMessageStringId": "OPEN_URL_ACTION_FAILED",  
                "id": "concerts_action_id",  
                "openUrlAction": {  
                    "url": "<https://www.acme.com/concerts/?artistId=a:12345678&tracker=foo>"  
                },  
                "showInBrowse": false,  
                "title": "CONCERTS_STRING"  
            }  
        ],  
        "successMessageStringId": "DELETE_SUCCESS"  
    }
    

The JSON relatedActions object provides a new HTTP request to add the favorite that was just removed as well as any other related actions you might require. Note the following about the relatedActions structure:

First action

  • The title value, ADD_MUSIC, corresponds to the stringId value in your Localization Resources.
  • The simpleHttpRequestAction can include the following in any order:
    • method - The required HTTP method to execute for the new HTTP action. Use PUT to remove a favorite.
    • url - The required URL of the new HTTP request that Sonos would send if the listener decides to selects the new HTTP action.
    • refreshOnSuccess - (Optional) Set this option to true so that the Sonos app updates the current container after adding the item.
  • (Optional) Use a showInBrowse value of false if you don't want to show this to the listener when they browse their favorites from the Sonos app. This way the listener doesn't see an action to add the favorite to their favorites when they're browsing their favorites.
  • (Optional) you can supply string ID values for successMessageStringId and failureMessageStringId that Sonos would display to the listener depending on the results of the new HTTP request. The values correspond to text values in your Localization Resources.

Second action

  • (Optional) An openUrl action is included in this example. You can include more than one action in your response to the original HTTP request. See Web page for details.
  • (Optional) This final successMessageStringId refers to a success message for the original add favorite HTTP request. This message would override a successMessageStringId value if it was supplied in the original getExtendedMetadata response.

Display your favorites

In order for the listener to browse and select their favorites, you provide access to the favorites from the top-level (root) container. The following screen shows an example of how a listener accesses favorites.

The following steps describe how to display in the Sonos app the listener's favorites from your service.

  1.  When the Sonos listener starts using your service or browses to the top of your service, Sonos sends your service a getMetadata request for the top-level root of your containers. The following is a sample request for the root.

    <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <getMetadata xmlns="http://www.sonos.com/Services/1.1">
          <id>root</id>
          <index>0</index>
          <count>100</count>
        </getMetadata>
      </soap:Body>
    </soap:Envelope>
    
  2. Return a favorites container with the other top-level item types in the getMetadata response. The favorites is a container itemType with the containsFavorite element set to true.This tells the Sonos app to poll more frequently for changes to this container.

    <soap:Envelope
        xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
      <soap:Body>
        <getMetadataResponse
            xmlns="http://www.sonos.com/Services/1.1">
          <getMetadataResult>
            <index>0</index>
            <count>4</count>
            <total>4</total>
            <mediaCollection readOnly="false" userContent="true" renameable="false">
              <id>playlists</id>
              <itemType>playlist</itemType>
              <title>Playlists</title>
              <canScroll>false</canScroll>
              <canPlay>false</canPlay>
              <canEnumerate>true</canEnumerate>
              <albumArtURI>http://icons.com/playlists-icon.png</albumArtURI>
              ...   
            </mediaCollection>
            <mediaCollection>
              <id>favorites</id>
              <itemType>container</itemType>
              <title>My Acme Favorites</title>
              <containsFavorite>true</containsFavorite>
              <albumArtURI>http://icons.com/favorites-icon.png</albumArtURI>
              ...
            </mediaCollection>
            <mediaCollection>
              <id>new</id>
              <itemType>trackList</itemType>
              <title>New</title>
              <canPlay>false</canPlay>
              <albumArtURI>http://icons.com/new-icon.png</albumArtURI>
              ...
            </mediaCollection>
            <mediaCollection>
              <id>surprises</id>
               <itemType>container</itemType>
               <displayType>genreMood</displayType>
               <title>Surprises</title>
               <canPlay>false</canPlay>
              <albumArtURI>http://icons.com/surprises-icon.png</albumArtURI>
               ...
            </mediaCollection>
          </getMetadataResult>
        </getMetadataResponse>
    ...
    
  3. When the listener selects the favorites node, Sonos sends another getMetadata request that you respond to with the listener's favorites on your service.

Provide a hierarchy of favorites

While you could place albums, songs, and other items in the same mediaCollection under a node such as “favorites”,  you might not want to mix all the listener's favorites together. For example, to separate favorite songs from favorite albums, create a hierarchical organization beneath the "favorites" node such as the following:

My Acme Favorites <id>favorites
    /Albums/ <id>albumList
    /Songs/ <id>songList

If your service implemented this hierarchy, when the Sonos app sends an HTTP request with an album ID, your service should act on your favorites "albumList". When the Sonos app sends a similar request with a track ID, your service should act on your favorites "songList". To create the albumList and songList nodes, your service would return the following when the listener browses into the favorites container:

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMetadataResponse
        xmlns="http://www.sonos.com/Services/1.1">
      <getMetadataResult>
        <index>0</index>
        <count>2</count>
        <total>2</total>
        <mediaCollection>
          <itemType>container</itemType>
          <id>albumList</id>
          <title>My Favorite Albums</title>
          <containsFavorite>true</containsFavorite>
          ...
        </mediaCollection>
        <mediaCollection>
          <itemType>container</itemType>
          <id>songList</id>
          <title>My Favorite Songs</title>
          <containsFavorite>true</containsFavorite>
          ...
        </mediaCollection>
      </getMetadataResult>
    </getMetadataResponse>
   </soap:Body>
</soap:Envelope>

Be sure to update all favorites and the favorites value before responding to getLastUpdate requests as described in Synchronize your favorites because all child nodes are governed by the parent node that is marked with containsFavorites set to true.


Synchronize your favorites

Update your favorites to stay synchronized. Sonos periodically sends a getLastUpdate request to check for changes. If changes have occurred for favorites, be sure to update the favorites value before you send the getLastUpdate response. When the Sonos app recognizes that the favorites value has changed, it will send a new getMetadata request to get the new container content.

Similarly, if a listener updates their favorites using another method such as your music app, be sure to update the favorites value. Then when the Sonos app sends getLastUpdate requests, your service responds with the new favorites value so that Sonos will know to send a getMetadata request to display the changes to the listener.


Deprecated method for implementing favorites

⚠️

Implementing favorites

This is the old method to implement favorites. If your integration already implemented favorites as described here, it will continue to work. For new integrations, see above for how to implement favorites.

Listeners can store favorite songs and albums on their Sonos system, your music service, or both. For example, a listener would choose Add Song to My Library to add it as a music service favorite, or Add song to Sonos Favorites to add it as a Sonos favorite:

Listeners can save any playable itemType to their Sonos favorites. Sonos players store Sonos favorites. Listeners can access them from the Sonos Favorites menu on the Sonos app. You do not need to do anything special to enable Sonos favorites. However, you can prevent a stream from being added as a favorite by setting isEphemeral to true in the streamMetadata object in your response (see the link for details).

You can also enable listeners to save favorite tracks and albums on your music service. This may be useful if you have your own app for listeners of your service. You can enable music service favorites to keep listener favorites in sync on Sonos and your music app. The rest of this document describes how to implement music service favorites.

Listeners use the Info View to add or remove favorite items. See Add actions for details.

Enable music service favorites

To enable listeners to add music service favorites:

You can also customize the way the Sonos app displays service favorites to listeners. For example, you can change the text that listeners select. You can also set up a hierarchy to store different kinds of favorites.

Turn on the album or track favorites capabilities

In order for listeners to select favorites in your service, you must enable the appropriate capabilities. You can choose to implement track, album, or both types of favorites. Choose the following capabilities:

  • "Favorites: Adding/Removing Tracks"
  • "Favorites: Adding/Removing Albums"
  • "Extended Metadata (for MOAPI-based InfoView)"

When testing your service, use the customSD.htm page on a player to choose capabilities, as described in Test your service on Sonos with customSD. When submitting your service to Sonos, use the Version Manager to choose the same capabilities for your service in production. See Submit your service for details.

Specify if a container contains favorites in your getMetadata response

If you will be presenting a user's music service favorites to them, you must configure it at the root level with a container itemType. Set the containsFavorite element to true to indicate to the Sonos app this holds favorites. For example, given the following request:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMetadata xmlns="http://www.sonos.com/Services/1.1">
      <id>root</id>
      <index>0</index>
      <count>100</count>
    </getMetadata>
  </soap:Body>
</soap:Envelope>

Your service might return the favorites container, among others, as shown below:

<soap:Envelope
    xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
  <soap:Body>
    <getMetadataResponse
        xmlns="http://www.sonos.com/Services/1.1">
      <getMetadataResult>
        <index>0</index>
        <count>3</count>
        <total>3</total>
        <mediaCollection>
          <itemType>container</itemType>
          <id>favorites</id>
          <title>My Favorites</title>
          <containsFavorite>true</containsFavorite>
          ...
        </mediaCollection>
        ...

Add additional child containers under this favorites container to provide a hierarchical organization to a user's favorites. See below for details.

Implement favorites in getExtendedMetadata, createItem, deleteItem, and getLastUpdate

When the listener selects the Info View for an album or track, the Sonos app sends a getExtendedMetadata request to your service. Your response will determine the options to display for the user. This can include the option to add or remove a music service favorite.

When the listener chooses to add a favorite, Sonos sends a createItem request to your service. When they choose to remove a favorite, Sonos sends a deleteItem request. To keep the Sonos app aware of changes made to listener favorites, Sonos sends getLastUpdate requests immediately following successful createItem and deleteItem responses, as well as at your specified polling interval.

Workflow: adding or removing a track or album favorite

The following describes the flow when adding or removing a track or album to a listener’s favorites:

  1. When the listener chooses the Info View for a track or album, the Sonos app calls getExtendedMetadata with the track or album ID. See Add actions for details.
  2. The Sonos app uses your response to getExtendedMetadata to display the Info View, including:
    • "Save to Your Music" if the isFavorite parameter is false.
    • "Remove from Your Music" if the isFavorite parameter is true. You can customize this string in your Localization Resources. See below for details.
  3. When the listener selects:
    • "Save to Your Music", the Sonos app calls createItem with the track or album ID.
    • "Remove from Your Music", the Sonos app calls deleteItem with the track or album ID.
  4. Depending on the selection, modify your list of favorites for the user:
    • If the listener added the item to favorites, in your createItem implementation, add this item to a list of favorites your service maintains for this listener.
    • If the listener removed the item from their favorites, in your deleteItem implementation, remove this item from any list of favorites your service maintains for this listener.
  5. After the Sonos app receives a response to createItem or deleteItem, it immediately calls getLastUpdate to see if a change has occurred so it can pull the latest changes with a call to getMetadata. Other active Sonos apps in the household may not reflect these changes until they call getLastUpdate. See the note below for details.

Stay in sync! Update favorites before sending getLastUpdate response

Be sure to update all music service favorites on your service and update the favorites value for your getLastUpdate response before you respond to the getLastUpdate request. When the Sonos app sees that the favorites value has changed, it will send a new getMetadata request to get the new container content.

Similarly, if a listener updates their favorites using your proprietary music app, update the favorites value for your getLastUpdate response so that when Sonos apps send getLastUpdate requests at the polling interval, they will know to send getMetadata requests to display these changes to the listener.

Localization and error handling

You can change the text for the "Add Song to My Library" and "Delete Song from My Library" Info View options by setting text values in your Localization Resources. First, specify the add track, remove track, add album, and remove album from favorites menu items in your presentation map. See Customize display for details. Include text values, as well as for the failure, in progress, and success states. For the remove favorite action, include a prompt string ID if you want to prompt the user to give them an option to reconsider. For example, "Are you sure you want to remove this track from Your Music?"

Here's an example of some strings in an i18next file format:

{
    "en-US":{
      "common":{
          ...
          },
      "integration":{
        "SAVE_ALBUM": "Add Song to My Library",
        "DELETE_ALBUM": "Delete Song from My Library",
        "SAVE_TRACK": "Add Album to My Library",
        "DELETE_TRACK": "Delete Album from My Library"
        ...
      }
    },
}

See Add actions for details.

Hierarchical nodes beneath favorites

While you could place albums and songs in the same mediaCollection under a root node called “Favorites,” you might not want to mix all user favorites together. For example, you may want to separate favorite songs from favorite albums. To do this, you should create some sort of organization beneath the root-level favorites node. You might have a hierarchy somewhat similar to this:

My Library/ (itemType.favorites)  
 Albums/ (itemType.albumList)  
 Songs/ (itemType.trackList or itemType.Playlist)

If you implement the hierarchy above, when the Sonos app sends a createItem or deleteItem request with an album ID, it should act on Albums list in My Library. When the Sonos app sends a similar request with a track ID, it should act on the Songs list in My Library. You would still update all favorites before responding to the getLastUpdate request as described earlier as all child nodes are governed by the parent node marked as favorites in the itemType element.