{"id":13314769,"url":"https://github.com/adamint/spotify-web-api-kotlin","last_synced_at":"2025-04-06T07:11:39.545Z","repository":{"id":31058810,"uuid":"104819774","full_name":"adamint/spotify-web-api-kotlin","owner":"adamint","description":"Spotify Web API wrapper for Kotlin, Java, JS, and Native - Targets JVM, Android, JS (browser), Native (Desktop), and Apple tvOS/iOS. Includes a Spotify Web Playback SDK wrapper for Kotlin/JS, and a spotify-auth wrapper for Kotlin/Android.","archived":false,"fork":false,"pushed_at":"2024-04-30T03:39:05.000Z","size":7299,"stargazers_count":203,"open_issues_count":11,"forks_count":23,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-30T05:08:09.167Z","etag":null,"topics":["android","android-library","api","java","javascript","jvm","kotlin","kotlin-multiplatform","nodejs","pkce-authentication","spotify","spotify-api","spotify-broadcast-notifications","spotify-web-api","web-playback-sdk","wrapper"],"latest_commit_sha":null,"homepage":"https://adamint.github.io/spotify-web-api-kotlin-docs/","language":"Kotlin","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/adamint.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":"adamint","patreon":null,"open_collective":null,"ko_fi":"adamratzman","tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2017-09-26T01:22:07.000Z","updated_at":"2025-03-24T10:19:10.000Z","dependencies_parsed_at":"2024-04-27T20:25:05.118Z","dependency_job_id":"2edbd69c-e02a-421e-ae18-9924b0f031b1","html_url":"https://github.com/adamint/spotify-web-api-kotlin","commit_stats":null,"previous_names":[],"tags_count":34,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamint%2Fspotify-web-api-kotlin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamint%2Fspotify-web-api-kotlin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamint%2Fspotify-web-api-kotlin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/adamint%2Fspotify-web-api-kotlin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/adamint","download_url":"https://codeload.github.com/adamint/spotify-web-api-kotlin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247445670,"owners_count":20939958,"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":["android","android-library","api","java","javascript","jvm","kotlin","kotlin-multiplatform","nodejs","pkce-authentication","spotify","spotify-api","spotify-broadcast-notifications","spotify-web-api","web-playback-sdk","wrapper"],"created_at":"2024-07-29T18:12:08.589Z","updated_at":"2025-04-06T07:11:39.523Z","avatar_url":"https://github.com/adamint.png","language":"Kotlin","funding_links":["https://github.com/sponsors/adamint","https://ko-fi.com/adamratzman"],"categories":[],"sub_categories":[],"readme":"# Kotlin Spotify Web API \nA [Kotlin](https://kotlinlang.org/) implementation of the [Spotify Web API](https://developer.spotify.com/web-api/),\nsupporting Kotlin/JS, Kotlin/Android, Kotlin/JVM, and Kotlin/Native\n(macOS, Windows, Linux).\n\nThis library has first-class support for Java and is a viable alternative for Java development. \nPlease see [the Java section](#java) for more details.\n\n**Use this library in Kotlin, Java, JavaScript, Swift, or native code!** Because this library targets both iOS and Android, it can also be used in KMM ([Kotlin Multiplatform Mobile](https://kotlinlang.org/lp/mobile/)) applications as a shared source.\n\n[![Maven CEntral](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core)\n[![](https://img.shields.io/badge/Documentation-latest-orange.svg)](https://adamint.github.io/spotify-web-api-kotlin-docs/)\n![](https://img.shields.io/badge/License-MIT-blue.svg)\n[![codebeat badge](https://codebeat.co/badges/0ab613b0-31d7-4848-aebc-4ed1e51f069c)](https://codebeat.co/projects/github-com-adamint-spotify-web-api-kotlin-master)\n\n## Table of Contents\n* [Oerview and how to install](#overview-and-how-to-install)\n    + [JVM, Android, JS, Native](#jvm-android-js-native-apple)\n    + [Android information](#android)\n      * [Android sample app](#android-sample-application)\n* [Documentation](#documentation)\n* [Need help, have a question, or want to contribute?](#have-a-question)\n* [Creating a new api instance](#creating-a-new-api-instance)\n    + [SpotifyAppApi](#spotifyappapi)\n    + [SpotifyClientApi](#spotifyclientapi)\n        * [PKCE](#pkce)\n        * [Non-PKCE](#non-pkce-backend-applications-requires-client-secret)\n    + [SpotifyImplicitGrantApi](#spotifyimplicitgrantapi)\n    + [SpotifyApiBuilder block \u0026 setting API options](#spotifyapibuilder-block--setting-api-options)\n        * [API options](#api-options)\n    + [Using the API](#using-the-api)\n* [Platform-specific wrappers and information](#platform-specific-wrappers-and-information)\n    + [Java](#java)\n    + [Android authentication](#android-authentication)\n    + [JavaScript: Spotify Web Playback SDK wrapper](#js-spotify-web-playback-sdk-wrapper)\n* [Tips](#tips)\n    + [Building the API](#building-the-api)\n* [Notes](#notes)\n    + [LinkedResults, PagingObjects, and Cursor-based Paging Objects](#the-benefits-of-linkedresults-pagingobjects-and-cursor-based-paging-objects)\n    + [Generic Requests](#generic-request)\n    + [Track Relinking](#track-relinking)\n* [Contributing](#contributing)\n\n## Overview and how to install\nCurrent version:\n\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.adamratzman/spotify-api-kotlin-core)\n\n### JVM, Android, JS, Native, Apple\n```\nrepositories {\n    mavenCentral()\n}\n\nimplementation(\"com.adamratzman:spotify-api-kotlin-core:VERSION\")\n```\n\n\n### JS\nPlease see the [JS Spotify Web Playback SDK wrapper](#js-spotify-web-playback-sdk-wrapper) to learn how to use Spotify's web playback SDK in a browser application.\n\n### Android\n**Note**: For information on how to integrate implicit/PKCE authentication, Spotify app remote, and Spotify broadcast notifications into \nyour application, please see the [Android README](README_ANDROID.md).\n\n\n*If you declare any release types not named debug or release, you may see \"Could not resolve com.adamratzman:spotify-api-kotlin-android:VERSION\". You need to do the following for each release type not named debug or release:*\n```\nandroid {\n    buildTypes {\n        yourReleaseType1 {\n            // ...\n            matchingFallbacks = ['release', 'debug'] \n        }\n        yourReleaseType2 {\n            // ...\n            matchingFallbacks = ['release', 'debug'] \n        }\n\t...\n    }\n}\n```\n\n\nTo successfully build, you might need to exclude kotlin_module files from the packaging. To do this, inside the android/buildTypes/release closure, you would put:\n```\npackagingOptions {\n\texclude 'META-INF/*.kotlin_module'\n}\n```\n\n#### Android sample application\nYou can find a simple sample application demonstrating how to use spotify-web-api-kotlin in a modern Android app, as well as how to integrate with the Spotify app, [here](https://github.com/Nielssg/Spotify-Api-Test-App).\n\n## Documentation\nThe `spotify-web-api-kotlin` JavaDocs are hosted [here](https://adamint.github.io/spotify-web-api-kotlin-docs/).\n\n## Have a question?\nIf you have a question, you can:\n\n1. Create an [issue](https://github.com/adamint/spotify-web-api-kotlin/issues)\n2. Join our [Discord server](https://discord.gg/G6vqP3S)\n3. Contact me using **Adam#9261** on [Discord](https://discordapp.com)\n\n## Unsupported features on each platform:\n| Feature                     | JVM                | Android            | JS                 | Native (Mac/Windows/Linux) |\n|-----------------------------|--------------------|--------------------|--------------------|----------------------------|\n| Edit client playlist        | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | Unsupported                |\n| Remove playlist tracks      | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | Unsupported                |\n\nPlease feel free to open an issue/discussion on GitHub or Discord if you need access to one of these features \nor have an interest in implementing one, as direction can be provided.\n\n## Creating a new api instance\nTo decide which api you need (SpotifyAppApi, SpotifyClientApi, SpotifyImplicitGrantApi), you can refer \nto the sections below or the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/). In general:\n- If you don't need client resources, use SpotifyAppApi\n- If you're using the api in a backend application, use SpotifyClientApi (with or without PKCE)\n- If you're using the api in Kotlin/JS browser, use SpotifyImplicitGrantApi\n- If you need access to client resources in an Android or other application, use SpotifyClientApi with PKCE\n\n**Note**: You can use the online [Spotify OAuth Token Generator](https://adamratzman.com/projects/spotify/generate-token) tool to generate a client token for local testing.\n\n### SpotifyAppApi\nThis provides access only to public Spotify endpoints.\nUse this when you have a server-side application. Note that implicit grant authorization \nprovides a higher api ratelimit, so consider using implicit grant if your application has \nsignificant usage.\n\nBy default, the SpotifyApi `Token` automatically regenerates when needed. \nThis can be changed by overriding the `automaticRefresh` builder setting.\n\nThere are four exposed builders, depending on the level of control you need over api creation. \nPlease see the [spotifyAppApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/-spotify-app-api/index.html) for a full list of available builders.\n\nYou will need:\n- Spotify application client id\n- Spotify application client secret\n\nExample creation (default settings)\n\n```kotlin\nval api = spotifyAppApi(\"clientId\", \"clientSecret\").build() // create and build api\nprintln(api.browse.getNewReleases()) // use it\n```\n\nExample creation, using an existing Token and setting automatic token refresh to false\n```kotlin\nval token = spotifyAppApi(spotifyClientId, spotifyClientSecret).build().token\nval api = spotifyAppApi(\n  \"clientId\",\n  \"clientSecret\",\n  token\n) { \n  automaticRefresh = false \n}.build()\n\nprintln(api.browse.getNewReleases()) // use it\n```\n\n### SpotifyClientApi\nThe `SpotifyClientApi` is a superset of `SpotifyApi`; thus, nothing changes if you want to \naccess public data.\nThis library does not provide a method to retrieve the code from your  callback url; instead,\nyou must implement that with a web server. \nAutomatic Token refresh is available *only* when building with an authorization code or a \n`Token` object. Otherwise, it will expire `Token.expiresIn` seconds after creation.\n\nMake sure your application has requested the proper [Scopes](https://developer.spotify.com/web-api/using-spotifyScopes/) in order to \nensure proper function of this library. The api option `requiredScopes` allows you to verify \nthat a client has actually authorized with the scopes you are expecting.\n\nYou will need:\n- Spotify application client id\n- Spotify application client secret (if not using PKCE)\n- Spotify application redirect uri\n- To choose which client authorization method (PKCE or non-PKCE) to use\n\n#### PKCE\nUse the PKCE builders and helper methods if you are using the Spotify client authorization PKCE flow.\nBuilding via PKCE returns a `SpotifyClientApi` which has modified refresh logic.\n\nUse cases:\n1. You are using this library in an application (likely Android), or do not want to expose the client secret.\n\nTo learn more about the PKCE flow, please read the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow).\nSome highlights about the flow are:\n- It is refreshable, but each refresh token can only be used once. This library handles token refresh automatically by default\n- It does not require a client secret; instead, a set redirect uri and a random code verifier \nare used to verify the authenticity of the authorization.\n- A code verifier is required. The code verifier is \"*a cryptographically random string between 43 and 128 characters in length. \nIt can contain letters, digits, underscores, periods, hyphens, or tildes.*\"\n- A code challenge is required. \"*In order to generate the code challenge, your app should \nhash the code verifier using the SHA256 algorithm. Then, base64url encode the hash that you generated.*\"\n- When creating a pkce api instance, the code verifier is passed in by you and compared to \nthe code challenge used to authorize the user.\n\nThis library contains helpful methods that can be used to simplify the PKCE authorization process.\nThis includes `getSpotifyPkceCodeChallenge`, which SHA256 hashes and base64url encodes the code \nchallenge, and `getSpotifyPkceAuthorizationUrl`, which allows you to generate an easy authorization url for PKCE flow.\n\nPlease see the [spotifyClientPkceApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-client-pkce-api.html) for a full list of available builders.\n \n**Takeaway**: Use PKCE authorization flow in applications where you cannot secure the client secret.\n\nTo get a PKCE authorization url, to which you can redirect a user, you can use the `getSpotifyPkceAuthorizationUrl`\ntop-level method. An example is shown below, requesting 4 different scopes.\n```kotlin\nval codeVerifier = \"thisisaveryrandomalphanumericcodeverifierandisgreaterthan43characters\"\nval codeChallenge = getSpotifyPkceCodeChallenge(codeVerifier) // helper method\nval url: String = getSpotifyPkceAuthorizationUrl(\n    SpotifyScope.PLAYLIST_READ_PRIVATE,\n    SpotifyScope.PLAYLIST_MODIFY_PRIVATE,\n    SpotifyScope.USER_FOLLOW_READ,\n    SpotifyScope.USER_LIBRARY_MODIFY,\n    clientId = \"clientId\",\n    redirectUri = \"your-redirect-uri\",\n    codeChallenge = codeChallenge\n)\n```\n\nThere is also an optional parameter `state`, which helps you verify the authorization.\n\n**Note**: If you want automatic token refresh, you need to pass in your application client id and redirect uri \nwhen using the `spotifyClientPkceApi`.\n\n##### Example: A user has authorized your application. You now have the authorization code obtained after the user was redirected back to your application. You want to create a new `SpotifyClientApi`.\n```kotlin\nval codeVerifier = \"thisisaveryrandomalphanumericcodeverifierandisgreaterthan43characters\"\nval code: String = ...\nval api = spotifyClientPkceApi(\n    \"clientId\", // optional. include for token refresh\n    \"your-redirect-uri\", // optional. include for token refresh\n    code,\n    codeVerifier // the same code verifier you used to generate the code challenge\n) {\n  retryWhenRateLimited = false\n}.build()\n\nprintln(api.library.getSavedTracks().take(10).filterNotNull().map { it.track.name })\n```\n\n#### Non-PKCE (backend applications, requires client secret)\nTo get a non-PKCE authorization url, to which you can redirect a user, you can use the `getSpotifyAuthorizationUrl`\ntop-level method. An example is shown below, requesting 4 different scopes.\n```kotlin\nval url: String = getSpotifyAuthorizationUrl(\n    SpotifyScope.PLAYLIST_READ_PRIVATE,\n    SpotifyScope.PLAYLIST_MODIFY_PRIVATE,\n    SpotifyScope.USER_FOLLOW_READ,\n    SpotifyScope.USER_LIBRARY_MODIFY,\n    clientId = \"clientId\",\n    redirectUri = \"your-redirect-uri\",\n    state = \"your-special-state\" // optional\n)\n```\nThere are also several optional parameters, allowing you to set whether the authorization url is meant \nfor implicit grant flow, the state, and whether a re-authorization dialog should be shown to users.\n\nThere are several exposed builders, depending on the level of control you need over api creation. \nPlease see the [spotifyClientApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-client-api.html) for a full list of available builders.\n\n##### Example: You've redirected the user back to your web server and have an authorization code (code).\nIn this example, automatic token refresh is turned on by default.\n```kotlin\nval authCode = \"\"\nval api = spotifyClientApi(\n    \"clientId\",\n    \"clientSecret\",\n    \"your-redirect-uri\",\n    authCode\n).build() // create and build api\nprintln(api.personalization.getTopTracks(limit = 5).items.map { it.name }) // print user top tracks\n```\n\n##### Example: You've saved a user's token from previous authorization and need to create an api instance.\nIn this case, if you provide a client id to the builder, automatic token refresh will also be turned on.\n```kotlin\nval token: Token = ... // your existing token\nval api = spotifyClientApi(\n    \"clientId\",\n    \"clientSecret\",\n    \"your-redirect-uri\",\n    token\n) {\n  onTokenRefresh = {\n    println(\"Token refreshed at ${System.currentTimeMillis()}\")\n  }\n}.build()\nprintln(api.personalization.getTopTracks(limit = 5).items.map { it.name })\n```\n\n\n### SpotifyImplicitGrantApi\nUse the `SpotifyImplicitGrantApi` if you are using the Spotify implicit grant flow.\n`SpotifyImplicitGrantApi` is a superset of `SpotifyClientApi`.\nUnlike the other builders, the `spotifyImplicitGrantApi` builder method directly returns \na `SpotifyImplicitGrantApi` instead of an api builder.\n\nUse cases:\n1. You are using the **Kotlin/JS** target for this library.\n2. Your frontend Javascript passes the token received through the implicit grant flow to your \nbackend, where it is then used to create an api instance.\n\nTo learn more about the implicit grant flow, please read the [Spotify authorization guide](https://developer.spotify.com/documentation/general/guides/authorization-guide/#implicit-grant-flow).\nSome highlights about the flow are:\n- It is non-refreshable\n- It is client-side\n- It does not require a client secret\n\nPlease see the [spotifyImplicitGrantApi builder docs](https://adamint.github.io/spotify-web-api-kotlin-docs/spotify-web-api-kotlin/com.adamratzman.spotify/spotify-implicit-grant-api.html) for a full list of available builders.\n \nThe Kotlin/JS target contains the `parseSpotifyCallbackHashToToken` method, which will parse the hash \nfor the current url into a Token object, with which you can then instantiate the api.\n\n**Takeaway**: There are two ways to use implicit grant flow, browser-side only and browser and \nserver. This library provides easy access for both.\n\n##### Example\n```kotlin\nval token: Token = ...\nval api = spotifyImplicitGrantApi(\n    null,\n    null,\n    token\n) // create api. there is no need to build it \nprintln(api.personalization.getTopArtists(limit = 1)[0].name) // use it\n```\n\n### SpotifyApiBuilder Block \u0026 setting API options \nThere are three pluggable blocks in each api's corresponding builder\n\n1. `credentials` lets you set the client id, client secret, and redirect uri\n2. `authorization` lets you set the type of api authorization you are using. \nAcceptable types include: an authorization code, a `Token` object, a Token's access code string, and an optional refresh token string\n3. `options` lets you configure API options to your own specific needs\n\n#### API options\nThis library does not attempt to be prescriptivist. \nAll API options are located in `SpotifyApiOptions` and their default values can be overridden; however, use caution in doing so, as \nmost of the default values either allow for significant performance or feature enhancements to the API instance.\n\n- `useCache`: Set whether to cache requests. Default: true\n- `cacheLimit`: The maximum amount of cached requests allowed at one time. Null means no limit. Default: 200\n- `automaticRefresh`: Enable or disable automatic refresh of the Spotify access token when it expires. Default: true\n- `retryWhenRateLimited`: Set whether to block the current thread and wait until the API can retry the request. Default: true\n- `enableLogger`: Set whether to enable to the exception logger. Default: true\n- `testTokenValidity`: After API creation, test whether the token is valid by performing a lightweight request. Default: false\n- `defaultLimit`: The default amount of objects to retrieve in one request. Default: 50\n- `json`: The Json serializer/deserializer instance.\n- `allowBulkRequests`: Allow splitting too-large requests into smaller, allowable api requests. Default: true \n- `requestTimeoutMillis`: The maximum time, in milliseconds, before terminating an http request. Default: 100000ms\n- `refreshTokenProducer`: Provide if you want to use your own logic when refreshing a Spotify token.\n- `requiredScopes`: Scopes that your application requires to function (only applicable to `SpotifyClientApi` and `SpotifyImplicitGrantApi`).\nThis verifies that the token your user authorized with actually contains the scopes your \napplication needs to function.\n\nNotes:\n- Unless you have a good reason otherwise, `useCache` should be true\n- `cacheLimit` is per Endpoint, not per API. Don't be surprised if you end up with over 200 items in your cache with the default settings.\n- `automaticRefresh` is disabled when client secret is not provided, or if tokenString is provided in SpotifyClientApi\n- `allowBulkRequests` for example, lets you query 80 artists in one wrapper call by splitting it into 50 artists + 30 artists\n- `refreshTokenProducer` is useful when you want to re-authorize with the Spotify Auth SDK or elsewhere\n\n### Using the API\nAPIs available in all `SpotifyApi` instances, including `SpotifyClientApi` and `SpotifyImplicitGrantApi`:\n- `SearchApi` (searching items)\n- `AlbumApi` (get information about albums)\n- `BrowseApi` (browse new releases, featured playlists, categories, and recommendations)\n- `ArtistApi` (get information about artists)\n- `PlaylistApi` (get information about playlists)\n- `UserApi` (get public information about users on Spotify)\n- `TrackApi` (get information about tracks)\n- `FollowingApi` (check whether users follow playlists)\n\nAPIs available only in `SpotifyClientApi` and `SpotifyImplicitGrantApi` instances:\n- `ClientSearchApi` (all the methods in `SearchApi`, and searching shows and episodes)\n- `EpisodeApi` (get information about episodes)\n- `ShowApi` (get information about shows)\n- `ClientPlaylistApi` (all the methods in `PlaylistApi`, and get and manage user playlists)\n- `ClientProfileApi` (all the methods in `UserApi`, and get the user profile, depending on scopes)\n- `ClientFollowingApi` (all the methods in `FollowingApi`, and get and manage following of playlists, artists, and users)\n- `ClientPersonalizationApi` (get user top tracks and artists)\n- `ClientLibraryApi` (get and manage saved tracks and albums)\n- `ClientPlayerApi` (view and control Spotify playback)\n\n## Platform-specific wrappers and information\n\n### Java\nThis library has first-class support for Java! You have two choices when using this library: async-only with Kotlin\nsuspend functions (using SpotifyContinuation).\n\n\n#### Integrating with Kotlin suspend functions via Java `Continuation`s\nUnfortunately, coroutines don't play very nicely with Java code. Fortunately, however, we provide a wrapper around Kotlin's \n`Continuation` class that allows you to directly implement `onSuccess` and `onFailure` handlers on API methods.\n\nPlease see below for an example:\n\n```java\nimport com.adamratzman.spotify.SpotifyApiBuilderKt;\nimport com.adamratzman.spotify.SpotifyAppApi;\nimport com.adamratzman.spotify.javainterop.SpotifyContinuation;\nimport com.adamratzman.spotify.models.Album;\nimport org.jetbrains.annotations.NotNull;\n\nimport java.util.concurrent.ExecutionException;\n\npublic class SpotifyTestApp {\n    static SpotifyAppApi api;\n\n    public static void main(String[] args) throws ExecutionException, InterruptedException {\n        var id = \"spotify-client-id\";\n        var secret = \"spotify-client-secret\";\n        SpotifyApiBuilderKt.spotifyAppApi(id, secret).build(true, new SpotifyContinuation\u003c\u003e() {\n            @Override\n            public void onSuccess(SpotifyAppApi spotifyAppApi) {\n                api = spotifyAppApi;\n                runAlbumSearch();\n            }\n\n            @Override\n            public void onFailure(@NotNull Throwable throwable) {\n                throwable.printStackTrace();\n            }\n        });\n\n        Thread.sleep(1000000);\n    }\n\n    public static void runAlbumSearch() {\n        api.getAlbums().getAlbum(\"spotify:album:0b23AHutIA1BOW0u1dZ6wM\", null, new SpotifyContinuation\u003c\u003e() {\n            @Override\n            public void onSuccess(Album album) {\n                System.out.println(\"Album name is: \" + album.getName() + \". Exiting now..\");\n\n                System.exit(0);\n            }\n\n            @Override\n            public void onFailure(@NotNull Throwable throwable) {\n                throwable.printStackTrace();\n            }\n        });\n    }\n}\n```\n\n### Android authentication\nFor information on how to integrate implicit/PKCE authentication, Spotify app remote, and Spotify broadcast notifications into \nyour application, please see the [Android README](README_ANDROID.md).\n\n### JS Spotify Web Playback SDK wrapper\n`spotify-web-api-kotlin` provides a wrapper around Spotify's [Web Playback SDK](https://developer.spotify.com/documentation/web-playback-sdk/reference/) \nfor playing music via Spotify in the browser on your own site.\n\nTo do this, you need to create a `Player` instance and then use the associated methods to register listeners, play, \nand get current context.\n\nPlease see an example of how to do this [here](https://github.com/adamint/spotify-web-api-browser-example/blob/95df60810611ddb961a7a2cb0c874a76d4471aa7/src/main/kotlin/com/adamratzman/layouts/HomePageComponent.kt#L38). \nAn example project, [spotify-web-api-browser-example](https://github.com/adamint/spotify-web-api-browser-example), \ndemonstrates how to create a frontend JS Kotlin application with Spotify integration and \nthat will play music in the browser.\n\n**Notes**:\n1. You must include the Spotify player JS script by including `\u003cscript src=\"https://sdk.scdn.co/spotify-player.js\"\u003e\u003c/script\u003e`\n2. You must define a `window.onSpotifyWebPlaybackSDKReady` function immediately afterwards - this should load your main application bundle.\n    Otherwise, you will get errors. An example is below:\n   \n```html\n\u003chtml\u003e\n\u003chead\u003e\n    ...\n    \u003cscript src=\"https://code.jquery.com/jquery-3.5.1.min.js\" integrity=\"sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=\" crossorigin=\"anonymous\"\u003e\u003c/script\u003e\n\n    \u003cscript\u003e\n        jQuery.loadScript = function (url, callback) {\n            jQuery.ajax({\n                url: url,\n                dataType: 'script',\n                success: callback,\n                async: true\n            });\n        }\n    \u003c/script\u003e\n\n    \u003cscript src=\"https://sdk.scdn.co/spotify-player.js\"\u003e\u003c/script\u003e\n    \u003cscript\u003e\n        window.onSpotifyWebPlaybackSDKReady = () =\u003e {\n            $.loadScript(\"main.bundle.js\")\n        }\n    \u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n....\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n## Tips\n\n### Building the API\nThe easiest way to build the API is using .build() after a builder\n```kotlin\nrunBlocking {\n    val api = spotifyAppApi(clientId, clientSecret).build()\n}\n```\n\n## Notes\n### Re-authentication\nIf you are using an authorization flow or token that does not support automatic token refresh, `SpotifyException.ReAuthenticationNeededException` \nwill be thrown. You should put your requests, if creating an application, behind a try/catch block to re-authenticate users if this \nexception is thrown.\n\n### LinkedResults, PagingObjects, and Cursor-based Paging Objects\nSpotify provides these three object models in order to simplify our lives as developers. So let's see what we\ncan do with them!\n\n#### PagingObjects\nPagingObjects are a container for the requested objects (`items`), but also include \nimportant information useful in future calls. It contains the request's `limit` and `offset`, along with \n(sometimes) a link to the next and last page of items and the total number of items returned.\n\nIf a link to the next or previous page is provided, we can use the `getNext` and `getPrevious` methods to retrieve \nthe respective PagingObjects \n\n#### Cursor-Based Paging Objects\nA cursor-based paging object is a PagingObject with a cursor added on that can be used as a key to find the next \npage of items. The value in the cursor, `after`, describes after what object to begin the query.\n\nJust like with PagingObjects, you can get the next page of items with `getNext`. *However*, there is no \nprovided implementation of `after` in this library. You will need to do it yourself, if necessary.\n\n#### LinkedResults\nSome endpoints, like `PlaylistAPI.getPlaylistTracks`, return a LinkedResult, which is a simple wrapper around the \nlist of objects. With this, we have access to its Spotify API url (with `href`), and we provide simple methods to parse \nthat url.\n\n### Generic Request\nFor obvious reasons, in most cases, making asynchronous requests via `queue` or `queueAfter` is preferred. However, \nthe synchronous format is also shown.\n\n```kotlin\nval api = spotifyAppApi(\n        System.getenv(\"SPOTIFY_CLIENT_ID\"),\n        System.getenv(\"SPOTIFY_CLIENT_SECRET\")\n).build()\n\n// print out the names of the twenty most similar songs to the search\nprintln(api.search.searchTrack(\"Début de la Suite\").joinToString { it.name })\n\n// simple, right? what about if we want to print out the featured playlists message from the \"Overview\" tab?\nprintln(api.browse.getFeaturedPlaylists().message)\n\n// easy! let's try something a little harder\n// let's find out Bénabar's Spotify ID, find his top tracks, and print them out\nval benabarId = api.search.searchArtist(\"Bénabar\")[0].id\n// this works; a redundant way would be: api.artists.getArtist(\"spotify:artist:6xoAWsIOZxJVPpo7Qvqaqv\").id\nprintln(api.artists.getArtistTopTracks(benabarId).joinToString { it.name })\n```\n\n### Track Relinking\nSpotify keeps many instances of most tracks on their servers, available in different markets. As such, if we use endpoints \nthat return tracks, we do not know if these tracks are playable in our market. That's where track relinking comes in.\n\nTo relink in a specified market, we must supply a `market` parameter for endpoints where available. \nIn both Track and SimpleTrack objects in an endpoint response, there is a nullable field called `linked_from`. \nIf the track is unable to be played in the specified market and there is an alternative that *is* playable, this \nwill be populated with the href, uri, and, most importantly, the id of the track.\n\nYou can then use this track in `SpotifyClientApi` endpoints such as playing or saving the track, knowing that it will be playable \nin your market!\n\n## Contributing\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamint%2Fspotify-web-api-kotlin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fadamint%2Fspotify-web-api-kotlin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fadamint%2Fspotify-web-api-kotlin/lists"}