Which package to install
Most apps install one package, an integration, and import everything from it. This page helps you pick one and explains how the other packages fit around it.
What to install
| You're building | Install |
|---|---|
| Code that runs on a server: a Node service, a Cloudflare Worker, Bun, Deno, a command-line tool or an Electron main process | server |
| A web page without React | browser |
| A React app | react |
| A Next.js app | server for route handlers, server components and actions, and react for client components. See Set up your server. |
| Your own client, from the parts | core, and the client and library packages you need. See Build your own client from the parts. |
| A Music User Token for your own account, to try the API or run a script | The CLI, @open-music-sdk/cli, beside any of the above. See The command-line tool. |
Each package's reference page gives its install line.
A page can't sign a developer token, so it fetches one from a route on your server. tokenEndpoint in server is that route. An app with browser or react therefore runs server, or another route that does the same job, on its back end. See Serve a developer token to a page.
How the packages are split
The SDK is a family of small packages in four tiers, in the manner of the AWS SDK for JavaScript v3. Each tier is built on the ones below it.
| Tier | Packages | What it's for |
|---|---|---|
| Integrations | server, browser, react | What an app installs. A ready-made client, and everything else an app uses, from one import. |
| Clients | client-catalog, client-user | A named function for nearly every endpoint of Apple's API |
| Libraries | lib-playlists, lib-preview-player | The work most apps do around the clients |
| Foundation | core, developer-token, user-token, util-artwork, types, validate | The parts everything else is built on |
The clients are split at the token boundary. Every function in client-catalog reads the catalog and sends the developer token alone. Every function in client-user reads or changes one listener's things and sends their Music User Token as well. Developer tokens and Music User Tokens explains why the line falls there.
The libraries do what an app would otherwise write around the clients:
lib-playlistsfinds tracks from another service in Apple's catalog, reads a playlist whole, and adds what it's missing without adding anything twice.lib-preview-playerplays the short preview clips of the songs a client fetched, as a queue around one audio element.
The foundation packages:
coreis the HTTP client every request goes through. It attaches the tokens, followsnextlinks, turns Apple's status codes into errors and retries what's worth retrying.developer-tokensigns a developer token with your private key, or fetches one from your token endpoint, and keeps it fresh.user-tokenchecks a Music User Token with Apple, takes one in from a page, and keeps it in a store on your server.util-artworkturns Apple's artwork templates into image URLs.typesandvalidateare generated from Apple's documentation: a TypeScript type and a Standard Schema validator for every object in the API.
What an integration gives you
Each integration gives you a client. createServerClient in server signs its own developer token with your key. createBrowserClient in browser and react fetches one from your token endpoint.
The client is core's client, with request, paginate, storefront, as and forUser, and three namespaces on it:
catalog: every function ofclient-catalog, bound to the client, handing over what Apple's answer holds instead of the whole answer.user: every function ofclient-user, bound the same way.playlists: the verbs oflib-playlists.
as(token) gives you the same client for one listener, and forUser(userId) does the same with the token looked up in a store.
Each integration adds what its platform needs:
serverhastokenEndpoint, the route that hands a page a developer token.browserhascreateConnect, which runs Apple's sign-in for the listener's Music User Token, andMUSICKIT_SCRIPT, the address of Apple's script, for your content security policy.reacthas everything inbrowser, plusMusicProvider, the hooksuseMusic,useMusicUserToken,useConnect,usePreviewPlayeranduseMusicQueries, andmusicQueriesfor TanStack Query.
Each also re-exports what an app uses of the other packages, under the names those packages give them. The reference pages of server and browser list them. core's createClient, and the tools the clients are built with, aren't re-exported. To build your own client, install core and the client and library packages themselves.
One version for every package
Every package ships the same version number. If you install core and the client and library packages yourself, keep them all on the same version.
If your app does end up with a different copy of core than one of the packages resolves, nothing breaks. A client made by either copy is a client to every package, and an AppleMusicError is recognised, and retried, whichever copy made it. That's because both go by shape: a client is anything with the client's methods, and an AppleMusicError is an Error with that name and a _tag.
Module format and runtimes
Every package is ESM only, with no CommonJS build. The SDK supports Node 24 or newer, and needs no framework runtime.
serveris one build that runs on Node, Cloudflare Workers, Bun and Deno, since each has the samefetchand WebCrypto. It's also for a command-line tool or an Electron main process. See Set up your server.browserruns in a page. Nothing a page bundles from it signs a token, holds a key or touches the page's storage.reactruns in a page too, with React 19 as a peer dependency. TanStack Query isn't a dependency:musicQueriesgives whatuseQueryanduseInfiniteQuerytake, and imports nothing from it.coredepends on nothing outside the family, and runs anywherefetchdoes.jose, which signs developer tokens, is the only third-party runtime dependency in the family.lib-preview-playerneeds an audio element, so it runs in a browser.lib-playlistsandutil-artworkrun anywhere.