Spotify's Web API centers on three families of entities you will use most: catalog objects (artists, albums, tracks, shows, episodes, audiobooks), user-scoped resources (playlists, saved library items, followed artists/users), and playback targets (devices & the user's active playback session). Understanding how these groups relate and which IDs each operation needs is the difference between succeeding on the first call and getting stuck hunting for values.
Domain model and key relationships
-
Catalog objects are identified by Spotify IDs and URIs. Catalog endpoints accept either raw
idpath parameters (e.g.get-track,get-an-album) or comma-separatedidsquery parameters for batch fetches (e.g.get-several-tracks). Some write endpoints require full Spotify URIs (e.g.add-to-queueand playlist insertions acceptspotify:track:<id>orspotify:episode:<id>). -
Playlists are first-class, mutable, user-owned resources. Most playlist operations require a
playlist_idpath value (get details, get items, add items, remove items, reorder). Playlist creation uses auser_idpath (create a playlist for a user). Playlist mutation endpoints often return asnapshot_idthat identifies the playlist state after the change. -
The authenticated user's identity and library are separate:
get-current-users-profilereturns the current user'sid(useful forcreate-playlist), whileget-users-playlistsandget-a-list-of-current-users-playlistsenumerate playlists. Saved library operations (save/remove albums, tracks, shows, episodes, audiobooks) operate on the current user and use dedicated endpoints. -
Playback control targets devices.
get-a-users-available-devicesreturnsdevice.idvalues you pass to playback operations. If you omitdevice_id, commands target the user's currently active device.
Entry points — what to call first
-
When you need the current user's identifier: call
get-current-users-profile. The returnedidis theuser_idused bycreate-playlistand some user-scoped listing endpoints. -
When you need a
playlist_id: either usesearchwithtype=playlist, useget-a-list-of-current-users-playlists(orget-list-users-playlistsfor other users), or callget-playlistif you already have an id/URI. -
For playback control: call
get-a-users-available-devicesto discoverdevice_idvalues (useful forstart-a-users-playback,transfer-a-users-playback, volume and skip commands). If nodevice_idis provided, the active device is used. -
To fetch catalog IDs in bulk:
search(with appropriatetype) finds items and returnsidanduri;get-several-tracks,get-multiple-artists,get-multiple-albumsaccept comma-separatedidsfor batch retrieval.
Common tasks and the sequence of calls to perform them
The following tasks are the ones users ask for most often and show the typical sequence of operations and parameters you must supply.
-
Create a playlist and add tracks
- Get current user
idviaget-current-users-profile(if creating for the authenticated user). Use thatuser_idwithcreate-playlistand supply playlist metadata in the body. - Add items with
add-tracks-to-playlistusing theplaylist_id. Prefer sending URIs in the request body when adding many items (queryuriscan exceed URL length). Note the maximum items per request (see batching below).
- Get current user
-
Inspect and modify a playlist's items
- Retrieve playlist items with
get-playlists-tracks(usefieldsto limit nested fields and reduce payload). Mutating operations returnsnapshot_idvalues:remove-tracks-playlistandreorder-or-replace-playlists-tracksreturnsnapshot_idwhich identifies the new playlist state. - Use
reorder-or-replace-playlists-tracksto replace the full item list (supplyurisor a body). Use the reorder parameters in the body to move ranges — the operation returns a newsnapshot_id.
- Retrieve playlist items with
-
Control playback (start, pause, skip, seek, queue)
- Discover devices via
get-a-users-available-devices. Usedevice_idfor explicit targeting or omit it to affect the active device. - Start/resume with
start-a-users-playback. Providecontext_uri(album/playlist) oruris(list of track URIs) in the body; useoffsetto start at a specific position. - Add a single item to the queue with
add-to-queue(requires a Spotify URI, not just anid). - Seek with
seek-to-position-in-currently-playing-track, set volume withset-volume-for-users-playback, toggle shuffle withtoggle-shuffle-for-users-playback, and set repeat withset-repeat-mode-on-users-playback.
- Discover devices via
-
Manage the user's saved library (save / remove / check)
- Save or remove items using the dedicated endpoints:
save-tracks-user,remove-tracks-user,save-albums-user,remove-albums-user,save-shows-user,remove-shows-user, etc. Each endpoint has its own maximum per request (see batching rules below). - To check whether items are in the user's library, use the corresponding "check" endpoints (e.g.
check-users-saved-tracks) which accept comma-separatedidsand return boolean arrays.
- Save or remove items using the dedicated endpoints:
-
Search and recommendations
- Use
searchwithqandtypeto find catalog items and obtainid/uri. Use field filters inq(e.g.year:1990-1995,artist:Radiohead,tag:new) to narrow results. - Generate personalized recommendations with
get-recommendations. Provide up to 5 seed values acrossseed_artists,seed_tracks, andseed_genres(at least one seed is required). Optionally set tunable attributes (e.g.target_energy,min_tempo) to bias results.
- Use
Paging, batching, and parameter limits (practical rules)
-
Many list endpoints use
limitandoffset. Defaults are typically 20; maximum per-request limits are often 50. If more results are needed, call the same endpoint with a largeroffset. -
Batch endpoints accept comma-separated
idsoruriswith strict maxima: common limits are 20 for albums, 50 for tracks/shows/episodes/audiobooks, and 100 for some playlist operations (playlist add/set endpoints note a 100-item limit). Sending more than the allowed maximum in one request will fail. -
When adding many tracks to a playlist, avoid using the
urisquery parameter because of URL-length concerns; put the URIs in the request body instead. -
Audio-features batching:
get-several-audio-featuresaccepts up to 100 track IDs.
OAuth scopes and permission patterns (what will fail without the right scopes)
Many operations require the authenticated token to include specific user-scopes. Common mappings to keep in mind:
-
Playback control: require playback scopes such as
user-read-playback-state,user-modify-playback-state, and for streaming/remote control a streaming-related scope may be necessary. -
Reading the current playback and currently playing track:
user-read-currently-playinganduser-read-playback-state. -
Managing playlists:
playlist-modify-publicand/orplaylist-modify-privateare required to create or edit playlists;playlist-read-privateis required to read private playlists. -
Saved library:
user-library-readto check and list saved items,user-library-modifyto save or remove items. -
Following artists/users and checking follows:
user-follow-readanduser-follow-modify. -
Top items and recently-played:
user-top-readanduser-read-recently-played.
If a write operation returns 403 or 401-like errors, it commonly indicates missing scopes or that the authenticated user is not allowed to perform the action on that resource.
Market and availability quirks
-
Many catalog endpoints accept a
marketparameter. If a user access token is supplied, the user's account country takes precedence over themarketquery value. If neither amarketnor a user-country is available, some content may be treated as unavailable. When availability matters (e.g., building a play queue or creating a playlist meant to be playable), prefer catalog items returned with an explicit market or respect the user's account country. -
Track/episode playability sometimes differs by market and by whether the response marks an item as playable. Use
include_external=audioonsearchonly when the client can play externally hosted content.
Playlist mutation details and snapshot semantics
-
After any playlist mutation (
add-tracks-to-playlist,remove-tracks-playlist,reorder-or-replace-playlists-tracks) the response includes asnapshot_id. Thesnapshot_idis an opaque identifier for that playlist state. If the caller needs to confirm a change was applied or to detect concurrent modifications, preserve thesnapshot_idreturned by the most recent change. -
When removing individual occurrences of a track from a playlist, use
remove-tracks-playlistwith objects identifyinguriandpositionsif you need to remove a specific occurrence.
Playback command details and device selection
-
Most playback commands accept an optional
device_id. If omitted they act on the user's currently active device. Useget-a-users-available-devicesto list devices and theiridvalues. Some devices may refuse remote commands depending on platform or current state (e.g. a device already in a different session). -
add-to-queuerequires a Spotify URI (track or episode). Passing an id without thespotify:track:orspotify:episode:prefix will not work. -
start-a-users-playbackaccepts a body withcontext_uri(album/playlist/podcast) or an arrayurisfor a list of tracks; use theoffsetobject to start at a specific item index.
Search syntax and recommendation seeds — non-obvious filters
-
The
searchqparameter supports field filters (for exampleartist:Queen year:1975-1980 isrc:...) and special filters liketag:new(albums in the last two weeks) andtag:hipster(lowest popularity). Use these filters to narrow results without post-filtering. -
get-recommendationsrequires at least one seed acrossseed_artists,seed_tracks,seed_genresand allows at most five total seed values. Tunable attributes (min/max/target prefixed keys) bias results; if results are sparse, the recommendations response can include debugging information explaining why the requested target count couldn't be met.
Error and rate-limit signals to observe
-
429 responses indicate rate limiting. The response typically includes a
Retry-Afterheader; use the header value to determine when the operation can be retried. -
400-level errors on write endpoints commonly indicate invalid input (exceeding batch size, malformed URIs, invalid
positionindices when inserting into playlists). 403 errors often indicate missing scopes or permission problems.
Practical tips and gotchas (quick reference of common pitfalls)
-
Many endpoints accept both
idanduriforms in different contexts. Check whether an endpoint requiresid(path param) oruri(queue and many playlist insertion operations). Passing the wrong form will fail. -
Respect per-endpoint batch limits (20, 50, 100 depending on endpoint). If a user requests adding dozens or hundreds of items, break the work into multiple requests explicitly by calling the add endpoint multiple times with valid batch sizes.
-
For playlist operations that accept
fields, usefieldsto return only what you need (for examplefields=tracks.items(track(name,uri)),snapshot_id) to reduce payload size when scanning or reporting playlist contents. -
When modifying playback, several operations are eventual:
transfer-a-users-playbackmay not make a device active instantly;start-a-users-playbackmay return before playback actually starts. Verify playback state viaget-information-about-the-users-current-playbackif you need confirmation. -
Some "get multiple" endpoints (e.g.
get-several-tracks,get-multiple-artists) will return arrays in the same order as requested IDs; use that ordering to correlate results to input IDs. -
If the user asks to play or queue an item found via
search, prefer theurifield from search results—it's the simplest, guaranteed-to-work identifier for playback endpoints.
When you need something not covered here
If a requested action requires IDs you don't have, the usual ways to obtain them are search (by text/filters), get-current-users-profile (to find the current user_id), or the relevant list endpoint (get-a-list-of-current-users-playlists, get-a-users-available-devices, or catalog lookups like get-an-artist / get-an-album). Use the operation that naturally returns the ID the mutate or playback endpoint requires.
Use these patterns to map user intents to the minimal set of calls: find the needed IDs via search/list endpoints, ensure required OAuth scopes are present for the intended mutation or playback, respect per-endpoint batch limits, and pass device_id when you must target a particular device rather than the user's active device.