Introducing Playlist Collaboration to the Amazon Music API
Introducing Playlist Collaboration to the Amazon Music API¶
Today we are enabling two or more users to collaborate on a playlist through the Amazon Music API (Firefly). These capabilities can be used to 1) add collaborators to a user generated playlist; 2) send, receive and accept collaboration invites; 3) update playlist by collaborators; 4) read playlist by collaborators; and 5) view list of collaborators.
Creating the playlist¶
As a pop junkie, I want to create a new pop playlist and add my friends as collaborators allowing them to add/remove/reorder songs in my playlist, so that we can all listen to this playlist during our upcoming weekend outing. Let’s start by creating a new playlist. Users can also add collaborators on an existing user playlist.
Before creating the playlist, I will get the track ASINs I want to add to my playlist.
query {
searchTracks(searchOptions: {
searchFilters: [
{
field: "title",
query: "You Need To Calm Down"
}
],
limit: 1
}) {
edges {
node {
title,
id
}}}}
The response gives me the track ASIN.
{
"data": {
"searchTracks": {
"edges": [
{
"node": {
"title": "You Need To Calm Down",
"id": "B07T35P7C6"
}}]}}}
Now that we have a way to get track ASINs, lets create my first collaborative playlist!
mutation {
createPlaylist(
title: "My first Collab Playlist",
trackAsins: ["B07T35P7C6", "B09YG6RC8D"],
visibility: "PUBLIC",
description: "Playlist creation via FF console for launch announcement"
)
{
id,
title,
curator {
name
}
collaborators {
edgeCount
edges {
node {
name
}
}
}
tracks {
edgeCount
edges {
contributingUser {
name
}
node {
title
}}}}}
The playlist “My first Collab Playlist ” is created.
{
"data": {
"createPlaylist": {
"id": "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
"title": "My first Collab Playlist",
"curator": {
"name": "Deepa"
},
"collaborators": {
"edgeCount": 0,
"edges": []
},
"tracks": {
"edgeCount": 2,
"edges": [
{
"contributingUser": {
"name": "Deepa"
},
"node": {
"title": "You Need To Calm Down"
}
},
{
"contributingUser": {
"name": "Deepa"
},
"node": {
"title": "You Are My Sunshine"
}}]}}}
Inviting collaborators¶
Now I will add collaborators to my playlist. To do so, I will first generate a collaboration invitation with the playlist ID returned above during the creation. I will add the playlist ID to the uri : “mrn:1.0:library:playlist:uuid” parameter. Users can currently add collaborators to public user playlist only. Ability to add collaborators to private user playlists will be launched as a fast follow.
mutation {
createInvite(uri: "mrn:1.0:library:playlist:uuid:2ae510f2-6a34-4d19-a8a5-1707cb78db71", type: "PLAYLIST"){
id
url
}}
An invitation is created with invitation ID and invitation URL. This invitation ID and URL can be used to send invitation to the intended collaborators.
{
"data": {
"createInvite": {
"id": "20df1a87-af3c-479e-95af-ab4ab94df302",
"url": "https://music.amazon.com/user-playlists/2ae510f2-6a34-4d19-a8a5-1707cb78db71/invitations/20df1a87-af3c-479e-95af-ab4ab94df302"
}}}
When an invitation is received by the collaborator, experience builders can use the invitation ID to query the invitation details and required playlist metadata to show to the users. Only new collaborators can view and accept the invitations.
query {
invite(id: "20df1a87-af3c-479e-95af-ab4ab94df302", type: "PLAYLIST") {
playlist {
curator {
handle
name
}
title
images {
url
imageType
}}}}
I get back the response with invitation details.
{
"data": {
"invite": {
"playlist": {
"curator": {
"handle": "deepa10822275",
"name": "Deepa"
},
"title": "My first Collab Playlist",
"images": [
{
"url": "https://m.media-amazon.com/images/I/71NgXihplYL._US2800_BL50_BG34,34,34_CLa%7C2800,2800%7C71NgXihplYL.jpg,91lIqKCsG4L.jpg%7C0,0,2800,2800+0,0,1400,1400+1400,1400,1400,1400.jpg",
"imageType": "PRIMARY"
},
{
"url": "https://m.media-amazon.com/images/I/71NgXihplYL._BG34,34,34_CLa%7C4200,2100%7C91lIqKCsG4L.jpg,71NgXihplYL.jpg,91lIqKCsG4L.jpg,71NgXihplYL.jpg,91lIqKCsG4L.jpg,71NgXihplYL.jpg,91lIqKCsG4L.jpg,71NgXihplYL.jpg%7C0,0,1400,1400+1400,700,1400,1400+2800,0,1400,1400+0,1400,700,700+700,1400,700,700+1400,0,700,700+2100,0,700,700+2800,1400,700,700+3500,1400,700,700.jpg",
"imageType": null
}]}}}}
Once the invitation is accepted by the collaborator in the CX, experience builders can call Firefly to accept the invite with invitation ID. This will add the calling user as collaborator.
mutation {
acceptInvite(id: "20df1a87-af3c-479e-95af-ab4ab94df302", type: "PLAYLIST") {
status
}}
I see the invite is accepted successfully.
{
"data": {
"acceptInvite": {
"status": "SUCCESS"
}}}
Retrieving the playlist, I am collaborating on¶
When a collaborator accepts the invite to collaborate on a playlist, they are also automatically added as a follower to that playlist. And the playlist shows in their library under list of followed playlists. Let’s query the collaborators’ list of followed playlists.
query {
user {
followedPlaylists {
edges {
node {
id
title
}}}}}
We see in the response, “My first Collab Playlist” is added in collaborators followed playlist list.
{
"data": {
"user": {
"followedPlaylists": {
"edges": [
{
"node": {
"id": "e20aecebf32d47979cce7b4643c15cfesune",
"title": "My first Collab Playlist"
}
},
{
"node": {
"id": "PP17C52789656C4847B82CEB2994CCCF5F",
"title": "My Discovery Mix"
}}]}}}
Collaborators can also query all the playlists they are collaborating on.
query {
user {
id
handle
playlists(roleFilter: COLLABORATOR) {
edgeCount
edges {
role
node {
id
title
}}}}}
I get the response confirming the collaborator can collaborate on “My first Collab Playlist”.
{
"data": {
"user": {
"id": "pagfaoqdzmbpoarilfsezo2vae",
"handle": "rohan50064546",
"playlists": {
"edgeCount": 1,
"edges": [
{
"role": "COLLABORATOR",
"node": {
"id": "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
"title": "My first Collab Playlist"
}}]}}}}
Adding a song to the playlist as a collaborator¶
Now that “My first Collab Playlist” is created and one of my friends is added as a collaborator, let’s start collaborating!! To do so, the collaborator will first read the playlist with the playlist ID. Owners and collaborators will be able to read the playlist they are collaborating on.
query {
playlist(id: "2ae510f2-6a34-4d19-a8a5-1707cb78db71") {
id,
title,
visibility,
curator {
name
}
collaborators {
edgeCount
edges {
node {
id
name
}
}
}
tracks {
edgeCount
edges {
contributingUser {
name
}
cursor
node {
id
title
}}}}}
We have the playlist details. It shows the playlist head metadata, the curator/owner name, collaborator count and the list of collaborators. The playlist response also shows tracks attributed to the right contributor.
{
"data": {
"playlist": {
"id": "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
"title": "My first Collab Playlist",
"visibility": "PUBLIC",
"curator": {
"name": "Deepa"
},
"collaborators": {
"edgeCount": 1,
"edges": [
{
"node": {
"id": "pagfaoqdzmbpoarilfsezo2vae",
"name": "Rohan"
}
}
]
},
"tracks": {
"edgeCount": 2,
"edges": [
{
"contributingUser": {
"name": "Deepa"
},
"cursor": "0:9e42a01d-6732-465c-804b-c48c453a124c",
"node": {
"id": "B07T35P7C6",
"title": "You Need To Calm Down"
}
},
{
"contributingUser": {
"name": "Deepa"
},
"cursor": "1:b178a43a-4c3b-4201-a0f6-8f3de8e06b49",
"node": {
"id": "B09YG6RC8D",
"title": "You Are My Sunshine"
}}]}}}}
To add/remove/reorder tracks as a collaborator, the collaborator will make a playlist mutation request with intended tracks. In the response you’ll see the tracks added and attributed to the right contributor.
mutation {
appendTracks(
trackIds: ["B00OQZ4BV4","B00OQZ4D9Y"],
playlistId: "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
rejectDuplicateTracks: true)
{
id
title
tracks {
edgeCount
edges {
contributingUser {
name
}
cursor
node {
title
}}}}}
I see in the response the tracks are added to the playlist and attributed to the right contributor.
{
"data": {
"appendTracks": {
"id": "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
"title": "My first Collab Playlist",
"tracks": {
"edgeCount": 4,
"edges": [
{
"contributingUser": {
"name": "Deepa"
},
"cursor": "0:9e42a01d-6732-465c-804b-c48c453a124c",
"node": {
"title": "You Need To Calm Down"
}
},
{
"contributingUser": {
"name": "Deepa"
},
"cursor": "1:b178a43a-4c3b-4201-a0f6-8f3de8e06b49",
"node": {
"title": "You Are My Sunshine"
}
},
{
"contributingUser": {
"name": "Rohan"
},
"cursor": "2:05882d85-7960-4f8c-9c55-7515833558f4",
"node": {
"title": "Time of Our Lives [Explicit]"
}
},
{
"contributingUser": {
"name": "Rohan"
},
"cursor": "3:40372572-da98-4396-b8ea-3c18f863f4de",
"node": {
"title": "Celebrate (From the Original Motion Picture \"Penguins of Madagascar\")"
}}]}}}}
Removing a track from a playlist as a collaborator¶
Collaborators can also remove tracks and reorder tracks. To remove and re-order tracks the experience builders are required to provide unique track entry id found in the above response under “cursor” field.
mutation {
removeTracks(
entryIds: ["b178a43a-4c3b-4201-a0f6-8f3de8e06b49","40372572-da98-4396-b8ea-3c18f863f4de"],
playlistId: "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
)
{
id
title
tracks {
edgeCount
edges {
contributingUser {
name
}
cursor
node {
id
title
}}}}}
Let’s read the playlist again to make sure collaborator contributions made it to my playlist. We will use the same playlist query shown earlier to read the playlist. Here is the response.
{
"data": {
"playlist": {
"id": "2ae510f2-6a34-4d19-a8a5-1707cb78db71",
"title": "My first Collab Playlist",
"visibility": "PUBLIC",
"curator": {
"name": "Deepa"
},
"collaborators": {
"edgeCount": 1,
"edges": [
{
"node": {
"id": "pagfaoqdzmbpoarilfsezo2vae",
"name": "Rohan"
}
}
]
},
"tracks": {
"edgeCount": 2,
"edges": [
{
"contributingUser": {
"name": "Deepa"
},
"cursor": "0:9e42a01d-6732-465c-804b-c48c453a124c",
"node": {
"id": "B07T35P7C6",
"title": "You Need To Calm Down"
}
},
{
"contributingUser": {
"name": "Rohan"
},
"cursor": "1:05882d85-7960-4f8c-9c55-7515833558f4",
"node": {
"id": "B00OQZ4BV4",
"title": "Time of Our Lives [Explicit]"
}}]}}}}
And voila! My first collaborative playlist is ready for listening with track contributions from me my friends!
What’s next?¶
As a fast follow, we will launch the ability to add collaborators on private user playlists. Currently collaborators can be added to public user playlists.
Note:
You can try these queries and mutation through the firefly console. If you do so before all react native user playlist traffic is redirected from MusicPlaylistService (MuPS) to FireFly→UnifiedPlaylistService (UPS) , you’d have to add "x-amzn-feature-flags": "use-ups" to request header so that playlist requests go to UPS where part of these capabilities are built. Not adding the request header will direct calls to MuPS returning incorrect responses and errors.
