π Reference
Deep links, the low-level transport, domain types, and error handling
π Deep links
Build URLs that open an entity in the Qobuz app or web player β pure string builders, no network.
client.deepLink
Every client carries a deep-link helper:
client.deepLink.album("0634904032432") // https://open.qobuz.com/album/0634904032432
client.deepLink.track(33933680)
client.deepLink.playlist(65996412)
client.deepLink.artist(43840)createDeepLink(base?)
Use it standalone (without a client). base is "open" (default, shareable) or "play" (web player).
import { createDeepLink } from "@kud/qobuz"
const open = createDeepLink() // https://open.qobuz.com/β¦
const play = createDeepLink("play") // https://play.qobuz.com/β¦Returns a DeepLink β { album(id), track(id), playlist(id), artist(id) }.
βΆοΈ Now playing
readNowPlayingTrackId(options?)
The id of the currently-playing track, read directly from the Qobuz desktop app's local queue state β no API call, no auth. The lower-level primitive behind client.nowPlaying().
import { readNowPlayingTrackId } from "@kud/qobuz"
const trackId = await readNowPlayingTrackId() // number | undefinedReturns undefined if nothing is playing or the state file is absent. options is { path?: string } β overrides the default macOS location (defaultPlayerStatePath()). macOS only.
π Collection stats
readLibraryStats(options?)
Collection analytics computed from the Qobuz desktop app's local library database (qobuz.db) β no API call, no auth. Reads the SQLite file read-only/immutable (via the system sqlite3), so the running app is undisturbed.
import { readLibraryStats } from "@kud/qobuz"
const stats = await readLibraryStats({ limit: 10 })
// stats.quality β [{ bitDepth: 24, count: 192 }, β¦] (hi-res ratio)
// stats.topGenres β [{ name: "Metal", count: 484 }, β¦]
// stats.topLabels β [{ name: "Nuclear Blast", count: 75 }, β¦]
// stats.topArtists β [{ name: "In Flames", count: 10 }, β¦] (by offline albums)
// stats.recentlyAddedβ [{ month: "2026-06", count: 51 }, β¦]
// stats.totals β { offlineAlbums, offlineArtists, offlineTracks, savedTracks }Returns a LibraryStats, or undefined if the database (or sqlite3) is absent. options is { path?: string; limit?: number }. macOS only.
Offline vs saved. Quality (
quality,topArtists,recentlyAdded) comes from your offline/downloaded tracks; genres and labels come from your broader saved library β the two live in different tables, so the type names them explicitly.
π οΈ Low-level transport
For endpoints not yet wrapped by a resource, drop down to the raw signed-request transport.
createTransport(config)
import { createTransport, QOBUZ_BASE_URL } from "@kud/qobuz"
const transport = createTransport({ appId, token })
const raw = await transport.get("label/get", { label_id: 123 })config is { appId, token?, baseUrl?, fetchImpl? }. The returned Transport exposes get<T>(path, query?), which injects the X-App-Id / X-User-Auth-Token / User-Agent headers and throws a QobuzError (kind: "http") on non-2xx. QOBUZ_BASE_URL is the default API base.
π Domain types
All ids and fields use camelCase. Optional fields are absent when Qobuz doesn't return them.
type Album = {
id: string // note: album ids are strings
title: string
artist?: Artist
tracksCount?: number
releaseDate?: string
duration?: number
image?: QobuzImage
genre?: string
hires?: boolean
}
type Artist = {
id: number
name: string
picture?: string
albumsCount?: number
}
type Track = {
id: number
title: string
album?: Album
artist?: Artist
trackNumber?: number
duration?: number
hires?: boolean
}
type Playlist = {
id: number
name: string
description?: string
tracksCount?: number
isPublic?: boolean
owner?: string
duration?: number
}
type QobuzImage = { thumbnail?: string; small?: string; large?: string }
type SearchResults = {
query: string
albums: Album[]
tracks: Track[]
artists: Artist[]
}
type UserFavourites = { albums: Album[]; artists: Artist[]; tracks: Track[] }
type FavouriteType = "albums" | "artists" | "tracks"
type PageOptions = { limit?: number; offset?: number }
type CreatePlaylistParams = {
name: string
description?: string
isPublic?: boolean
}β οΈ Error handling
Every failure throws a QobuzError β a standard Error augmented with a kind and an optional HTTP status:
type QobuzError = Error & {
kind: "http" | "auth" | "bootstrap"
status?: number
}kind | When |
|---|---|
auth | The token/app_id was rejected (e.g. expired session). |
http | A non-2xx response from the API; status carries the code. |
bootstrap | fetchAppId couldn't scrape the app_id (Qobuz changed its bundle). |
import { connect, createMemoryStore, type QobuzError } from "@kud/qobuz"
try {
await connect({ token, store: createMemoryStore() })
} catch (error) {
const qobuzError = error as QobuzError
if (qobuzError.kind === "auth") {
// prompt the user to reconnect with a fresh token
}
}