Get Songs from Apple Music API recently added

I'm working on an idea to use recently added tracks in my app.

From what I can tell, the following endpoint will only supply albums and the id's are not related to any catalog resource:

https://api.music.apple.com/v1/me/library/recently-added

However, if I use the following endpoint, I get access to a semi-deeply-nested data value that contains the goodies I'm looking for:

https://api.music.apple.com/v1/me/library/recently-added?include=catalog

This seems better than doing a search for each item, as I have access to a catalog resource id.

The data in the response is like the below.

You can see under relationships, there's catalog, and in there is data, and in there is href, which is what I want.

My problem is that I'm doing something dumb with the the decode.

I'm using MusicKit's MusicDataRequest, as I don't see a way to get this info via MusicKit methods.

And because of that, I gotta setup the request manually.

If I just decode with the following, using Album as a type, the info I want isn't there for understood reasons.

struct AppleMusicRecentlyAddedRequest: Decodable {
    // var next: String?
    var items: [Album]?
    enum CodingKeys: String, CodingKey {
        case next
        case data
    }
    init (from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        self.items = try container.decodeIfPresent([Album].self, forKey: .data)
    }
}

I've attempted to go down the rabbit hole to get at catalog's data with:

struct AppleMusicRecentlyAddedRequest: Decodable {
    var items: [???]?
        enum CodingKeys: String, CodingKey {
        case next
        case data
        case relationships
        case catalog
    }
    init (from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let dataContainer = try container.nestedContainer(keyedBy: CodingKeys.self, forKey: .data)
        let relationshipsContainer = try dataContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .relationships)
        let catalogContainer = try relationshipsContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .catalog)
        self.items = try catalogContainer.decodeIfPresent([???].self, forKey: .data)
    }
}

But anything I try for ???, including a complete manual copy of the response in a struct, isn't working, mainly because I'm not very good tat this.

The main error I get is:

Expected to decode Dictionary<String, Any> but found an array instead

Which makes me think I gotta decode catalog data, or something, but I'm at my wits end at this point.

Any tips on how to get at data would be awesome; even better would be just to the the href inside catalog/data for each item in the main response.

@JoeKun, if there's anyway that MusicKit can make this easier, kindly advise.

Thanks.

[
    {
    "id":"l.WAiAqm3",
    "type":"library-albums",
    "href":"/v1/me/library/albums/l.WAiAqm3",
    "attributes":{
        "releaseDate":"2010-12-23",
        "artwork":{
            "width":1200,
            "height":1200,
            "url":"https://is4-ssl.mzstatic.com/image/thumb/Music/df/48/bb/mzi.wxowhcmy.jpg/{w}x{h}bb.jpg"
        },
        "dateAdded":"2022-04-13T07:07:50Z",
        "name":"Play With Me Papa",
        "artistName":"John Keawe",
        "genreNames":[
            "New Age"
        ],
        "playParams":{
            "id":"l.WAiAqm3",
            "kind":"album",
            "isLibrary":true
        },
        "trackCount":1
    },
    "relationships":{
        "catalog":{
            "href":"/v1/me/library/albums/l.WAiAqm3/catalog",
            "data":[
                {
                    "id":"417478467",
                    "type":"albums",
                    "href":"/v1/catalog/us/albums/417478467",
                    "attributes":{
                        "artwork":{
                            "width":600,
                            "height":600,
                            "url":"https://is4-ssl.mzstatic.com/image/thumb/Music/df/48/bb/mzi.wxowhcmy.jpg/{w}x{h}bb.jpg",
                            "bgColor":"ecf2fe",
                            "textColor1":"3a2212",
                            "textColor2":"3f2b1b",
                            "textColor3":"5e4b41",
                            "textColor4":"615349"
                        },
                        "artistName":"John Keawe",
                        "isSingle":false,
                        "url":"https://music.apple.com/us/album/play-with-me-papa/417478467",
                        "isComplete":true,
                        "genreNames":[
                            "New Age",
                            "Music",
                            "Worldwide"
                        ],
                        "trackCount":13,
                        "isMasteredForItunes":false,
                        "releaseDate":"2010-12-23",
                        "name":"Play With Me Papa",
                        "recordLabel":"Homestead Productions",
                        "upc":"704565719925",
                        "copyright":"℗ 2010 John Keawe",
                        "playParams":{
                            "id":"417478467",
                            "kind":"album"
                        },
                        "isCompilation":false
                    }
                }
            ]
        }
]

From what I understand, dataContainer will be an array and you are expecting a dictionary there

While Joe will be able to provide a perfect answer, you can use the following structure to decode the relationship:

struct RecentlyAdded: Decodable {
  var data: [RecentlyAddedData]

  struct RecentlyAddedData: Decodable {
    var relationships: Relationships

    struct Relationships: Decodable {
      var catalog: MusicItemCollection<Album>
    }
  }
}

I am not sure how you can leverage Album and associate the relationship directly with it. Also, if you don't know, the recently-added endpoint provides playlists and stations resources apart from albums.

Looking forward to Joe's answer.

Get Songs from Apple Music API recently added
 
 
Q