{"id":29374234,"url":"https://github.com/peter-schorn/spotifyapi","last_synced_at":"2025-07-09T20:02:25.662Z","repository":{"id":41109045,"uuid":"287608340","full_name":"Peter-Schorn/SpotifyAPI","owner":"Peter-Schorn","description":"A Swift library for the Spotify web API. Supports all endpoints.","archived":false,"fork":false,"pushed_at":"2025-05-08T20:12:00.000Z","size":73586,"stargazers_count":294,"open_issues_count":1,"forks_count":37,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-07-09T18:05:12.968Z","etag":null,"topics":["api","api-wrapper","combine","spotify","spotifyapi","swift","swiftui"],"latest_commit_sha":null,"homepage":"https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Peter-Schorn.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2020-08-14T19:22:23.000Z","updated_at":"2025-06-24T19:32:31.000Z","dependencies_parsed_at":"2025-05-08T21:36:14.597Z","dependency_job_id":null,"html_url":"https://github.com/Peter-Schorn/SpotifyAPI","commit_stats":{"total_commits":469,"total_committers":5,"mean_commits":93.8,"dds":0.01279317697228144,"last_synced_commit":"b665ed8b0bf85a4cff99d9001201ec66a098b269"},"previous_names":[],"tags_count":63,"template":false,"template_full_name":null,"purl":"pkg:github/Peter-Schorn/SpotifyAPI","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peter-Schorn%2FSpotifyAPI","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peter-Schorn%2FSpotifyAPI/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peter-Schorn%2FSpotifyAPI/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peter-Schorn%2FSpotifyAPI/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Peter-Schorn","download_url":"https://codeload.github.com/Peter-Schorn/SpotifyAPI/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Peter-Schorn%2FSpotifyAPI/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264502604,"owners_count":23618651,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","api-wrapper","combine","spotify","spotifyapi","swift","swiftui"],"created_at":"2025-07-09T20:01:03.623Z","updated_at":"2025-07-09T20:02:25.638Z","avatar_url":"https://github.com/Peter-Schorn.png","language":"Swift","readme":"# SpotifyAPI\n\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FPeter-Schorn%2FSpotifyAPI%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/Peter-Schorn/SpotifyAPI)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2FPeter-Schorn%2FSpotifyAPI%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/Peter-Schorn/SpotifyAPI)\n\n**A Swift library for the Spotify web API**\n\n### Features\n\n* Supports *all* of the [Spotify web API endpoints][24], including playing content, creating playlists, and retrieving albums.\n* Uses Apple's Combine framework, which makes chaining asynchronous requests a breeze\n* Supports three different authorization methods\n* Automatically refreshes the access token when necessary\n\nRead the full [documentation][1] and check out [this example iOS app][14] and this [example command-line app][23].\n\n### Sponsors\n\n* [bbauman1](https://github.com/bbauman1)\n\n## Table of Contents\n\n* **[Supported Platforms](#supported-platforms)**\n* **[Installation](#installation)**\n* **[Quick Start](#quick-start)**\n* **[Authorizing with the Authorization Code Flow with Proof Key for Code Exchange](#authorizing-with-the-authorization-code-flow-with-proof-key-for-code-exchange)**\n* **[Authorizing with the Authorization Code Flow](#authorizing-with-the-authorization-code-flow)**  \n* **[Authorizing with the Client Credentials Flow](#authorizing-with-the-client-credentials-flow)**\n* **[Saving Authorization Information to Persistent Storage][16]**\n* **[Using the Player Endpoints][26]**\n* **[Working with Paginated Results][27]**\n* **[Debugging][28]**\n* **[Running the Unit Tests][29]**\n\n## Supported Platforms\n\n* Swift 5.6+\n* iOS 13+\n* macOS 10.15+\n* tvOS 13+\n* watchOS 6+\n* Linux\n\n## Installation\n\n1. In Xcode, open the project that you want to add this package to.\n2. From the menu bar, select File \u003e Swift Packages \u003e Add Package Dependency...\n3. Paste the [URL](https://github.com/Peter-Schorn/SpotifyAPI.git) for this repository into the search field.\n5. Select the `SpotifyAPI` Library.\n4. Follow the prompts for adding the package.\n\n## Quick Start\n\nTo get started, go to the [Spotify Developer Dashboard][2] 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**.\n\nThe next step is authorizing your app. *All* requests to the Spotify web API—whether they require [authorization scopes][5] or not—require authorization This library supports three authorization methods:\n\n* **[Authorization Code Flow with Proof Key for Code Exchange](#authorizing-with-the-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][5]. 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][15].\n\n* **[Authorization Code Flow](#authorizing-with-the-authorization-code-flow)**: Use this method if you need to access/modify user data, which requires [authorization scopes][5]. 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][3].\n* **[Client Credentials Flow](#authorizing-with-the-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][5] 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][4].\n\nSee also [Additional Authorization Methods][25].\n\nWhen 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][16] for a guide on how to do this.\n\n## Authorizing with the Authorization Code Flow with Proof Key for Code Exchange\n\nCreate an instance of `SpotifyAPI` and assign an instance of `AuthorizationCodeFlowPKCEManager` to the `authorizationManager` property:\n```swift\nimport SpotifyWebAPI\n\nlet spotify = SpotifyAPI(\n    authorizationManager: AuthorizationCodeFlowPKCEManager(\n        clientId: \"Your Client Id\"\n    )\n)\n```\n\nBefore 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.\n\nIn order to generate the code challenge, your app should hash the code verifier using the SHA256 algorithm. Then, [base64url][19] encode the hash that you generated. **Do not include any** `=` **padding characters** (percent-encoded or not).\n\nYou 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. \n\nFor example:\n\n```swift\nlet codeVerifier = String.randomURLSafe(length: 128)\nlet codeChallenge = String.makeCodeChallenge(codeVerifier: codeVerifier)\n\n// optional, but strongly recommended\nlet state = String.randomURLSafe(length: 128)\n```\n\nIf you use your own method to create these values, you can validate them using this [PKCE generator tool][18]. See also `Data.base64URLEncodedString()` and `String.urlSafeCharacters`.\n\nNext, 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.\n\n```swift\nlet authorizationURL = spotify.authorizationManager.makeAuthorizationURL(\n    redirectURI: URL(string: \"Your Redirect URI\")!,\n    codeChallenge: codeChallenge,\n    state: state,\n    scopes: [\n        .playlistModifyPrivate,\n        .userModifyPlaybackState,\n        .playlistReadCollaborative,\n        .userReadPlaybackPosition\n    ]\n)!\n```\n\nSee the full documentation for [makeAuthorizationURL(redirectURI:showDialog:codeChallenge:state:scopes:)][20].\n\nThe 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][2]. **DO NOT add a forward-slash to the end of the redirect URI.**\n\nThe documentation for each endpoint lists the [authorization scopes][5] 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.\n\nYou 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.\n\nAfter 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:)][21] to request the access and refresh tokens:\n```swift\nspotify.authorizationManager.requestAccessAndRefreshTokens(\n    redirectURIWithQuery: url,\n    // Must match the code verifier that was used to generate the \n    // code challenge when creating the authorization URL.\n    codeVerifier: codeVerifier,\n    // Must match the value used when creating the authorization URL.\n    state: state\n)\n.sink(receiveCompletion: { completion in\n    switch completion {\n        case .finished:\n            print(\"successfully authorized\")\n        case .failure(let error):\n            if let authError = error as? SpotifyAuthorizationError, authError.accessWasDenied {\n                print(\"The user denied the authorization request\")\n            }\n            else {\n                print(\"couldn't authorize application: \\(error)\")\n            }\n    }\n})\n.store(in: \u0026cancellables)\n```\n\nOnce 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:\n```swift\nimport SpotifyExampleContent\n\nlet playbackRequest = PlaybackRequest(\n    context: .uris(\n        URIs.Tracks.array(.faces, .illWind, .fearless)\n    ),\n    offset: .uri(URIs.Tracks.fearless),\n    positionMS: 50_000\n)\n\nspotify.play(playbackRequest)\n    .sink(receiveCompletion: { completion in\n        print(completion)\n    })\n    .store(in: \u0026cancellables)\n```\n\nThe full documentation for all of the endpoints can be found [here][8]. You are also encouraged to read the [Spotify web API reference][12].\n\n## Authorizing with the Authorization Code Flow\n\nCreate an instance of `SpotifyAPI` and assign an instance of `AuthorizationCodeFlowManager` to the `authorizationManager` property:\n```swift\nimport SpotifyWebAPI\n\nlet spotify = SpotifyAPI(\n    authorizationManager: AuthorizationCodeFlowManager(\n        clientId: \"Your Client Id\", clientSecret: \"Your Client Secret\"\n    )\n)\n```\n\nNext, 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.\n```swift\nlet authorizationURL = spotify.authorizationManager.makeAuthorizationURL(\n    redirectURI: URL(string: \"Your Redirect URI\")!,\n    showDialog: false,\n    scopes: [\n        .playlistModifyPrivate,\n        .userModifyPlaybackState,\n        .playlistReadCollaborative,\n        .userReadPlaybackPosition\n    ]\n)!\n```\n\nSee the full documentation for [makeAuthorizationURL(redirectURI:showDialog:state:scopes:)][6].\n\nThe 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][2]. **DO NOT add a forward-slash to the end of the redirect URI.**\n\nThe documentation for each endpoint lists the [authorization scopes][5] 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.\n\nYou 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.\n\nAfter 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:)][7] to request the access and refresh tokens:\n```swift\nspotify.authorizationManager.requestAccessAndRefreshTokens(\n    redirectURIWithQuery: url\n)\n.sink(receiveCompletion: { completion in\n    switch completion {\n        case .finished:\n            print(\"successfully authorized\")\n        case .failure(let error):\n            if let authError = error as? SpotifyAuthorizationError, authError.accessWasDenied {\n                print(\"The user denied the authorization request\")\n            }\n            else {\n                print(\"couldn't authorize application: \\(error)\")\n            }\n    }\n})\n.store(in: \u0026cancellables)\n```\n\nOnce 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:\n\n```swift\nspotify.currentUserPlaylists()\n    .extendPages(spotify)\n    .sink(\n        receiveCompletion: { completion in\n            print(completion)\n        },\n        receiveValue: { results in\n            print(results)\n        }\n    )\n    .store(in: \u0026cancellables)\n```\n\nThis authorization process is fully implemented in this [example app][22]. The full documentation for all of the endpoints can be found [here][8]. You are also encouraged to read the [Spotify web API reference][12].\n\n## Authorizing with the Client Credentials Flow\n\nCreate an instance of `SpotifyAPI` and assign an instance of `ClientCredentialsFlowManager` to the `authorizationManager` property:\n```swift\nimport SpotifyWebAPI\n\nlet spotify = SpotifyAPI(\n    authorizationManager: ClientCredentialsFlowManager(\n        clientId: \"Your Client Id\", clientSecret: \"Your Client Secret\"\n    )\n)\n```\n\nTo authorize your application, call `authorize()`:\n```swift\nspotify.authorizationManager.authorize()\n    .sink(receiveCompletion: { completion in\n        switch completion {\n            case .finished:\n                print(\"successfully authorized application\")\n            case .failure(let error):\n                print(\"could not authorize application: \\(error)\")\n        }\n    })\n    .store(in: \u0026cancellables)\n```\n\nSee the full documentation for [authorize][13].\n\nOnce 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:\n```swift\nspotify.search(query: \"Pink Floyd\", categories: [.track])\n    .sink(\n        receiveCompletion: { completion in\n            print(completion)\n        },\n        receiveValue: { results in\n            print(results)\n        }\n    )\n    .store(in: \u0026cancellables)\n```\n\nThis authorization process is implemented in this [example command-line app][23]. The full documentation for all of the endpoints can be found [here][8]. You are also encouraged to read the [Spotify web API reference][12].\n\n[1]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi\n[2]: https://developer.spotify.com/dashboard/login\n\n[3]: https://developer.spotify.com/documentation/general/guides/authorization/code-flow/\n[4]: https://developer.spotify.com/documentation/general/guides/authorization/client-credentials/\n[5]: https://developer.spotify.com/documentation/general/guides/authorization/scopes/\n[6]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/authorizationcodeflowbackendmanager/makeauthorizationurl(redirecturi:showdialog:state:scopes:)\n[7]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/authorizationcodeflowbackendmanager/requestaccessandrefreshtokens(redirecturiwithquery:state:)\n\n[8]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/spotifyapi\n[12]: https://developer.spotify.com/documentation/web-api/reference/\n[13]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/clientcredentialsflowbackendmanager/authorize()\n[14]: https://github.com/Peter-Schorn/SpotifyAPIExampleApp\n[15]: https://developer.spotify.com/documentation/general/guides/authorization/code-flow/\n[16]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/saving-the-authorization-information-to-persistent-storage\n[17]: https://github.com/Peter-Schorn/SpotifyAPI/wiki\n[18]: https://tonyxu-io.github.io/pkce-generator/\n[19]: https://tools.ietf.org/html/rfc4648#section-5\n[20]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/authorizationcodeflowpkcebackendmanager/makeauthorizationurl(redirecturi:codechallenge:state:scopes:)\n[21]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/authorizationcodeflowpkcebackendmanager/requestaccessandrefreshtokens(redirecturiwithquery:codeverifier:state:)\n\n[22]: https://github.com/Peter-Schorn/SpotifyAPIExampleApp#how-the-authorization-process-works\n[23]: https://github.com/Peter-Schorn/SpotifyAPIExamples\n[24]: https://developer.spotify.com/documentation/web-api/reference/\n[25]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/additional-authorization-methods\n[26]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/using-the-player-endpoints\n[27]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/working-with-paginated-results\n[28]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/debugging\n[29]: https://peter-schorn.github.io/SpotifyAPI/documentation/spotifywebapi/running-the-unit-tests\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-schorn%2Fspotifyapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpeter-schorn%2Fspotifyapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpeter-schorn%2Fspotifyapi/lists"}