Universal search enables Sonos users to find content across multiple music services on a Sonos app. Users can find content throughout different categories, such as artists, tracks, albums, or others. Users must have an account on a music service for it to be shown in the results. Sonos apps display results alphabetically by music service. This guide goes over the following:
The screen shot below shows the results of a search on the Sonos app for mobile devices.

Sonos provides two different ways of searching for content. Your service must support both methods of searching to provide your listeners with the best Sonos experience.
Listeners using the Sonos app on a Mac or PC can perform a keyword search across categories in your service. Implement this by responding to a getMetadata
request for search with a list of categories. See below for details.
Listeners using the Sonos app for iOS or Android can perform a category search across multiple services at once. Implement this by sending a list of searchable categories from your presentation map. See the rest of this document for details.
How search works
- User searches for an artist, album, track, or other category in the search box on the Sonos app.
- The Sonos app sends the search request entered by the user to your service through the SMAPI search() method.
- Your service returns the results and the Sonos app aggregates and displays them.
You can offer varying degrees of search:
- Category search – offer search results using the standard Sonos search categories.
- Custom Category – offer search results using a category customized to your music service.
- Multiple Library Search – offer search results within the context of different libraries, such as a global library and a user-specific library.
You can combine these search methods to offer an extensive solution for your service. They are described below in order of complexity.
Category search
In order to offer search across all services, Sonos standardized category names. Search categories are integrated into the presentation map. The PresentationMap
element uses a “Search” type to specify your search categories and mappings. Use a Category
element inside a SearchCategories
element inside a Match
element to map a known canonical search ID to the SMAPI ID that you’ve defined for your service, using the id and mappedId
attributes, or omit the mappedId
type to use a default SMAPI ID.
- The id attribute is the canonical search ID.
- The mappedId attribute is the search term that your SMAPI implementation expects.
For example, in one of the mappings below, the “user” category is mapped to the Sonos canonical search ID “people”.
1 2 3 4 5 6 7 8 9 10 11 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category mappedId="artist" id="artists"/> <Category mappedId="album" id="albums"/> <Category mappedId="track" id="tracks"/> <Category mappedId="playlist" id="playlists"/> <Category mappedId="user" id="people"/> </SearchCategories> </Match> </PresentationMap> |
See below for the full list of Sonos canonical search IDs.
Category attributes
A Category type has the following attributes:
Name | Type | Description |
id |
CanonicalSearchId | Defines unique identifiers for known categories of searchable items across SMAPI services. One of the following is required:
|
mappedId |
string | The SMAPI identifier for the category used by the music service in search . This is optional. |
Custom Category search
Use a CustomCategory
element inside a SearchCategories
element inside a Match
element to define a searchable type that is not defined as a Sonos canonical search ID.
1 2 3 4 5 6 7 8 |
<PresentationMap type="Search"> <Match> <SearchCategories> ... <CustomCategory mappedId="my:custom:smapi_id:concerts" stringId="Concerts"/> </SearchCategories> </Match> </PresentationMap> |
Add text for the custom search category to the strings.xml file and use the stringId value to identify this value in the strings.xml file. Sonos apps use the string entry for the UI and pass the mappedId value back to your service through search
when the listener attempts to search for it.
1 2 3 4 5 6 |
<stringtables xmlns="http://sonos.com/sonosapi"> <stringtable rev="1" xml:lang="en-US"> <string stringId="Concerts">Concerts</string> </stringtable> ... </stringtables> |
Be sure that your custom category doesn’t search the same fields as an existing Sonos category. If this is the case, you should use the existing category.
CustomCategory attributes
A CustomCategory
type has the following attributes.
Name | Type | Description |
mappedId |
string | The SMAPI identifier for the category passed to search . This is required. |
stringId |
string | The string entry from strings.xml used for the UI for the custom search category. This is required. |
Multiple Library search
Sonos supports multiple searches for the same category in different contexts, for example, if your service offers a global library of songs as well as a user-specific library of songs, a user can search for a song and see the results in the global library as well as their own user library. Sonos apps for mobile devices display the search context within the search results for your service:

And Sonos apps for Windows and Mac OS offer users the ability to choose the context to search:

Use multiple SearchCategories
elements to support search results grouped by context, and then use a stringId
attribute in the SearchCategories
element to define the context for the search. Use a Category
element inside a SearchCategories
element to define search categories.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<PresentationMap type="Search"> <Match> <!-- First grouping, for user content --> <SearchCategories stringId="SEARCH_USER_CONTENT"> <Category id="tracks" mappedId="search:tracks:1"/> <Category id="albums" mappedId="search:albums:1"/> <Category id="artist" mappedId="search:artist:1"/> <Category id="playlists" mappedId="search:playlists:1"/> <Category id="tags" mappedId="search:tags:1"/> <CustomCategory stringId="SEARCH_CUSTOM" mappedId="search:custom:1"/> </SearchCategories> <!-- Second grouping, for global content --> <SearchCategories stringId="SEARCH_GLOBAL_CONTENT"> <Category id="tracks" mappedId="search:tracks:0"/> <Category id="albums" mappedId="search:albums:0"/> <Category id="artists" mappedId="search:artists:0"/> <CustomCategory stringId="SEARCH_CUSTOM" mappedId="search:custom:0"/> </SearchCategories> </Match> </PresentationMap> |
While mappedId
is an optional attribute of the Category
element, you should use this attribute when using multiple category groups to be sure that you can disambiguate them at the endpoint of your service.
Note: The Sonos app displays the search results in the order you specify in the presentation map. In the example above, the results for SEARCH_USER_CONTENT
will be displayed above the results for SEARCH_GLOBAL_CONTENT
.
Define the text to use in the user interface in the strings.xml file for these stringId
keys.
1 2 3 4 5 6 7 8 9 |
<stringtables xmlns="http://sonos.com/sonosapi"> <stringtable rev="1" xml:lang="en-US"> <string stringId="SEARCH_USER_CONTENT">Local Library</string> </stringtable> <stringtable rev="1" xml:lang="en-US"> <string stringId="SEARCH_GLOBAL_CONTENT">Global Library</string> </stringtable> ... </stringtables> |
Context search attributes
Implement context search on your existing category or custom category search using the mappedId
attribute as defined below.
Name | Type | Description |
mappedId |
string | The SMAPI identifier for the category passed to the SMAPI search() method. You should have a method to determine the search category grouping; in the example above, this is determined by appending a “:0” and “:1”. |
All search category
As part of the new search experience on Sonos, you can optimize search traffic by implementing an All search category. This category performs all-inclusive searches across your currently-supported categories, then returns a heterogeneous mix of content and category results.
Presentation map configuration
This document assumes knowledge of the presentation map configuration for Sonos search. Refer to Sample presentation map configuration for more details.
Preparing for search traffic
Search requests will come from a central Sonos cloud service, not from the user’s clients.
To enable the All search category, you must allow traffic from the following IP addresses:
Prod US | Prod EU |
---|---|
54.174.40.169 | 54.155.193.190 |
54.86.86.14 | 54.228.23.52 |
3.89.18.155 | 54.78.147.117 |
Implementing All search category
The following example will demonstrate how to implement the new All search category.
In this example, we’ll focus on the following search categories currently present in the PMAP: Artist, Album, Track, and Playlist.
1 2 3 4 5 6 7 8 9 10 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category mappedId="artist" id="artists"/> <Category mappedId="album" id="albums"/> <Category mappedId="track" id="tracks"/> <Category mappedId="playlist" id="playlists"/> </SearchCategories> </Match> </PresentationMap> |
These categories are supported in this example of the Sonos search, but your implementation may differ in supported categories.
To implement All category search, add the new all
category within the SearchCategories
tag:
1 2 3 4 5 6 7 8 9 10 11 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category mappedId="artist" id="artists"/> <Category mappedId="album" id="albums"/> <Category mappedId="track" id="tracks"/> <Category mappedId="playlist" id="playlists"/> <Category mappedId="all" id="all"/> </SearchCategories> </Match> </PresentationMap> |
You must use all
as the ID, since this will inform Sonos that the All category should be used by search experiences that support it instead of the other categories.
Fulfilling All search category requests
To fulfill a request for the new All category, ensure your service can perform cross-category searches, then return a set of cross-category results.
Your results should return in the same format type as regular SMAPI search category responses. The only difference is that the itemTypes of the responses will vary.
Testing All search category
To ensure that your SMAPI service is returning the expected results, test out the All search category calls using cURL or your preferred HTTP client.
- In the terminal, create a POST request for the All search category
id
ensuring you have valid credentials for your service.
Example request
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 |
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <soapenv:Header> <ns:credentials> <!--Optional:--> <ns:zonePlayerId>PLAYER ID</ns:zonePlayerId> <!--Optional:--> <ns:deviceId>?</ns:deviceId> <!--Optional:--> <ns:deviceProvider>?</ns:deviceProvider> <!--Optional:--> <ns:deviceCert>?</ns:deviceCert> <ns:loginToken> <ns:token>TOKEN FOR YOUR SERVICE ACCOUNT</ns:token> <ns:key>KEY FOR YOUR SERVICE ACCOUNT</ns:key> <ns:householdId>YOUR SONOS HHID</ns:householdId> </ns:loginToken> </ns:credentials> </soapenv:Header> <soapenv:Body> <ns:search> <ns:id>all</ns:id> <ns:term>the</ns:term> <ns:index>0</ns:index> <ns:count>100</ns:count> </ns:search> </soapenv:Body> </soapenv:Envelope> |
- Send the request and verify that the resulting response contains the expected information for requests made to the All search category.
Example response
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" encoding="UTF-8"?> <soapenv: Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> <soapenv: Header/> <soapenv:Body> <searchResponse xmlns="http://www.sonos.com/Services/1.1"> <searchResult> <index>0</index> <count>100</count> <total>41366</total> <mediaCollection> <id>acme: album: 4JAvwK4APPArjIs0dGoJXX</id> <itemType>album</itemType> <title>The Off-Season</title> <artist>J. Cole</artist> <artistId>acme: artist:613HvQ5sa6mXTsMTB19r05</artistId> <canPlay>true</canPlay> <canEnumerate>true</canEnumerate> <albumArtURI>http://www.dreamville.com/wp-content/uploads/2021/05/OFFSZN.jpg</albumArtURI> </mediaCollection> ... |
All search category ranking results
The All category search results are ranked in terms of relevancy. Up to nine results are presented in the default Sonos search results view per content provider.

If a user then browses into more results from your service, the full set of results will be displayed, grouped by category.

Presentation map configuration examples
The SearchCategories
element details the searchable asset types that your service provides, such as tracks, albums, stations, playlists, and so on. This element was added as of build 26.1-73040 and above. Sonos apps using build 38.1 and above can add multiple SearchCategories
elements to enable context search (see About My Sonos System in the Sonos app to find the build number).
The service in this example supports searchable artists, albums, and tracks using default SMAPI IDs:
1 2 3 4 5 6 7 8 9 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category id="artists" /> <Category id="albums" /> <Category id="tracks" /> </SearchCategories> </Match> </PresentationMap> |
This example shows a service that supports searchable artists, albums, and tracks but the SMAPI IDs for searching on those categories are different than the default:
1 2 3 4 5 6 7 8 9 10 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category id="artists" mappedId="my:custom:smapi_id:artist" /> <Category id="albums" mappedId="my:custom:smapi_id:album" /> <Category id="tracks" mappedId="my:custom:smapi_id:track" /> <Category id="podcasts" mappedId="my:custom:smapi_id:shows" /> </SearchCategories> </Match> </PresentationMap> |
This example shows a service that supports searchable artist, albums, and tracks using a mix of default SMAPI IDs and custom SMAPI IDs, along with a CustomCategory
that is not found in the canonical search categories:
1 2 3 4 5 6 7 8 9 10 |
<PresentationMap type="Search"> <Match> <SearchCategories> <Category id="artists" /> <Category id="albums" mappedId="my:custom:smapi_id:album" /> <Category id="tracks" mappedId="my:custom:smapi_id:track" /> <CustomCategory mappedId="my:custom:smapi_id:concerts" stringId="Concerts"/> </SearchCategories> </Match> </PresentationMap> |
In the example above, the Sonos app will allow searching for artists, albums, tracks, and concerts. The Sonos app will use the stringId as the default display text. To localize this string, you must add an entry in strings.xml that maps the stringId
to appropriate text.
Strings XML localization
Following the existing Sonos app localization functionality, Sonos apps will use the stringId
from the presentation map configuration of a CustomCategory
, and look up the string node in the strings.xml configuration with the same stringId
using the language setting from the Sonos app to get the text that will be displayed to the listener. See Strings and Localization for details.
If a matching stringId
is not found, the Sonos app will default to the text configured as the stringId
in the presentation map as a fallback.
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 |
<?xml version="1.0" encoding="utf-8" ?> <stringtables xmlns="http://sonos.com/sonosapi"> <stringtable rev="1" xml:lang="en-US"> <string stringId="Concerts">Concerts</string> </stringtable> <stringtable rev="1" xml:lang="da-DK"> <string stringId="Concerts">Koncerter</string> </stringtable> <stringtable rev="1" xml:lang="de-DE"> <string stringId="Concerts">Konzerte</string> </stringtable> <stringtable rev="1" xml:lang="es-ES"> <string stringId="Concerts">Conciertos</string> </stringtable> <stringtable rev="1" xml:lang="fr-FR"> <string stringId="Concerts">Concerts</string> </stringtable> <stringtable rev="1" xml:lang="it-IT"> <string stringId="Concerts">Concerti</string> </stringtable> <stringtable rev="1" xml:lang="ja-JP"> <string stringId="Concerts">コンサート</string> </stringtable> <stringtable rev="1" xml:lang="nb-NO"> <string stringId="Concerts">Konserter</string> </stringtable> <stringtable rev="1" xml:lang="nl-NL"> <string stringId="Concerts">Concerten</string> </stringtable> <stringtable rev="1" xml:lang="pt-BR"> <string stringId="Concerts">Concertos</string> </stringtable> <stringtable rev="1" xml:lang="sv-SE"> <string stringId="Concerts">Konserter</string> </stringtable> <stringtable rev="1" xml:lang="zh-CN"> <string stringId="Concerts">音乐会</string> </stringtable> </stringtables> |
SMAPI interaction
With the proper configuration, Sonos apps will use the presentation map to configure universal search. When a listener searches for a given term, the Sonos app will submit a request to your SMAPI search endpoint for each of the SearchCategories
you have defined in the presentation map simultaneously. Using the last presentation_map.xml configuration as an example, the Sonos app will emit four SMAPI calls asynchronously:
- search(“artists”, “my term”, 0, 100)
- search(“my:custom:smapi_id:album”, “my term”, 0, 100)
- search(“my:custom:smapi_id:track”, “my term”, 0, 100)
- search(“my:custom:smapi_id:concerts”, “my term”, 0, 100)
The Sonos app then aggregates the results sent by your service and displays them accordingly. See search
for sample requests and responses.
Support search on desktop apps
You must implement search for Windows and Mac OS applications as well as Sonos apps for mobile devices. Implement search for mobile devices by sending a list of searchable categories in the SearchCategories
element in the presentation map as described above. Implement it for Windows and Mac OS by sending these categories in a response to a getMetadata
request on the search container.
The Sonos app displays the search results in the order you specify in the presentation map. For example, if your presentation map lists artists, albums, and songs from top to bottom, the Sonos desktop app displays these categories from left to right.
Request
The Sonos app for Windows and Mac OS sends a getMetadata
request on the search container for your service:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <soapenv:Header> <ns:credentials> ... </ns:credentials> </soapenv:Header> <soapenv:Body> <ns:getMetadata> <ns:id>search</ns:id> <ns:index>0</ns:index> <ns:count>10</ns:count> </ns:getMetadata> </soapenv:Body> </soapenv:Envelope> |
Response
Your service should respond with the search categories:
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 |
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <s:Body> <ns:getMetadataResponse> <ns:getMetadataResult> <ns:index>0</ns:index> <ns:count>2</ns:count> <ns:total>2</ns:total> <ns:mediaCollection> <ns:id>search:songs</ns:id> <ns:itemType>search</ns:itemType> <ns:title>Songs</ns:title> <ns:canPlay>false</ns:canPlay> <ns:albumArtURI/> </ns:mediaCollection> <ns:mediaCollection> <ns:id>search:artists</ns:id> <ns:itemType>search</ns:itemType> <ns:title>Artists</ns:title> <ns:canPlay>false</ns:canPlay> <ns:albumArtURI/> </ns:mediaCollection> </ns:getMetadataResult> </ns:getMetadataResponse> </s:Body> </s:Envelope> |
See search
for details.
Sonos app for Windows and Mac OS
In the Sonos app for Windows or Mac OS, the user searches for “rock” in the “Artists” category:

In the example above, the Sonos app sends the following request:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <soapenv:Header> <ns:credentials> <ns:loginToken> <ns:token>ABCDEFGHIJK123</ns:token> <ns:key>keyvalue</ns:key> <ns:householdId>householdId</ns:householdId> </ns:loginToken> </ns:credentials> </soapenv:Header> <soapenv:Body> <ns:search> <ns:id>search:artists</ns:id> <ns:term>rock</ns:term> <ns:index>0</ns:index> <ns:count>10</ns:count> </ns:search> </soapenv:Body> </soapenv:Envelope> |
The service responds with:
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 |
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns="http://www.sonos.com/Services/1.1"> <s:Body> <ns:searchResponse> <ns:searchResult> <ns:index>0</ns:index> <ns:count>10</ns:count> <ns:total>10</ns:total> <ns:mediaCollection> <ns:id>artist_abc123</ns:id> <ns:itemType>artist</ns:itemType> <ns:title>Rock Sound</ns:title> <ns:canPlay>false</ns:canPlay> <ns:canEnumerate>true</ns:canEnumerate> <ns:albumArtURI>https://cdn.example.com/artist_abc123.jpg</ns:albumArtURI> </ns:mediaCollection> <ns:mediaCollection> <ns:id>artist_abc456</ns:id> <ns:itemType>artist</ns:itemType> <ns:title>Bebble Rock</ns:title> <ns:canPlay>false</ns:canPlay> <ns:canEnumerate>true</ns:canEnumerate> <ns:albumArtURI>https://cdn.example.com/artist_abc456.jpg</ns:albumArtURI> </ns:mediaCollection> <ns:mediaCollection> <ns:id>artist_bcd789</ns:id> <ns:itemType>artist</ns:itemType> <ns:title>Q107Toronto</ns:title> <ns:canPlay>false</ns:canPlay> <ns:canEnumerate>true</ns:canEnumerate> <ns:albumArtURI>https://cdn.example.com/artist_bcd789.jpg</ns:albumArtURI> </ns:mediaCollection> ... </ns:searchResult> </ns:searchResponse> </s:Body> </s:Envelope> |