Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions .github/workflows/ci-client.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,30 @@ jobs:
environment: release
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: '17'
- name: Install curl
run: sudo apt-get install -y curl libcurl4-openssl-dev

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Make gradlew executable
run: chmod +x gradlew

- name: Verify Android
run: ./gradlew testDebugUnitTest

- name: Verify JVM/JS
run: ./gradlew jvmTest

- name: Archive test results
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
path: build/reports
if-no-files-found: warn
if: always()
44 changes: 25 additions & 19 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,28 @@ jobs:
SPOTIFY_CLIENT_ID: ${{ secrets.SPOTIFY_CLIENT_ID }}
SPOTIFY_CLIENT_SECRET: ${{ secrets.SPOTIFY_CLIENT_SECRET }}
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
- name: Install curl
run: sudo apt-get install -y curl libcurl4-openssl-dev
- name: Test android
run: ./gradlew testDebugUnitTest
- name: Test jvm
run: ./gradlew jvmTest
- name: Archive test results
uses: actions/upload-artifact@v2
if: always()
with:
name: code-coverage-report
path: build/reports
- name: Check out repo
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Test android
run: ./gradlew testDebugUnitTest

- name: Test jvm
run: ./gradlew jvmTest

- name: Archive test results
uses: actions/upload-artifact@v4
if: always()
with:
name: code-coverage-report
path: build/reports
if-no-files-found: warn
85 changes: 62 additions & 23 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,68 +28,107 @@ jobs:
environment: release
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: '17'
- name: Install curl
run: sudo apt-get install -y curl libcurl4-openssl-dev

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Make gradlew executable
run: chmod +x gradlew

- name: Verify Android
run: ./gradlew testDebugUnitTest

- name: Verify JVM/JS
run: ./gradlew jvmTest

- name: Publish JVM/Linux/Android
run: ./gradlew publishKotlinMultiplatformPublicationToNexusRepository publishJvmPublicationToNexusRepository publishAndroidPublicationToNexusRepository publishLinuxX64PublicationToNexusRepository publishJsPublicationToNexusRepository

- name: Archive test results
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v4
with:
name: code-coverage-report
name: code-coverage-report-linux
path: build/reports
if-no-files-found: warn
if: always()

release_mac:
runs-on: macos-latest
environment: release
needs: release_android_jvm_linux_js
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Make gradlew executable
run: chmod +x gradlew

- name: Publish macOS/iOS
run: ./gradlew publishMacosX64PublicationToNexusRepository publishIosX64PublicationToNexusRepository publishIosArm64PublicationToNexusRepository

release_windows:
runs-on: windows-latest
environment: release
needs: release_android_jvm_linux_js
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: '17'
- run: choco install curl

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Fix gradlew permissions
run: git update-index --chmod=+x gradlew
shell: bash

- name: Publish windows
run: ./gradlew publishMingwX64PublicationToNexusRepository
shell: bash

release_docs:
runs-on: ubuntu-latest
environment: release
steps:
- name: Check out repo
uses: actions/checkout@v2
- name: Install java 11
uses: actions/setup-java@v2
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: 'adopt'
distribution: 'temurin'
java-version: '17'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@v3

- name: Make gradlew executable
run: chmod +x gradlew

- name: Build docs
run: ./gradlew dokkaHtml

- name: Push docs to docs repo
uses: cpina/github-action-push-to-another-repository@main
env:
Expand All @@ -98,5 +137,5 @@ jobs:
source-directory: 'docs'
destination-github-username: 'adamint'
destination-repository-name: 'spotify-web-api-kotlin-docs'
user-email: adam@adamratzman.com
target-branch: main
user-email: 'adam@adamratzman.com'
target-branch: 'main'
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ to the sections below or the [Spotify authorization guide](https://developer.spo

**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.

**Important**: As of March 2026, to use any API endpoints, you must have a Spotify Premium subscription, unless you are in extended quota mode.

### SpotifyAppApi
This provides access only to public Spotify endpoints.
Use this when you have a server-side application. Note that implicit grant authorization
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,8 @@ kotlin {
}

val commonJvmLikeTest by creating {
dependsOn(commonTest.get())

dependencies {
implementation(kotlin("test-junit"))
implementation("com.sparkjava:spark-core:$sparkVersion")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,7 @@ public open class SpotifyClientApi(
* An API instance created through implicit grant flow, with access to private information
* managed through the scopes exposed in [token]. [token] is not refreshable and is only accessible for limited time.
*/
@Deprecated("Removed")
public class SpotifyImplicitGrantApi(
clientId: String?,
token: Token,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import kotlinx.serialization.json.Json
* @param scopes Spotify scopes the api instance should be able to access for the user
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
* @param redirectUri Spotify [redirect uri](https://developer.spotify.com/documentation/general/guides/app-settings/)
* @param isImplicitGrantFlow Whether the authorization url should be for the Implicit Grant flow, otherwise for Authorization Code flo
* @param isImplicitGrantFlow Whether the authorization url should be for the Implicit Grant flow, otherwise for Authorization Code flow (Deprecated)
* @param shouldShowDialog If [isImplicitGrantFlow] is true, whether or not to force the user to approve the app again if they’ve already done so.
* @param state This provides protection against attacks such as cross-site request forgery.
*/
Expand Down Expand Up @@ -107,11 +107,14 @@ public fun getSpotifyPkceCodeChallenge(codeVerifier: String): String {
*
* Use case: I have a token obtained after implicit grant authorization.
*
* * **Deprecated**. Read how to migrate [here](https://developer.spotify.com/documentation/web-api/tutorials/migration-implicit-auth-code).
*
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
* @param token Token created from the hash response in the implicit grant callback
*
* @return [SpotifyImplicitGrantApi] that can immediately begin making calls
*/
@Deprecated("Removed")
public fun spotifyImplicitGrantApi(
clientId: String?,
token: Token
Expand All @@ -127,12 +130,15 @@ public fun spotifyImplicitGrantApi(
*
* Use case: I have a token obtained after implicit grant authorization.
*
* **Deprecated**. Read how to migrate [here](https://developer.spotify.com/documentation/web-api/tutorials/migration-implicit-auth-code).
*
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
* @param token Token created from the hash response in the implicit grant callback
* @param block Block to set API options
*
* @return [SpotifyImplicitGrantApi] that can immediately begin making calls
*/
@Deprecated("Removed")
public fun spotifyImplicitGrantApi(
clientId: String?,
token: Token,
Expand Down Expand Up @@ -1134,7 +1140,7 @@ public class SpotifyUserAuthorization(
* @param requestTimeoutMillis The maximum time, in milliseconds, before terminating an http request
* @param refreshTokenProducer Provide if you want to use your own logic when refreshing a Spotify token
* @param onTokenRefresh Provide if you want to act on token refresh event
* @param requiredScopes Scopes that your application requires to function (only applicable to [SpotifyClientApi] and [SpotifyImplicitGrantApi]).
* @param requiredScopes Scopes that your application requires to function (only applicable to [SpotifyClientApi]).
* @param proxyBaseUrl Provide if you have a proxy base URL that you would like to use instead of the Spotify API base
* (https://api.spotify.com/v1).
* @param retryOnInternalServerErrorTimes Whether and how often to retry once if an internal server error (500..599) has been received. Set to 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.adamratzman.spotify.annotations

/**
* The underlying endpoint or field is only available in Extended Quota Mode after March 9, 2026.
* It is **not available** in development mode!
*/
@RequiresOptIn(
level = RequiresOptIn.Level.WARNING,
message = "Requires Extended Quota Mode after March 9, 2026"
)
@Retention(AnnotationRetention.BINARY)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
public annotation class SpotifyExtendedQuota
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package com.adamratzman.spotify.endpoints.client
import com.adamratzman.spotify.GenericSpotifyApi
import com.adamratzman.spotify.SpotifyException.BadRequestException
import com.adamratzman.spotify.SpotifyScope
import com.adamratzman.spotify.annotations.SpotifyExtendedQuota
import com.adamratzman.spotify.endpoints.pub.EpisodeApi
import com.adamratzman.spotify.models.Episode
import com.adamratzman.spotify.models.EpisodeList
Expand Down Expand Up @@ -54,6 +55,7 @@ public class ClientEpisodeApi(api: GenericSpotifyApi) : EpisodeApi(api) {
* @return List of possibly-null [Episode] objects.
* @throws BadRequestException If any invalid show id is provided
*/
@SpotifyExtendedQuota
public suspend fun getEpisodes(vararg ids: String): List<Episode?> {
requireScopes(SpotifyScope.UserReadPlaybackPosition)
checkBulkRequesting(50, ids.size)
Expand Down
Loading
Loading