Music
This guide covers everything you need to build a music experience: browsing and searching the catalog, streaming and downloading tracks, and accessing timing and waveform data for advanced video sync use cases.
List genres with their tracks
Use the genres endpoint to list the available genres.
We recommend that you specify the "type" featured to only show the genres that are featured by our curation team and order by relevance to make sure that the order is based on the most popular genres.
Featured genres have cover art that you can show in your interface. Filtering by a featured genre (e.g. rock) matches tracks tagged with any of its child genres (indie-rock, alternative-rock, etc.), so the 12 featured genres effectively cover the full catalog.
To get only featured genres, list genres using type=featured filter.
Sub-genres (child genres) may not have cover art — the images field can be empty or absent. This is expected behaviour. Always check for the presence of cover art before rendering it, and provide a fallback (e.g. a placeholder image or text-only display) for sub-genres that have none.
The /v0/genres endpoint is capped at 20 results per page. The full catalog (type=all) contains around 500 genres, so you must paginate to retrieve them all. See Pagination for details.
Use the genre details endpoint to show the tracks for a given genre.
List playlists with their tracks
Use the collections endpoint to display playlists curated by our team of in-house experts.
Collections have attributes like title and cover art, and you can choose to return collections with or without tracks.
The response will include a maximum of 20 tracks per collection. If a collection contains more than 20 tracks, use the endpoint '/collections/{collectionId}' to get all tracks.
Dynamic vs. static collections:
- Curated collections are maintained by Epidemic Sound's curation team and may update dynamically — tracks can be added, removed, or reordered at any time. For example, a "Trending on TikTok" collection is refreshed daily. Always fetch collection data from the API rather than caching it locally.
- Imported collections (created by importing a playlist URL from epidemicsound.com) are static snapshots. They do not automatically sync when the source playlist changes on the Epidemic Sound website.
For better performance, especially with large collections, use excludeFields=tracks to list only collection metadata. You can then fetch tracks for specific collections separately using the collection details endpoint.
List moods with their tracks
Use the moods endpoint to allow users to browse the music catalog based on moods like happy, epic or relaxing. Moods have cover art that you can show in your interface.
We recommend that you specify the "type" featured to only display moods that are featured on epidemicsound.com.
The /v0/moods endpoint is capped at 20 results per page. The full catalog (type=all) contains 46 moods, so you must paginate to retrieve them all. See Pagination for details.
Use the mood details endpoint to show the tracks for a given mood.
Browse vs. Search
The Epidemic Sound API offers two ways to find tracks — browse (/v0/tracks) and search (/v0/tracks/search). Both support the same filtering options (mood, genre, BPM, vocals), but search offers additional capabilities:
Search advantages:
- Text search: Optional
termparameter for semantic and keyword search - Sorting: Results can be sorted by relevance, date, title, popularity, BPM, or duration
- Facet counts: Returns aggregation data showing how many tracks match each mood/genre in the result set
- Comprehensive: Can do everything browse does, plus more
Browse advantages:
- Higher page limits: Up to 100 results per page (vs. 60 for search)
When to use which:
- Use search for most use cases — it's more flexible and handles both text search and filter-only scenarios
- Use browse only when you need page sizes above 60 results
Since search accepts all the same filters and the term parameter is optional, you can call search without a term to get pure filtering behavior with the added benefits of sorting and facet counts.
When combining different filters (mood, genre, BPM), all filters are applied as AND — results must match every specified filter. For example, filtering by mood happy and genre pop returns only tracks that are both happy and pop.
Multiple values within a single filter default to AND as well, but this is configurable — see Combine multiple values with AND or OR below.
Multiple values for genre and mood must be sent as repeated query parameters. Bracket notation and comma-separated values are silently ignored — the filter has no effect but you still get a response.
✅ ?genre=dream-pop&genre=synth-pop
❌ ?genre[]=dream-pop&genre[]=synth-pop
❌ ?genre=dream-pop,synth-pop
Many HTTP client libraries (e.g. axios, jQuery) default to bracket notation when serializing arrays. If your filters seem to have no effect, inspect the raw URL your client is sending.
Combine multiple values with AND or OR (filterBehaviour)
The filterBehaviour parameter controls how several values of the same filter combine:
| Value | Behaviour |
|---|---|
allOf | Return only tracks matching every value. This is the default. |
anyOf | Return tracks matching at least one value, which widens the result set. |
# Tracks tagged both sad AND hopeful — a narrow result set
?mood=sad&mood=hopeful&filterBehaviour=allOf
# Tracks tagged sad OR hopeful — substantially wider
?mood=sad&mood=hopeful&filterBehaviour=anyOf
filterBehaviour is available on browse, search and matching image, and applies to the mood and genre filters.
It groups values within a single filter. Different filters still combine with AND, so this returns tracks that are (sad or hopeful) and tagged jazz:
?mood=sad&mood=hopeful&genre=jazz&filterBehaviour=anyOf
Choose anyOf when adding a value should broaden the selection, which is typically what a multi-select mood or genre picker means. Choose allOf when each added value should narrow it. A single anyOf request returns the whole widened set, ranked and paginated like any other result set, so there is no need to issue one request per value and merge them yourself.
allOfis the default, so the parameter is only needed when you wantanyOf.- It has no effect on a filter with only one value.
vocalTypealways combines its values with OR and ignoresfilterBehaviour.- An unrecognised value returns
400naming the parameter — unlike most filters here, this one fails loudly rather than silently.
Search for music
Use the search endpoint to search for any given query within our music library (max 500 characters). The search endpoint uses an open language model that allows users to use semantic search terms such as "music for a calm beach scene" or "high energy track for a workout".
The search endpoint indexes track attributes including moods, genres, artist names, song titles, and BPM. You can further refine results by:
- Filtering by specific genres and moods (applied as AND with the search term; combine multiple values with
filterBehaviour) - Sorting results using
sort(Relevance, Date, Title, Popularity, BPM, Duration) andorder(asc, desc)
Sort and order (ASC/DESC)
The sort parameter chooses what to sort by; the order parameter chooses direction. For most sort types the meaning is intuitive, but for relevance it is easy to get it wrong.
| Sort value | Recommended order | Meaning |
|---|---|---|
Relevance | desc | Most relevant first. With order=asc the API returns the least relevant results (a different slice), which is rarely what you want. |
Date | desc or asc | desc = newest first; asc = oldest first. |
Title | asc or desc | asc = A→Z; desc = Z→A. |
Popularity | desc | Most downloaded first. Useful for surfacing trending or popular tracks. |
BPM | asc or desc | Sort by tempo. asc = slowest first; desc = fastest first. |
Duration | asc or desc | asc = shortest first; desc = longest first. |
Search results are paginated. See Pagination for how to page through results.
Filter by vocals (vocalType)
vocalType is a server-side filter on both browse and search, and is the correct way
to get instrumental-only results:
NONE- fully instrumentalPRESENCE- vocal chops, samples, ad-libs, textures, no lead vocalLEAD- sung lead vocals
Filter by tempo (bpmMin / bpmMax)
bpmMin and bpmMax define an inclusive range and work on both browse and search.
For high-energy content, try combining a semantic term with a BPM floor:
term=high energy workout&bpmMin=140.
Browse
Use the browse endpoint to list tracks filtered by mood, genre, and BPM range simultaneously — its advantage over search is a limit of up to 100. Different filters are combined with AND logic, so results must match every specified criterion; use filterBehaviour to control how multiple values of the same filter combine.
Batch track metadata
Use the track metadata endpoint to fetch metadata for multiple tracks at once by providing a list of track IDs. This is more efficient than making individual requests when you need details for several tracks.
Track ID format
All track IDs in the Partner API are UUIDs (e.g. 1a8d1f60-398c-3cec-83bf-4ed5efd3b851). This is consistent across all endpoints and matches the IDs used in public epidemicsound.com track URLs.
Batch size limit
The endpoint accepts multiple trackId query parameters, but because this is a GET request the IDs are passed in the URL. The server enforces a 4096-byte HTTP request line limit, which with UUID-length IDs means you can include a maximum of around 90 IDs per request before the server returns a 400 error.
For lists larger than 90 tracks, split the IDs into batches and fire the requests in parallel:
async function getTracksMetadata(apiKey, trackIds) {
const BATCH_SIZE = 50 // stay well within the URL length limit
const batches = []
for (let i = 0; i < trackIds.length; i += BATCH_SIZE) {
batches.push(trackIds.slice(i, i + BATCH_SIZE))
}
const results = await Promise.all(
batches.map((batch) => {
const params = new URLSearchParams()
batch.forEach((id) => params.append('trackId', id))
return fetch(
`https://partner-content-api.epidemicsound.com/v0/tracks/metadata?${params}`,
{ headers: { Authorization: `Bearer ${apiKey}` } }
).then((r) => r.json())
})
)
return results.flat()
}
Understanding track response fields
Every track response carries the same set of metadata fields. See the Metadata guide for the full reference, including which fields are nullable and how to fetch metadata in batches.
One of them is worth knowing about before you build against it: isPreviewOnly is not a reliable download check. See the known issue in the Metadata guide.
Audio formats
The API supports low and high quality MP3 files for downloads, and adaptive HLS streaming for real-time playback. See Tracks in the API Reference for full details.
Play a track
For real-time playback while users browse the music library, use the streaming endpoint which returns an HLS (HTTP Live Streaming) manifest URL.
Why HLS for previewing:
- Smaller file transfers: Audio is encoded using the AAC standard, which has a smaller footprint than MP3 for similar quality
- Adaptive quality: The HLS client library automatically switches between two variant quality streams based on network speed
- Seeking support: Users can skip forward/backward during playback
Implementation:
The format consists of audio files split into smaller chunks with manifests (.m3u8 files) that reference these audio files. HLS client libraries handle the complexity automatically:
- iOS/Safari: Native HLS support via AVFoundation (no additional library needed)
- Web browsers: Use hls.js library
- Android: ExoPlayer with HLS support
Here is an example app for iOS that plays HLS streams.
Access to tracks for preview depends on your partnership agreement. See the Fundamentals on content access for details.
Preview vs. Download:
Use HLS streaming for previewing tracks during browsing. When users want to add a track to their project, use the download endpoint below which provides MP3 files.
Download a track
When a user wants to add a track to their project for editing or export, use the download endpoint to get an MP3 file.
Available qualities:
- Normal (128kbps): Sufficient for most use cases
- High (320kbps): For content requiring higher audio quality
The download links expire after 24 hours (normal quality) or 1 hour (high quality). The expiration time is included in the response.
Access to tracks for download depends on your partnership agreement. See the Fundamentals on content access for details.
Report usage of a track
When a user exports their content to a platform or downloads the file to their device, report it. See the Report usage guide for the per-user and bulk endpoints.
Get waveform
All tracks in the library come with a waveform. Waveforms can be used for the following use cases:
- From our user research we know that users look at the waveform to understand track capabilities such as build, drop etc.
- Use it for selection of the particular parts of the track
- Use it to find similar repetitions in the entire track
- Loop selected part of the track using the waveform

Waveform URL data
Each track response includes a waveformUrl field containing a link to the track's waveform data in JSON format. You can find this field in the track response.
Each file consists of a single JSON object containing waveform data points and some meta-information used for its generation. Waveform files were generated for the audio files using 8-bit resolution featuring ~1600 minimum and maximum value pairs in the resulting waveform data.
The format follows the BBC audiowaveform JSON data format.
Example waveform object:
{
"version": 2,
"channels": 1,
"sample_rate": 48000,
"samples_per_pixel": 5539,
"bits": 8,
"length": 1601,
"data": [-46, 52, -44, 44, ...]
}
Highlights (most popular section)
Use the highlights endpoint to get the most popular section of a track. Powered by AI trained on billions of YouTube streams, this endpoint recommends the best time window for your use case.
A highlight is the AI-picked most engaging window of one track. For matching sections across different tracks, see the similar sections feature in Find Similar.
Use cases:
- Start playback from the most engaging part of the track
- Recommend the right section for short-form content (Reels, TikTok, Shorts)
The endpoint accepts up to 5 different durations per request (5-60 seconds each) and returns from/to timestamps (milliseconds) plus duration (seconds).
Get beat timestamps
Use the beats endpoint to get precise beat timestamps for a track. Unlike BPM which is a single number, beats data captures dynamic tempo changes throughout the track.
Use cases:
- Automatically cut video clips in sync with the beat
- Add snap markers aligned with beat timestamps in your editing UI
The response includes time (timestamp in seconds) and value (beat position in a bar, where 1 is the downbeat).
Get lyrics
Use the lyrics endpoint to retrieve the full lyrics text for a track.
Use cases:
- Display lyrics alongside the playing track
- Help users select tracks by lyrical content or theme
- Add captions to video content using the track
The response contains a single lyrics field as a plain string with newline-separated lines. The endpoint returns lyrics: null for:
- Instrumental tracks (
hasVocals: falseon the track response) - Vocal tracks whose lyrics have not been registered yet —
hasVocals: trueis not a guarantee that lyrics are available
Always handle the null case before rendering. You can use hasVocals: false as a safe shortcut to skip the call for known instrumentals, but a true value still requires a lyrics request to know for sure.