Book

Exploring Freelancing

Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!


Exploring MusicKit

I wrote this book to fill in the gap for the documentation, filled with examples so that you do not have to spend time experimenting yourself.

I hope this book provides value to you and your app, and you enjoy working with MusicKit and integrating Apple Music into your app!

Use the discount code “early” for a massive 75% discount!

I want this!


While writing the article on Exploring Genres in MusicKit for Swift, I heavily relied on Postman for experimenting with the responses from the Apple Music API.

Although you can debug print the response while using MusicKit, the biggest disadvantage of writing this post is that it does not support a simulator. If you try to do so, you get this error:

Failed retrieving MusicKit tokens: this is not supported in the simulator; please test this on a physical device. Throwing .developerTokenRequestFailed.

Setting up Apple Music API

The Apple Music API gives you access to the media in the Apple Music catalog and the user’s personal iCloud Music Library, and everything in between.

You can use the given APIs to retrieve information about albums, songs, artists, playlists, music videos, stations, ratings, charts, recommendations, etc. You can also search for different content in the catalog and the personal library.

Explore the different APIs here.

MusicKit Identifier and Private Key

You require a developer token for accessing the catalog and a user token for accessing their library. Note that if you are using MusicKit for Swift, you do not need to create anything manually.

However, you create a JSON Web Token (JWT) to communicate to Apple Music using Postman.

For this, you create a Music ID and a Key that will generate the developer token later on. In the Developer Portal, head over the Account section and select Certificates, Identifiers & Profiles.

  • In the sidebar, select Identifiers,
  • Click the Add button (+),
  • Choose MusicKit IDs, and
  • Click Continue.

Finally, enter some description and the identifier in a reverse-domain style.

Click Continue, and then Register.

Now, you need to create a key for this Music ID.

  • Select Keys from the sidebar,
  • Click the Add button (+),
  • Enter the Key Name accordingly, and
  • Enable MusicKit service.

Click on the Configure button.

Select the Music ID you configured in the previous step from the dropdown menu.

Click Save.

You are taken back to the previous page.

Click Continue and then Register to proceed further.

Click on the Download button to finally retrieve the key. Save it somewhere to access it to generate the developer token. You also need the Key ID mentioned on this page later.

Name: PlayParamsExample
Key ID: 1A2B3C4D5C // <-- Take a note of this Key ID
Services: MusicKit

Developer Token

As mentioned above, note where you saved the Key and the corresponding Key ID. You will also need your Team ID. For generating the JSON Web Token, you can use SwiftJWTSample as a package by Klass.

Run the following command:

swift run generateToken <team-id> <key-id> path_to_keys/AuthKey.p8

For example, here is a sample usage:

rudrankriyam@MacBook-Pro ~ % cd /Users/rudrankriyam/Desktop/SwiftJWTSample

rudrankriyam@MacBook-Pro SwiftJWTSample % swift run generateToken ZYXWDQWERTY 1A2B3C4D5C /Users/rudrankriyam/Desktop/AuthKey_ 1A2B3C4D5C.p8

You will see the JSON Web Token in the output if you did everything correctly. Copy the token, and save it for the next step.

Using Apple Music API

With every request, you need to send the value “Bearer " for the header "Authorization".

Let us take an example of fetching the catalog charts. The endpoint for it is:

https://api.music.apple.com/v1/catalog/{storefront}/charts

storefront is a required path parameter, and types is a required query parameter. The possible values for it are albums, music-videos, playlists and songs.

Example URL for fetching most played songs with a limit of 2 of genre alternatives:

https://api.music.apple.com/v1/catalog/in/charts?types=songs&limit=2&genre=20&chart=most-played

Sending the command on Postman:

You will get the following response in return:

Response
{
    "results": {
        "songs": [
            {
                "chart": "most-played",
                "name": "Top Songs",
                "orderId": "most-played:songs",
                "next": "/v1/catalog/in/charts?chart=most-played&genre=20&limit=2&offset=2&types=songs",
                "data": [
                    {
                        "id": "1508562516",
                        "type": "songs",
                        "href": "/v1/catalog/in/songs/1508562516",
                        "attributes": {
                            "previews": [
                                {
                                    "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/d6/34/b2/d634b201-0f5f-ad53-53d9-1d234d8cb906/mzaf_4956443266741752293.plus.aac.p.m4a"
                                }
                            ],
                            "artwork": {
                                "width": 3000,
                                "height": 3000,
                                "url": "https://is2-ssl.mzstatic.com/image/thumb/Music115/v4/da/8b/77/da8b7731-6f4f-eacf-5e74-8b23389eefa1/20UMGIM03371.rgb.jpg/{w}x{h}bb.jpg",
                                "bgColor": "ccabe7",
                                "textColor1": "0c000f",
                                "textColor2": "33003d",
                                "textColor3": "32223a",
                                "textColor4": "52225f"
                            },
                            "artistName": "Glass Animals",
                            "url": "https://music.apple.com/in/album/heat-waves/1508562310?i=1508562516",
                            "discNumber": 1,
                            "genreNames": [
                                "Alternative",
                                "Music"
                            ],
                            "durationInMillis": 238805,
                            "releaseDate": "2020-06-29",
                            "name": "Heat Waves",
                            "isrc": "GBUM72000433",
                            "hasLyrics": true,
                            "albumName": "Dreamland",
                            "playParams": {
                                "id": "1508562516",
                                "kind": "song"
                            },
                            "trackNumber": 14,
                            "composerName": "Dave Bayley"
                        }
                    },
                    {
                        "id": "1227451772",
                        "type": "songs",
                        "href": "/v1/catalog/in/songs/1227451772",
                        "attributes": {
                            "previews": [
                                {
                                    "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview125/v4/01/11/8b/01118b7d-8dfd-4bda-b431-3172d0a7b09a/mzaf_11749717436518009661.plus.aac.p.m4a"
                                }
                            ],
                            "artwork": {
                                "width": 1425,
                                "height": 1425,
                                "url": "https://is2-ssl.mzstatic.com/image/thumb/Music114/v4/fb/bf/6d/fbbf6d06-9a6c-9c49-c313-aed403613252/075679900180.jpg/{w}x{h}bb.jpg",
                                "bgColor": "242424",
                                "textColor1": "e4e4e4",
                                "textColor2": "cdcdcd",
                                "textColor3": "bdbdbd",
                                "textColor4": "ababab"
                            },
                            "artistName": "Jaymes Young",
                            "url": "https://music.apple.com/in/album/infinity/1227451760?i=1227451772",
                            "discNumber": 1,
                            "genreNames": [
                                "Alternative",
                                "Music"
                            ],
                            "durationInMillis": 237655,
                            "releaseDate": "2017-06-23",
                            "name": "Infinity",
                            "isrc": "USAT21700938",
                            "hasLyrics": true,
                            "albumName": "Feel Something",
                            "playParams": {
                                "id": "1227451772",
                                "kind": "song"
                            },
                            "trackNumber": 12,
                            "composerName": "Billboard & Jaymes Young"
                        }
                    }
                ],
                "href": "/v1/catalog/in/charts?chart=most-played&genre=20&limit=2&types=songs"
            }
        ]
    },
    "meta": {
        "results": {
            "order": [
                "most-played:songs"
            ]
        }
    }
}

You can easily experiment/explore other catalog APIs on Postman by sending the developer token in the header.

Generating User Token

If you want to explore the APIs that requires the user token, you can create one by simply running the following code in a sample app and printing the token to use later:

import StoreKit 
 let userToken = try await SKCloudServiceController().requestUserToken(forDeveloperToken: "<developerToken>")

print(userToken)

In Postman, add another header, “Music-User-Token” with the value “<userToken”.

Let us take an example of fetching my recently played track of the type songs and limiting it to 1:

https://api.music.apple.com/v1/me/recent/played/tracks?limit=1&types=songs

The response in Postman is:

Response
{
    "next": "/v1/me/recent/played/tracks?offset=1",
    "data": [
        {
            "id": "1544326470",
            "type": "songs",
            "href": "/v1/catalog/in/songs/1544326470",
            "attributes": {
                "previews": [
                    {
                        "url": "https://audio-ssl.itunes.apple.com/itunes-assets/AudioPreview115/v4/0c/ee/13/0cee1377-e29e-f636-4c17-60ea9dd66642/mzaf_2049439473266127461.plus.aac.p.m4a"
                    }
                ],
                "artwork": {
                    "width": 3000,
                    "height": 3000,
                    "url": "https://is5-ssl.mzstatic.com/image/thumb/Music124/v4/92/cc/83/92cc83f1-dd3b-b47c-8b71-605fa878b2ac/886448976905.jpg/{w}x{h}bb.jpg",
                    "bgColor": "191919",
                    "textColor1": "ffffff",
                    "textColor2": "d4d1d2",
                    "textColor3": "d0d0d0",
                    "textColor4": "aeacad"
                },
                "artistName": "G-Eazy & Bebe Rexha",
                "url": "https://music.apple.com/in/album/me-myself-i/1544326461?i=1544326470",
                "discNumber": 1,
                "genreNames": [
                    "Hip-Hop/Rap",
                    "Music"
                ],
                "durationInMillis": 251465,
                "releaseDate": "2015-10-30",
                "name": "Me, Myself & I",
                "isrc": "USRC11502210",
                "hasLyrics": true,
                "albumName": "When It's Dark Out (Deluxe Edition)",
                "playParams": {
                    "id": "1544326470",
                    "kind": "song"
                },
                "trackNumber": 3,
                "composerName": "Gerald Gillum, Michael Keenan, Christoph Andersson, Bleta Rexha, Tom Barnes, Ben Kohn, Lauren Edwards & Peter Kelleher",
                "contentRating": "explicit"
            }
        }
    ]
}

This way, you can get your stations, heavy rotation just by modifying the URL without changing the headers. It gives you a better (with faster iteration) idea of what type of structure you received from the response.

Conclusion

While I hope that MusicKit supports the simulator this WWDC, I find it better to create a Collection in Postman to save all the requests in one place to explore and experiment.

If you have a better approach, tag me on Twitter and let me know!

Thanks for reading, and I hope you’ll enjoy exploring Apple Music API!

Book

Exploring Freelancing

Navigate freelancing as a developer; find clients, manage contracts, ensure timely payment, and learn from experiences!