Issues retrieving Apple Music Storefront ID using the API

Hello,

I am having trouble retrieving the Storefront ID for my Apple Music account using the API. I am using the following code to make a GET request to the /me/storefront endpoint:

func getStoreFrontID(userToken: String) { let url = URL(string: "https://api.music.apple.com/v1/me/storefront")! var request = URLRequest(url: url) request.httpMethod = "GET" request.addValue("Bearer (userToken)", forHTTPHeaderField: "Authorization")

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
    if let error = error {
        print("Error: \(error.localizedDescription)")
        return
    }
    
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        print("Error: Invalid HTTP response")
        if let data = data,
           let errorMessage = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
           let message = errorMessage["errorMessage"] as? String {
            print("Error message: \(message)")
        } else {
            print("HTTP response: \(response.debugDescription)")
        }
        return
    }
    
    guard let data = data else {
        print("Error: No data received")
        return
    }
    
    do {
        let json = try JSONSerialization.jsonObject(with: data, options: [])
        if let dictionary = json as? [String: Any],
           let storefrontID = dictionary["defaultStorefront"] as? String {
            print("Store Front ID!: \(storefrontID)")
        }
    } catch {
        print("Error: \(error.localizedDescription)")
    }
}

task.resume()

}

The response I receive is a 403 error code with the following message:

Invalid HTTP response HTTP response: Optional(<NSHTTPURLResponse: 0x283989460> { URL: https://api.music.apple.com/v1/me/storefront } { Status Code: 403, Headers {...})

I'm not sure what's causing this issue, as I have confirmed that my user token is valid and authorized for Apple Music. Is there any additional step I need to take in order to retrieve the Storefront ID? Any help would be greatly appreciated.

Thank you.

Answered by iAmBowser in 748608022

func getStoreFrontID(userToken: String, developerToken: String) {
    let url = URL(string: "https:&#x2F;&#x2F;api.music.apple.com&#x2F;v1&#x2F;me&#x2F;storefront")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.addValue("Bearer \(developerToken)", forHTTPHeaderField: "Authorization")
    request.addValue(userToken, forHTTPHeaderField: "Music-User-Token")

    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let error = error {
            print("Error: \(error.localizedDescription)")
            return
        }

        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            print("Error: Invalid HTTP response")
            if let data = data,
               let errorMessage = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
               let message = errorMessage["errorMessage"] as? String {
                print("Error message: \(message)")
            } else {
                print("HTTP response: \(response.debugDescription)")
            }
            return
        }

        guard let data = data else {
            print("Error: No data received")
            return
        }

        do {
            let json = try JSONSerialization.jsonObject(with: data, options: [])
            if let dictionary = json as? [String: Any],
               let storefrontID = dictionary["defaultStorefront"] as? String {
                print("Store Front ID!: \(storefrontID)")
            }
        } catch {
            print("Error: \(error.localizedDescription)")
        }
    }

    task.resume()
}

This is the corrected function which takes the user token and developer token as parameters and makes a GET request to the /me/storefront endpoint to fetch the Storefront ID. It handles the response and prints the Storefront ID or any errors that occur during the process.

For the "Authorization", you are supposed to add the developer token, and not the user token. You add the user token for the "Music-User-Token" header. Your code should look like:

func getStoreFrontID(userToken: String) { 
let url = URL(string: "https:&#x2F;&#x2F;api.music.apple.com&#x2F;v1&#x2F;me&#x2F;storefront")! 
var request = URLRequest(url: url)
request.httpMethod = "GET" 
request.addValue("Bearer (developerToken)", forHTTPHeaderField: "Authorization")
request.addValue(userToken, forHTTPHeaderField: "Music-User-Token")

&#x2F;&#x2F;&#x2F; other code 

I am not sure about the iOS version you are using, but if you are using iOS 15+, it is better to just use MusicKit for Swift. One line of code. Don't have to deal with developer nor user token.

let storefront = try await MusicDataRequest.currentCountryCode
Accepted Answer

func getStoreFrontID(userToken: String, developerToken: String) {
    let url = URL(string: "https:&#x2F;&#x2F;api.music.apple.com&#x2F;v1&#x2F;me&#x2F;storefront")!
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.addValue("Bearer \(developerToken)", forHTTPHeaderField: "Authorization")
    request.addValue(userToken, forHTTPHeaderField: "Music-User-Token")

    let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
        if let error = error {
            print("Error: \(error.localizedDescription)")
            return
        }

        guard let httpResponse = response as? HTTPURLResponse,
              (200...299).contains(httpResponse.statusCode) else {
            print("Error: Invalid HTTP response")
            if let data = data,
               let errorMessage = try? JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
               let message = errorMessage["errorMessage"] as? String {
                print("Error message: \(message)")
            } else {
                print("HTTP response: \(response.debugDescription)")
            }
            return
        }

        guard let data = data else {
            print("Error: No data received")
            return
        }

        do {
            let json = try JSONSerialization.jsonObject(with: data, options: [])
            if let dictionary = json as? [String: Any],
               let storefrontID = dictionary["defaultStorefront"] as? String {
                print("Store Front ID!: \(storefrontID)")
            }
        } catch {
            print("Error: \(error.localizedDescription)")
        }
    }

    task.resume()
}

This is the corrected function which takes the user token and developer token as parameters and makes a GET request to the /me/storefront endpoint to fetch the Storefront ID. It handles the response and prints the Storefront ID or any errors that occur during the process.

Issues retrieving Apple Music Storefront ID using the API
 
 
Q