Building a playlist generator is one of the most rewarding projects for developers who want to combine music data with real application logic. Whether you're creating a mood-based mixtape tool or a recommendation engine for your users, MusicAPI gives you unified access to catalog data from Spotify, Apple Music, YouTube Music, and more through a single endpoint, making cross-platform playlist generation surprisingly straightforward.
Table of Contents
- What You Will Build
- Setting Up MusicAPI
- Searching For Tracks
- Building The Playlist Logic
- Creating And Saving Playlists
- Cross-Platform Playlist Sync
- Putting It All Together
Quick Summary
| Takeaway | Explanation |
|---|---|
| Unified music API access | MusicAPI connects to Spotify, Apple Music, YouTube Music, and more via one API |
| Simple track search | Search across platforms with a single request and consistent response format |
| Playlist creation | Programmatically create and populate playlists on any supported platform |
| Cross-platform sync | Match and transfer tracks between services using MusicAPI's matching engine |
| Production-ready code | Complete Python and JavaScript examples you can adapt for your own projects |
What You Will Build
Project Overview
In this music API tutorial, you will build a playlist generator that can search for tracks across multiple streaming platforms, assemble them into a cohesive playlist based on genre or artist similarity, and save that playlist directly to a user's streaming account. The finished application works with Spotify, Apple Music, YouTube Music, Deezer, Tidal, and other platforms — all through MusicAPI's unified interface.
By the end of this tutorial, you will have a working playlist generator that:
- Searches for tracks by genre, artist, or keyword
- Builds playlists using smart filtering logic
- Creates playlists on the user's chosen streaming platform
- Supports cross-platform track matching for multi-service sync
Prerequisites And Setup
Before you start, make sure you have the following:
- A MusicAPI account — Sign up at musicapi.com to get your API key
- Python 3.8+ or Node.js 16+ installed on your machine
- Basic knowledge of REST APIs and how to make HTTP requests
- A connected streaming account — You will need at least one streaming service connected through MusicAPI's OAuth flow
Setting Up MusicAPI
Getting Your API Key
Head to the MusicAPI dashboard and create a new project. Your API key will be displayed on the project settings page. Store it securely — you will need it for every request.
MusicAPI uses a simple Bearer token authentication model. Every request includes your API key in the Authorization header:
Authorization: Bearer YOUR_API_KEY
Installing Dependencies
Python:
pip install requests
JavaScript (Node.js):
npm install axios
That is all you need. MusicAPI is a REST API, so any HTTP client works. We use requests for Python and axios for JavaScript throughout this tutorial because they keep the code clean and readable.
Searching For Tracks
Basic Track Search
The foundation of any playlist generator is track search. MusicAPI provides a unified search endpoint that queries across all connected platforms simultaneously.
Python:
import requests
API_KEY = "your_musicapi_key"
BASE_URL = "https://api.musicapi.com/v1"
def search_tracks(query, limit=20):
"""Search for tracks across all connected platforms."""
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"q": query,
"type": "track",
"limit": limit
}
)
response.raise_for_status()
return response.json()["tracks"]
# Search for upbeat pop tracks
results = search_tracks("upbeat pop hits")
for track in results:
print(f"{track['name']} by {track['artist']} — {track['platform']}")
JavaScript:
const axios = require('axios');
const API_KEY = 'your_musicapi_key';
const BASE_URL = 'https://api.musicapi.com/v1';
async function searchTracks(query, limit = 20) {
const response = await axios.get(`${BASE_URL}/search`, {
headers: { Authorization: `Bearer ${API_KEY}` },
params: { q: query, type: 'track', limit }
});
return response.data.tracks;
}
// Search for upbeat pop tracks
const results = await searchTracks('upbeat pop hits');
results.forEach(track => {
console.log(`${track.name} by ${track.artist} — ${track.platform}`);
});
Each track object in the response includes a name, artist, album, platform, platformId, and duration — giving you everything you need to build playlist logic.
Filtering And Refining Results
Raw search results are a starting point. A good playlist generator filters and ranks tracks to create a coherent listening experience. MusicAPI supports several filter parameters to narrow results before they reach your application:
Python:
def search_with_filters(query, genre=None, year_from=None, year_to=None, limit=20):
"""Search with optional genre and year filters."""
params = {
"q": query,
"type": "track",
"limit": limit
}
if genre:
params["genre"] = genre
if year_from:
params["year_from"] = year_from
if year_to:
params["year_to"] = year_to
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params=params
)
response.raise_for_status()
return response.json()["tracks"]
# Find indie rock tracks from the last two years
tracks = search_with_filters("indie rock", genre="rock", year_from=2024)
Building The Playlist Logic
Genre-Based Playlist Generation
A genre-based playlist generator searches for tracks in a specific genre and assembles them into a balanced mix. The key is variety — you want different artists, tempos, and release years to keep the playlist interesting.
Python:
import random
def generate_genre_playlist(genre, track_count=25):
"""Generate a playlist based on a genre with artist diversity."""
search_queries = [
f"best {genre} songs",
f"new {genre} music",
f"popular {genre} tracks",
f"classic {genre} hits"
]
all_tracks = []
seen_artists = set()
for query in search_queries:
results = search_tracks(f"{query}", limit=30)
for track in results:
# Ensure artist diversity: max 2 tracks per artist
artist = track["artist"].lower()
if seen_artists.get(artist, 0) < 2 if isinstance(seen_artists, dict) else artist not in seen_artists:
all_tracks.append(track)
seen_artists.add(artist)
# Shuffle and trim to desired count
random.shuffle(all_tracks)
return all_tracks[:track_count]
playlist = generate_genre_playlist("electronic", track_count=20)
print(f"Generated playlist with {len(playlist)} tracks")
JavaScript:
async function generateGenrePlaylist(genre, trackCount = 25) {
const queries = [
`best ${genre} songs`,
`new ${genre} music`,
`popular ${genre} tracks`,
`classic ${genre} hits`
];
const allTracks = [];
const artistCount = {};
for (const query of queries) {
const results = await searchTracks(query, 30);
for (const track of results) {
const artist = track.artist.toLowerCase();
// Max 2 tracks per artist for variety
if ((artistCount[artist] || 0) < 2) {
allTracks.push(track);
artistCount[artist] = (artistCount[artist] || 0) + 1;
}
}
}
// Shuffle and trim
const shuffled = allTracks.sort(() => Math.random() - 0.5);
return shuffled.slice(0, trackCount);
}
const playlist = await generateGenrePlaylist('electronic', 20);
console.log(`Generated playlist with ${playlist.length} tracks`);
Artist-Based Discovery
Another common pattern is building playlists around a seed artist. You find related artists and pull tracks from each one to create a discovery-focused listening experience.
Python:
def get_related_artists(artist_id):
"""Get artists similar to the given artist."""
response = requests.get(
f"{BASE_URL}/artists/{artist_id}/related",
headers={"Authorization": f"Bearer {API_KEY}"}
)
response.raise_for_status()
return response.json()["artists"]
def generate_artist_radio(seed_artist_name, track_count=20):
"""Build a playlist around a seed artist and related artists."""
# Find the seed artist
search_results = search_tracks(seed_artist_name, limit=5)
if not search_results:
return []
seed_artist_id = search_results[0]["artistId"]
related = get_related_artists(seed_artist_id)
playlist_tracks = []
# Add top tracks from the seed artist
seed_tracks = search_tracks(f"{seed_artist_name} top tracks", limit=5)
playlist_tracks.extend(seed_tracks[:3])
# Add tracks from related artists
for artist in related[:8]:
artist_tracks = search_tracks(f"{artist['name']} popular", limit=5)
playlist_tracks.extend(artist_tracks[:2])
random.shuffle(playlist_tracks)
return playlist_tracks[:track_count]
radio_playlist = generate_artist_radio("Daft Punk", track_count=15)
Creating And Saving Playlists
Creating A Playlist On The Target Platform
Once you have assembled your track list, the next step is creating an actual playlist on the user's streaming platform. MusicAPI handles the platform-specific API calls behind the scenes.
Python:
def create_playlist(user_id, name, description="", platform="spotify"):
"""Create a new empty playlist on the specified platform."""
response = requests.post(
f"{BASE_URL}/playlists",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"userId": user_id,
"name": name,
"description": description,
"platform": platform,
"public": True
}
)
response.raise_for_status()
return response.json()["playlist"]
new_playlist = create_playlist(
user_id="user_123",
name="Weekend Electronic Mix",
description="Auto-generated electronic playlist for the weekend"
)
print(f"Created playlist: {new_playlist['id']}")
JavaScript:
async function createPlaylist(userId, name, description = '', platform = 'spotify') {
const response = await axios.post(`${BASE_URL}/playlists`, {
userId,
name,
description,
platform,
public: true
}, {
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
});
return response.data.playlist;
}
const newPlaylist = await createPlaylist(
'user_123',
'Weekend Electronic Mix',
'Auto-generated electronic playlist for the weekend'
);
console.log(`Created playlist: ${newPlaylist.id}`);
Adding Tracks To Your Playlist
With the playlist created, add tracks to it using the playlist tracks endpoint:
Python:
def add_tracks_to_playlist(playlist_id, track_ids):
"""Add a list of tracks to an existing playlist."""
response = requests.post(
f"{BASE_URL}/playlists/{playlist_id}/tracks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={"trackIds": track_ids}
)
response.raise_for_status()
return response.json()
# Add generated tracks to the playlist
track_ids = [track["platformId"] for track in playlist]
result = add_tracks_to_playlist(new_playlist["id"], track_ids)
print(f"Added {result['addedCount']} tracks to playlist")
JavaScript:
async function addTracksToPlaylist(playlistId, trackIds) {
const response = await axios.post(
`${BASE_URL}/playlists/${playlistId}/tracks`,
{ trackIds },
{
headers: {
Authorization: `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
}
}
);
return response.data;
}
const trackIds = playlist.map(track => track.platformId);
const result = await addTracksToPlaylist(newPlaylist.id, trackIds);
console.log(`Added ${result.addedCount} tracks to playlist`);
Cross-Platform Playlist Sync
Matching Tracks Across Services
One of MusicAPI's most powerful features for building a playlist generator is cross-platform track matching. If a user has playlists on Spotify but wants to listen on Apple Music, you can match tracks between services automatically.
Python:
def match_track_cross_platform(track_id, source_platform, target_platform):
"""Find the equivalent track on a different platform."""
response = requests.get(
f"{BASE_URL}/tracks/{track_id}/match",
headers={"Authorization": f"Bearer {API_KEY}"},
params={
"sourcePlatform": source_platform,
"targetPlatform": target_platform
}
)
response.raise_for_status()
match = response.json()
return match.get("matchedTrack")
def sync_playlist_to_platform(playlist_tracks, source_platform, target_platform):
"""Sync a full playlist from one platform to another."""
matched_tracks = []
unmatched = []
for track in playlist_tracks:
matched = match_track_cross_platform(
track["platformId"], source_platform, target_platform
)
if matched:
matched_tracks.append(matched)
else:
unmatched.append(track)
return matched_tracks, unmatched
matched, missing = sync_playlist_to_platform(
playlist, "spotify", "apple_music"
)
print(f"Matched: {len(matched)}, Missing: {len(missing)}")
Handling Missing Tracks Gracefully
Not every track exists on every platform. A production-grade playlist generator needs to handle missing tracks without breaking the user experience.
Python:
def sync_with_fallback(playlist_tracks, source_platform, target_platform):
"""Sync playlist with search-based fallback for unmatched tracks."""
synced = []
failed = []
for track in playlist_tracks:
# Try direct match first
matched = match_track_cross_platform(
track["platformId"], source_platform, target_platform
)
if matched:
synced.append(matched)
continue
# Fallback: search by name and artist on target platform
query = f"{track['name']} {track['artist']}"
search_results = search_tracks(query, limit=3)
target_results = [
t for t in search_results
if t["platform"] == target_platform
]
if target_results:
synced.append(target_results[0])
else:
failed.append(track)
return synced, failed
Putting It All Together
Full Working Example
Here is a complete Python script that ties everything together into a functional playlist generator:
Python:
import requests
import random
API_KEY = "your_musicapi_key"
BASE_URL = "https://api.musicapi.com/v1"
def search_tracks(query, limit=20):
response = requests.get(
f"{BASE_URL}/search",
headers={"Authorization": f"Bearer {API_KEY}"},
params={"q": query, "type": "track", "limit": limit}
)
response.raise_for_status()
return response.json()["tracks"]
def create_playlist(user_id, name, description, platform):
response = requests.post(
f"{BASE_URL}/playlists",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={
"userId": user_id,
"name": name,
"description": description,
"platform": platform
}
)
response.raise_for_status()
return response.json()["playlist"]
def add_tracks_to_playlist(playlist_id, track_ids):
response = requests.post(
f"{BASE_URL}/playlists/{playlist_id}/tracks",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
},
json={"trackIds": track_ids}
)
response.raise_for_status()
return response.json()
def build_playlist(genre, user_id, platform="spotify", count=25):
"""End-to-end playlist generation pipeline."""
print(f"Searching for {genre} tracks...")
queries = [f"best {genre}", f"new {genre}", f"top {genre} hits"]
all_tracks = []
seen = set()
for q in queries:
for track in search_tracks(q, limit=30):
key = f"{track['name'].lower()}_{track['artist'].lower()}"
if key not in seen:
all_tracks.append(track)
seen.add(key)
random.shuffle(all_tracks)
selected = all_tracks[:count]
print(f"Found {len(selected)} unique tracks. Creating playlist...")
playlist = create_playlist(
user_id=user_id,
name=f"{genre.title()} Mix — Auto Generated",
description=f"A curated {genre} playlist generated with MusicAPI",
platform=platform
)
track_ids = [t["platformId"] for t in selected]
result = add_tracks_to_playlist(playlist["id"], track_ids)
print(f"Playlist created with {result['addedCount']} tracks!")
return playlist
# Run the generator
my_playlist = build_playlist(
genre="lo-fi hip hop",
user_id="user_123",
platform="spotify",
count=20
)
JavaScript:
const axios = require('axios');
const API_KEY = 'your_musicapi_key';
const BASE_URL = 'https://api.musicapi.com/v1';
const headers = { Authorization: `Bearer ${API_KEY}` };
async function buildPlaylist(genre, userId, platform = 'spotify', count = 25) {
console.log(`Searching for ${genre} tracks...`);
const queries = [`best ${genre}`, `new ${genre}`, `top ${genre} hits`];
const allTracks = [];
const seen = new Set();
for (const q of queries) {
const response = await axios.get(`${BASE_URL}/search`, {
headers,
params: { q, type: 'track', limit: 30 }
});
for (const track of response.data.tracks) {
const key = `${track.name.toLowerCase()}_${track.artist.toLowerCase()}`;
if (!seen.has(key)) {
allTracks.push(track);
seen.add(key);
}
}
}
const shuffled = allTracks.sort(() => Math.random() - 0.5).slice(0, count);
console.log(`Found ${shuffled.length} unique tracks. Creating playlist...`);
const { data: { playlist } } = await axios.post(`${BASE_URL}/playlists`, {
userId,
name: `${genre.charAt(0).toUpperCase() + genre.slice(1)} Mix — Auto Generated`,
description: `A curated ${genre} playlist generated with MusicAPI`,
platform
}, { headers: { ...headers, 'Content-Type': 'application/json' } });
const trackIds = shuffled.map(t => t.platformId);
const { data: result } = await axios.post(
`${BASE_URL}/playlists/${playlist.id}/tracks`,
{ trackIds },
{ headers: { ...headers, 'Content-Type': 'application/json' } }
);
console.log(`Playlist created with ${result.addedCount} tracks!`);
return playlist;
}
buildPlaylist('lo-fi hip hop', 'user_123', 'spotify', 20);
Next Steps And Ideas
Now that you have a working playlist generator, here are some ideas to take it further:
- Add mood detection — Use track audio features (tempo, energy, valence) to generate mood-specific playlists like "Chill Evening" or "Morning Workout"
- Build a web interface — Wrap your generator in a simple web app using Flask (Python) or Express (Node.js) so users can create playlists from their browser
- Schedule recurring playlists — Set up a cron job that generates fresh playlists weekly using new releases and trending tracks
- Implement collaborative filtering — Analyze listening history across your user base to recommend tracks that similar listeners enjoy
- Add cross-platform sync — Let users mirror their favorite playlists across all their streaming accounts automatically
MusicAPI handles the complex platform integrations so you can focus on building great playlist experiences. Check out the full API documentation for additional endpoints covering user libraries, playback history, and audio features.
Ready to build your own playlist generator? Sign up for MusicAPI and start building today — the free tier includes enough requests to prototype and test your application.
