SpotifyAPI
A Swift library for the Spotify web API
Features
- Supports all of the Spotify web API endpoints, including playing content, creating playlists, and retrieving albums.
- Uses Apple's Combine framework, which makes chaining asynchronous requests a breeze
- Supports three different authorization methods
- Automatically refreshes the access token when necessary
Read the full documentation and check out this example iOS app and this example command-line app.
Sponsors
Table of Contents
- Supported Platforms
- Installation
- Quick Start
- Authorizing with the Authorization Code Flow with Proof Key for Code Exchange
- Authorizing with the Authorization Code Flow
- Authorizing with the Client Credentials Flow
- Saving Authorization Information to Persistent Storage
- Using the Player Endpoints
- Working with Paginated Results
- Debugging
- Running the Unit Tests
Supported Platforms
- Swift 5.3+
- iOS 13+
- macOS 10.15+
- tvOS 13+
- watchOS 6+
- Linux
Installation
- In Xcode, open the project that you want to add this package to.
- From the menu bar, select File > Swift Packages > Add Package Dependency...
- Paste the URL for this repository into the search field.
- Select the
SpotifyAPI
Library. - Follow the prompts for adding the package.
Quick Start
To get started, go to the Spotify Developer Dashboard and create an app. You will receive a client id and client secret. Then, click on "edit settings" and add a redirect URI. Usually, this should be a custom URL scheme that redirects to a location in your app. DO NOT add a forward-slash to the end of the redirect URI.
The next step is authorizing your app. All requests to the Spotify web API—whether they require authorization scopes or not—require authorization This library supports three authorization methods:
-
Authorization Code Flow with Proof Key for Code Exchange: This is the best option for mobile and desktop applications where it is unsafe to store your client secret. It provides an additional layer of security compared to the Authorization Code Flow. Use this method if you need to access/modify user data, which requires authorization scopes. It requires the user to login to their Spotify account in a browser/web view and approve your app. Read more at the Spotify web API reference.
-
Authorization Code Flow: Use this method if you need to access/modify user data, which requires authorization scopes. It requires the user to login to their Spotify account in a browser/web view and approve your app. Read more at the Spotify web API reference.
-
Client Credentials Flow: Use this method if you do NOT need to access/modify user data. In other words, you cannot access endpoints that require authorization scopes or an access token that was issued on behalf of a user. The advantage of this method is that it does not require any user interaction. Read more at the Spotify web API reference.
See also Additional Authorization Methods.
When creating an application that uses this library, you will probably want to save the authorization information to persistent storage so that the user does not have to login again every time the application is quit and re-launched. See Saving Authorization Information to Persistent Storage for a guide on how to do this.
Authorizing with the Authorization Code Flow with Proof Key for Code Exchange
Create an instance of SpotifyAPI
and assign an instance of AuthorizationCodeFlowPKCEManager
to the authorizationManager
property:
import SpotifyWebAPI
let spotify = SpotifyAPI(
authorizationManager: AuthorizationCodeFlowPKCEManager(
clientId: "Your Client Id"
)
)
Before each authentication request your app should generate a code verifier and a code challenge. The code verifier is a cryptographically random string between 43 and 128 characters in length. It can contain letters, digits, underscores, periods, hyphens, and tildes.
In order to generate the code challenge, your app should hash the code verifier using the SHA256 algorithm. Then, base64url encode the hash that you generated. Do not include any =
padding characters (percent-encoded or not).
You can use String.randomURLSafe(length:using:)
or String.randomURLSafe(length:)
to generate the code verifier. You can use the String.makeCodeChallenge(codeVerifier:)
instance method to create the code challenge from the code verifier.
For example:
let codeVerifier = String.randomURLSafe(length: 128)
let codeChallenge = String.makeCodeChallenge(codeVerifier: codeVerifier)
// optional, but strongly recommended
let state = String.randomURLSafe(length: 128)
If you use your own method to create these values, you can validate them using this PKCE generator tool. See also Data.base64URLEncodedString()
and String.urlSafeCharacters
.
Next, create the authorization URL that will be opened in a browser (or web view). When opened, it displays a permissions dialog to the user. The user can then choose to either authorize or deny authorization for your application.
let authorizationURL = spotify.authorizationManager.makeAuthorizationURL(
redirectURI: URL(string: "Your Redirect URI")!,
codeChallenge: codeChallenge,
state: state,
scopes: [
.playlistModifyPrivate,
.userModifyPlaybackState,
.playlistReadCollaborative,
.userReadPlaybackPosition
]
)!
See the full documentation for makeAuthorizationURL(redirectURI:showDialog:codeChallenge:state:scopes:).
The redirect URI needs to have been entered in the Redirect URI whitelist that you specified when you registered your application using the Spotify Developer Dashboard. DO NOT add a forward-slash to the end of the redirect URI.
The documentation for each endpoint lists the authorization scopes that are required. You can always authorize your application again for different scopes, if necessary. However, this is not an additive process. You must specify all the scopes that you need each time you create the authorization URL.
You can decide how to open the URL. If you are creating an iOS app, the simplest method is to use UIApplication.shared.open(authorizationURL)
to open the URL in the browser.
After the user either approves or denies authorization for your app, Spotify will redirect to the redirect URI that you specified when making the authorization URL with query parameters appended to it. Pass this URL into requestAccessAndRefreshTokens(redirectURIWithQuery:codeVerifier:state:) to request the access and refresh tokens:
spotify.authorizationManager.requestAccessAndRefreshTokens(
redirectURIWithQuery: url,
// Must match the code verifier that was used to generate the
// code challenge when creating the authorization URL.
codeVerifier: codeVerifier,
// Must match the value used when creating the authorization URL.
state: state
)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("successfully authorized")
case .failure(let error):
if let authError = error as? SpotifyAuthorizationError, authError.accessWasDenied {
print("The user denied the authorization request")
}
else {
print("couldn't authorize application: \(error)")
}
}
})
.store(in: &cancellables)
Once this publisher completes successfully, your application is authorized and you may begin making requests to the Spotify web API. Ensure that you generate a new value for the state parameter, code verifier, and code challenge before making another authorization request. The access token will be refreshed automatically when necessary. For example:
import SpotifyExampleContent
let playbackRequest = PlaybackRequest(
context: .uris(
URIs.Tracks.array(.faces, .illWind, .fearless)
),
offset: .uri(URIs.Tracks.fearless),
positionMS: 50_000
)
spotify.play(playbackRequest)
.sink(receiveCompletion: { completion in
print(completion)
})
.store(in: &cancellables)
The full documentation for all of the endpoints can be found here. You are also encouraged to read the Spotify web API reference.
Authorizing with the Authorization Code Flow
Create an instance of SpotifyAPI
and assign an instance of AuthorizationCodeFlowManager
to the authorizationManager
property:
import SpotifyWebAPI
let spotify = SpotifyAPI(
authorizationManager: AuthorizationCodeFlowManager(
clientId: "Your Client Id", clientSecret: "Your Client Secret"
)
)
Next, create the authorization URL that will be opened in a browser (or web view). When opened, it displays a permissions dialog to the user. The user can then choose to either authorize or deny authorization for your application.
let authorizationURL = spotify.authorizationManager.makeAuthorizationURL(
redirectURI: URL(string: "Your Redirect URI")!,
showDialog: false,
scopes: [
.playlistModifyPrivate,
.userModifyPlaybackState,
.playlistReadCollaborative,
.userReadPlaybackPosition
]
)!
See the full documentation for makeAuthorizationURL(redirectURI:showDialog:state:scopes:).
The redirect URI needs to have been entered in the Redirect URI whitelist that you specified when you registered your application using the Spotify Developer Dashboard. DO NOT add a forward-slash to the end of the redirect URI.
The documentation for each endpoint lists the authorization scopes that are required. You can always authorize your application again for different scopes, if necessary. However, this is not an additive process. You must specify all the scopes that you need each time you create the authorization URL.
You can decide how to open the URL. If you are creating an iOS app, the simplest method is to use UIApplication.shared.open(authorizationURL)
to open the URL in the browser.
After the user either approves or denies authorization for your app, Spotify will redirect to the redirect URI that you specified when making the authorization URL with query parameters appended to it. Pass this url into requestAccessAndRefreshTokens(redirectURIWithQuery:state:) to request the access and refresh tokens:
spotify.authorizationManager.requestAccessAndRefreshTokens(
redirectURIWithQuery: url
)
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("successfully authorized")
case .failure(let error):
if let authError = error as? SpotifyAuthorizationError, authError.accessWasDenied {
print("The user denied the authorization request")
}
else {
print("couldn't authorize application: \(error)")
}
}
})
.store(in: &cancellables)
Once this publisher completes successfully, your application is authorized and you may begin making requests to the Spotify web API. Ensure that you generate a new value for the state parameter before making another authorization request. The access token will be refreshed automatically when necessary. For example:
spotify.currentUserPlaylists()
.extendPages(spotify)
.sink(
receiveCompletion: { completion in
print(completion)
},
receiveValue: { results in
print(results)
}
)
.store(in: &cancellables)
This authorization process is fully implemented in this example app. The full documentation for all of the endpoints can be found here. You are also encouraged to read the Spotify web API reference.
Authorizing with the Client Credentials Flow
Create an instance of SpotifyAPI
and assign an instance of ClientCredentialsFlowManager
to the authorizationManager
property:
import SpotifyWebAPI
let spotify = SpotifyAPI(
authorizationManager: ClientCredentialsFlowManager(
clientId: "Your Client Id", clientSecret: "Your Client Secret"
)
)
To authorize your application, call authorize()
:
spotify.authorizationManager.authorize()
.sink(receiveCompletion: { completion in
switch completion {
case .finished:
print("successfully authorized application")
case .failure(let error):
print("could not authorize application: \(error)")
}
})
.store(in: &cancellables)
See the full documentation for authorize.
Once this publisher completes successfully, your application is authorized and you may begin making requests to the Spotify web API. The access token will be refreshed automatically when necessary. For example:
spotify.search(query: "Pink Floyd", categories: [.track])
.sink(
receiveCompletion: { completion in
print(completion)
},
receiveValue: { results in
print(results)
}
)
.store(in: &cancellables)
This authorization process is implemented in this example command-line app. The full documentation for all of the endpoints can be found here. You are also encouraged to read the Spotify web API reference.