Published on July 6, 2026

Building track search into your app means dealing with a dozen different APIs, each with its own auth flow, response format, and rate limits. A songs API collapses that complexity into a single integration. One request, normalized data, every major streaming service.
This post walks you through what a songs API does, the core endpoints you need, and how to build a working track search feature using MusicAPI.
A songs API is a REST interface that lets you search for tracks, fetch metadata (title, artist, album, ISRC, duration), and retrieve streaming or preview URLs. Instead of writing separate integrations for each music platform, a unified songs API handles the service-specific logic and returns a consistent response shape regardless of the source.
| Approach | Auth Flows | Response Formats | Maintenance Burden |
|---|---|---|---|
| Build from scratch (per service) | One per platform (10+) | Different schema per service | High: each API changes independently |
| Unified songs API | One SSO flow | Single normalized schema | Low: the API layer absorbs changes |
The difference is stark. With a direct integration approach, you write and maintain OAuth flows for Spotify, Apple Music, YouTube Music, Tidal, Deezer, and every other service you want to support. With a unified songs API, you authenticate once and get back the same track object every time.
Three operations form the backbone of any songs API: search, metadata retrieval, and streaming URL access.
Search by title, artist, or ISRC. Your users type a song name, and your app needs results fast. A good songs API accepts a query string and returns matching tracks across services. ISRC (International Standard Recording Code) search is critical for matching the exact same recording across platforms.
Fetch track metadata. Once you have a track ID, you need the full picture: title, artist name, album, duration, album art URL, and ISRC. This data powers your UI and any downstream logic like deduplication or analytics.
Get preview or streaming URLs. For playback features, the API should return a preview URL or streaming link tied to the user's authenticated service.
Here is a track search request using MusicAPI's /public/search endpoint:
curl -X POST https://api.musicapi.com/public/search \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"service": "spotify",
"query": "Bohemian Rhapsody Queen",
"type": "track",
"limit": 5
}'
The response returns a normalized array of track objects:
{
"tracks": [
{
"id": "3z8h0TU7ReDPLIbEnYhWlQ",
"title": "Bohemian Rhapsody",
"artist": "Queen",
"album": "A Night at the Opera",
"duration": 354000,
"isrc": "GBUM71029604",
"previewUrl": "https://p.scdn.co/mp3-preview/...",
"albumArt": "https://i.scdn.co/image/..."
}
]
}
That same request structure works for any of the 20+ supported services. Change "service": "spotify" to "service": "appleMusic" or "service": "tidal" and you get back the same fields.
Every streaming platform stores track metadata differently. Spotify returns duration_ms as an integer. Apple Music nests it under attributes.durationInMillis. YouTube Music does not always include ISRC at all.
MusicAPI handles this translation layer. One schema, 20 services. Your code processes a single track object shape regardless of which platform sourced the data.
| Field | Spotify | Apple Music | YouTube Music | Tidal | MusicAPI (normalized) |
|---|---|---|---|---|---|
| Track title | name | attributes.name | title | title | title |
| Artist | artists[0].name | attributes.artistName | artist.name | artist.name | artist |
| Duration | duration_ms | attributes.durationInMillis | lengthSeconds * 1000 | duration * 1000 | duration |
| ISRC | external_ids.isrc | attributes.isrc | Not always available | isrc | isrc |
| Preview URL | preview_url | attributes.previews[0].url | N/A | audioQuality link | previewUrl |
This normalization saves you from writing five different parsing functions and maintaining them as each platform changes its API. You write one parser. It works everywhere.
MusicAPI also handles per-service OAuth, token refresh, and rate limiting behind the scenes. You do not need to track refresh token expiry for each platform or build retry logic for rate-limited requests.
Want to see the full list of normalized endpoints? Check out the endpoints documentation to see every operation available through MusicAPI's unified interface.
Let's build a working track search feature from authentication to rendered results.
MusicAPI uses a Single Sign-On (SSO) flow. You register your app on the MusicAPI Dashboard, configure your API keys for each music service, and initialize the auth flow for your users.
// Initialize the authentication flow
const authUrl = await fetch('https://api.musicapi.com/auth/initialize', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
service: 'spotify',
callbackUrl: 'https://yourapp.com/callback'
})
});
// Redirect the user to authUrl to complete OAuth
After the user completes the OAuth flow, your callback endpoint receives a userUUID that identifies this user across all subsequent API calls.
With authentication complete, call the search endpoint:
async function searchTracks(query, service = 'spotify') {
const response = await fetch('https://api.musicapi.com/public/search', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({
service,
query,
type: 'track',
limit: 10
})
});
const data = await response.json();
return data.tracks;
}
// Usage
const results = await searchTracks('Bohemian Rhapsody');
The /public/search endpoint does not require user authentication for basic track searches. This means you can build search features that work before a user connects their streaming account.
Each track object in the response contains everything you need for a search results UI:
function renderTrackList(tracks) {
return tracks.map(track => ({
display: `${track.title} - ${track.artist}`,
album: track.album,
duration: formatDuration(track.duration),
artwork: track.albumArt,
isrc: track.isrc,
previewUrl: track.previewUrl
}));
}
function formatDuration(ms) {
const minutes = Math.floor(ms / 60000);
const seconds = Math.floor((ms % 60000) / 1000);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
You now have a complete search-to-display pipeline. The same code works whether you search Spotify, Apple Music, Tidal, or any other supported service.
Real-world track data is messy. Here are the edge cases you will hit and how to handle them.
A track that exists on Spotify US might not be available in Spotify Germany. Your songs API integration should check for null or empty streaming URLs and present a clear message to the user rather than a broken play button.
if (!track.previewUrl) {
showMessage('Preview not available in your region');
}
The same recording can appear multiple times across reissues, compilations, and deluxe editions. Use the ISRC field to deduplicate results when displaying search output:
function deduplicateByIsrc(tracks) {
const seen = new Set();
return tracks.filter(track => {
if (!track.isrc || seen.has(track.isrc)) return false;
seen.add(track.isrc);
return true;
});
}
Not every service returns every field. YouTube Music does not always provide ISRC. Some services omit preview URLs entirely. Check the supported features matrix to know which fields each service returns, and build your UI to gracefully handle missing data.
const artist = track.artist || 'Unknown Artist';
const duration = track.duration ? formatDuration(track.duration) : '--:--';
Each streaming platform enforces its own rate limits. MusicAPI abstracts this by managing request queuing and retry logic on the server side. You do not need to implement per-service rate limit handling. Read more about how rate limiting works in the MusicAPI docs.
A songs API is a REST interface for searching, retrieving metadata, and accessing streaming URLs for music tracks. It provides programmatic access to song data including title, artist, album, duration, ISRC, and preview URLs from one or more music streaming services.
Use a unified songs API like MusicAPI. Send a single POST request to the /public/search endpoint with your query and specify the target service. The response returns a normalized track object regardless of which platform you query. Switch between 20+ services by changing one parameter.
No. MusicAPI's /public/search endpoint works with just your API key for basic track, album, and artist searches. User authentication through the SSO flow is only required for user-specific operations like fetching liked tracks, managing playlists, or accessing library data.
ISRC (International Standard Recording Code) is a unique 12-character identifier assigned to each specific recording. It matters because the same song can have different IDs on Spotify, Apple Music, and Tidal, but the ISRC stays consistent. Use it to match tracks across services, deduplicate search results, and build cross-platform features like playlist migration.
Each platform stores track data differently. Spotify uses duration_ms, Apple Music uses attributes.durationInMillis, and Tidal uses duration in seconds. A unified songs API normalizes these differences into a single schema. MusicAPI translates every service's response into consistent field names (title, artist, album, duration, isrc, previewUrl) so your code only handles one format.
You can get preview URLs for tracks through MusicAPI's normalized response. Full streaming URLs require user authentication and depend on the user's subscription with the underlying service. Check the supported features page to see which services return preview URLs.
MusicAPI supports 20+ services for public endpoints including Spotify, Apple Music, YouTube Music, Tidal, Amazon Music, Deezer, SoundCloud, Pandora, Napster, Qobuz, and more. Twelve of these also support authenticated endpoints for user-specific data like liked tracks and playlists.
Ready to skip months of OAuth and SDK work? Start your free MusicAPI trial and connect 10+ streaming services with one unified API.