🎧 Unofficial Deezer Client KMP



A Kotlin Multiplatform client for Deezer’s official REST API.
Using Ktor Client.
Supports Android (min SDK 24 / JVM 8+), JVM Java, Kotlin/JVM, Kotlin/JS, Kotlin/WasmJs.
[!TIP]
It's recommended to configure Content Encoding
to reduce the size of the response.
If you consume a lot of images, consider using Caching
🛠️ Instalación
- Android minSdk Version 24
- JVM target Java 8+ / Kotlin JVM 1.8

Gradle
implementation("io.github.kingg22:deezer-client-kt:<latest-version>")
Maven
<dependency>
<groupId>io.github.kingg22</groupId>
<artifactId>deezer-client-kt-jvm</artifactId>
<version>current-version</version>
</dependency>
Install a Ktor client engine, see detail.

Example with CIO (Coroutines based):
Gradle
implementation("io.ktor:ktor-client-cio:$ktor_version")
Maven
<dependency>
<groupId>io.ktor</groupId>
<artifactId>ktor-client-cio-jvm</artifactId>
<version>${ktor_version}</version>
</dependency>
🧪 Usage
val httpClient = HttpClient {
install(DeezerClientPlugin)
}
val client = DeezerApiClient(httpClient)
val artist: Artist = client.artists.getById(27)
println("Artist: ${artist.name}")
- ✅ Java (CompletableFuture)
Paginated Response
Kotlin
val client: DeezerApiClient
val result: PaginatedResponse<Track> = client.searches.search("eminem")
checkNotNull(result.next)
val nextPage: PaginatedResponse<Track> = checkNotNull(tested.fetchNext(client, expand=true))
Java
import java.util.concurrent.CompletableFuture;
public class Test {
{
DeezerApiJavaClient client;
PaginatedResponse<Track> response = client.searches.search();
PaginatedResponse<Track> nextPage = response.fetchNext(client, Track.class, );
CompletableFuture<PaginatedResponse<Track>> nextPageFuture =
response.fetchNextFuture(client, Track.class, );
}
}
Reloading resources
Kotlin
val client: DeezerApiClient
val episode: Episode = client.episodes.getById(526673645)
val freshEpisode: Episode = episode.reload(client)
Java (Needs explicit cast, because of abstract Resource)
import java.util.concurrent.CompletableFuture;
{
{
;
client.episodes.getById();
(Episode) episode.reload(client);
CompletableFuture<Episode> freshEpisodeFuture =
(CompletableFuture<Episode>) episode.reloadFuture(client);
}
}
Advanced search
Kotlin
import io.github.kingg22.deezer.client.api.objects.SearchOrder
import io.github.kingg22.deezer.client.api.routes.SearchRoutes.Companion.buildAdvancedQuery
import io.github.kingg22.deezer.client.api.routes.SearchRoutes.Companion.setStrict
import kotlin.time.Duration.Companion.minutes
val client: DeezerApiClient
val query = buildAdvancedQuery {
artist =
durationMin = minutes
}
client.searches.searchPlaylist(query, strict = setString())
client.searches.searchTrack(
q = buildAdvancedQuery(q = , artist = ),
order = SearchOrder.RANKING,
limit = ,
index = ,
)
Java
Why not data class?
Read more about this here.
I take the decision to use class with Poko because immutability is guaranteed and equals are generated.
The idea of this api client is stateless, fetch what u need, and that's it.
🆚 Differences between kotlin and java versions
- Kotlin can't access to the java version and viceversa
Kotlin extensions vs. an external object with static methods (helpers / utility class)
- Java can't access some kotlin specific like DSL, reified types, suspend methods, function with kotlin duration
- Java wrappers of kotlin stuffs, so kotlin is a priority and dictates the route
- Java needs to use kotlin datetime LocalDate and LocalDateTime when get dates :/
- Similitude kotlin suspend and java blocking it reads the same >_<
🛣 Roadmap
⛓️💥 Dependencies
- ktor-client-content-negotiation-json with kotlinx-serialization
- ktor-client-logging.
- kotlinx-datetime for java is not supported easy less,
but can use long as seconds in some cases.
- Poko and KtorGen in compile time.
📃 References
🐞 Issue Guidelines
Please include one of the following types in your issue title or description:
- Serialization error – e.g. the JSON response missing required field, non-nullable property, etc.
- Missing field in response – field present in official API but absent in models (or extra non‑official data)
- Others
Also state if the issue refers to an official Deezer change or unofficial additional field.
🤝 Contributions
We welcome contributions if:
- Code is written in Kotlin
- Uses the official Deezer API (no scraping or unofficial endpoints)
- Includes at least one test with a sample JSON response
Please fork, open PRs, and ensure tests pass.
📄 License
Licensed under AGPL-3.0 — contributions must respect Deezer API Terms & Conditions, including attribution and rate‑limit policies.