When players send GET /itemWindow, they include a reason parameter to indicate why. For example, the player sends reason=load when sending GET /itemWindow because of a loadCloudQueue command.

Reason values

This table and the following sections describe each possible reason value and give situations where the player would send it in a GET /itemWindow request.

ValueDescription
loadSonos starts playback because of a loadCloudQueue command.
pauseAn explicit user action to pause playback.
playAn explicit user action to start playback.
queueCompletedThe player has finished fetching all of the audio for the current window. The player uses this reason to check for more tracks.
refreshThe player sends this reason to center the current window on the track that is currently playing.
resumeAn explicit user action to resume a suspended session. For example, the user pressed resume in the Sonos app.
skipNextAn explicit user action to skip to the next item.
skipPrevAn explicit user action to skip to the previous item.
skipToItemAn explicit user action to skip to an item in the queue that is neither the next item nor the previous item.

📘

Multiple reason values

In v2.2 of cloud queue, players can send requests with multiple reason values separated by a + symbol. Currently, the only time players do this is with reason=load+queueCompleted.


load

The load value indicates that the player is starting playback because of a loadCloudQueue command. Players only make requests for this reason if you've enabled the limitedSkips playback policy or if you don't include track metadata in the command. When you send track metadata in the command, the player starts playback immediately and the first GET /itemWindow request will have a reason of refresh.

Example use case:

  1. A listener browses your app and selects a song from their favorite playlist.
  2. Your app sends a loadCloudQueue command to the player without track metadata.
  3. The player sends GET /context to get the context for this session, and then GET /itemWindow with a reason=load to get the tracks.

pause

The pause value indicates that the player received an explicit user action to pause playback. Players only send requests for this reason when you enable the notifyUserIntent playback policy.

Example use case:

  1. A listener is enjoying a programmed radio station on Sonos.
  2. Before leaving for work, the listener uses the hardware controls on the player to pause playback.
  3. The player sends a GET /itemWindow request with reason=pause.

play

The play value indicates that the player received an explicit user action to start playback. Players send requests for this reason when playback was paused, but not suspended. Players only send requests for this reason when your service enables the notifyUserIntent playback policy. Players don’t send requests for this reason when playback starts because of a loadCloudQueue or skipToItem command.

You can use your response to requests for this reason to refresh any URL that may have expired.

Example use case:

  1. A listener is playing a new album on Sonos from your service when they have to pause playback and answer a phone call.
  2. After the phone call, the listener uses your app to resume playback, which sends a play command to the player.
  3. The player sends a GET /itemWindow request with reason=play.

queueCompleted

The queueCompleted value indicates that the player finished fetching all the audio for the current window. The player is checking the cloud queue for more tracks. If there are no more tracks, the player pauses playback after the current audio finishes playing.

Example use case:

  1. A listener is enjoying a playlist on Sonos from your service.
  2. The player finishes fetching all of the audio for the current window.
  3. The player sends GET /itemWIndow with reason=queueCompleted to check for more tracks.

refresh

The refresh value indicates that the player is trying to update the current window on the track that is playing. Players send this request in the background once they have enough audio buffered.

Example use case:

  1. A listener is enjoying a programmed radio listening session without interruptions.
  2. As playback nears the end of the current window, the player sends a GET /itemWindow request with reason=refresh to update the window around the track that is currently playing.

resume

The resume value indicates that the player is resuming a suspended session.

Example use case:

  1. A listener is playing a programmed radio station. At the start of this session, your service set the pauseTtlSec playback policy to a time of your choosing.
  2. After a time, the listener pauses the player.
  3. The amount of time you set in the pauseTtlSec playback policy goes by and the player suspends the session.
  4. The listener returns and uses the player hardware inputs to press play. Because your suspended session is still in the queue, the player sends a GET /itemWindow request with a reason=resume to continue the session.

skipNext

The skipNext value indicates that the player received an explicit user action to skip to the next item. Players only make requests for this reason if you enable either the limitedSkips or notifyUserIntent playback policy. In these cases, the player waits for your server's response before allowing the skip. Players don't send requests for this reason when they are starting playback.

Example use case:

  1. A listener is enjoying a programmed radio station.
  2. A track starts playing that the listener does not want to hear, so they use the player hardware inputs to skip to the next song.
  3. The player sends a GET /itemWindow request with reason=skipNext to your server.

skipPrev

The skipPrev value indicates that the player received an explicit user action to skip to the previous item. Players only make requests for this reason if you enable either the limitedSkips or notifyUserIntent playback policy. In these cases, the player waits for your server's response before allowing the skip. Players don't send requests for this reason when they are starting playback.

Example use case:

  1. A listener is listening to a playlist.
  2. The listener decides they want to hear the previous track again, so they use your app to return to the previous track.
  3. The player sends a GET /itemWindow request with reason=skipPrev to your server.

skipToItem

The skipToItem value indicates the user has skipped to the next track or to another track. This value is associated with the skipToItem command. Players send this reason if you enable the limitedSkips playback policy or if you don't include track metadata in the command. When you do include track metadata, the player begins fetching the audio and doesn’t immediately make a GET /itemWindow request. Later, the player sends GET /itemWindow with a reason of refresh to build a window around the track metadata that you provided in the command.

Example use case:

  1. A listener is enjoying a playlist.
  2. The listener decides to use your app to select a different track in the playlist.
  3. This sends a skipToItem command to the player.
  4. The player sends a GET /itemWindow request with reason=skipToItem to your server. This request uses the itemId from the skipToItem command to request a window around this track.

Multiple reason values

load+queueCompleted

The combination of load+queueCompleted indicates the player has downloaded all the track audio before sending the first GET /itemWindow request.

Example use case:

  1. A listener uses your app to create a playback session on Sonos.
  2. They select a very short track to start the listening session.
  3. Your app sends a loadCloudQueue command with the track metadata for this track.
  4. The player fetches the entire track before it requests an item window.
  5. The player sends a GET /itemWindow request with reason=load+queueCompleted to your server.

Error handling

If the player sends an itemId that does not exist in the cloud queue, you should send a 404 (“Not Found”) error. The player stops playback, enters PLAYBACK_STATE_IDLE, clears the queue, and waits until the user loads more content and selects a new item for playback.

The reason can be returned in the X-Rejected-Reason HTTP header for your cloud queue server, for logging purposes. For example, you could return ANOTHER_STREAM_BEING_PLAYED or STREAM_RATE_LIMIT_REACHED.

See Error handling for how to handle errors as well as a list of client and server errors.