Troubleshooting
Rate limiting
The API implements multiple layers of rate limiting to ensure fair usage and service stability:
1. Request Rate Limits
All requests are subject to per-second rate limits to protect against traffic spikes. These limits are keyed per user token, or per client IP for API key traffic. Funneling all users through one user ID is what usually triggers these limits.
If you consistently hit these limits, consider implementing request batching or caching strategies.
2. Daily App Limits
Each partner application has a daily request quota that counts every authenticated request to any /v0 endpoint - search, preview, download, sound effects, and reporting alike. Each app has two thresholds:
- Soft Limit - When reached, requests continue but response headers will indicate the limit has been exceeded. You can view your app's soft limit in the Developer Portal under your app settings.
- Hard Limit - When reached, requests are blocked with HTTP 429 responses. You can view your app's hard limit in the Developer Portal under your app settings.
Notifications:
- At 90% of soft limit: Warning notification sent
- At soft limit: Notification sent, but requests continue
- At hard limit: Requests blocked until daily reset (midnight UTC)
The daily limits reset at midnight UTC. If you need higher limits, contact your Epidemic Sound partner manager.
3. Per-user limits (user token auth only)
Partner Token / User Token integrations are limited to 350 requests per week per user, per app - but this counts only the audio-delivery endpoints, not general browsing:
GET /v0/tracks/{id}/downloadGET /v0/tracks/{id}/streamandGET /v0/tracks/{id}/hls
Downloads and streaming have separate 350-per-week counters, so exhausting one does not block the other.
Search, browse, metadata, moods, genres, collections, sound effect endpoints and usage reporting do not count. Only successful responses increment the counter.
API key requests are attributed to your app rather than to an end user, so the per-user weekly limit does not apply to them at all. If you authenticate with an API key, the daily app quota and the per-second spike limits are the limits that apply to you.
Rate Limiting Response Headers
When rate limits are encountered, the API returns the following headers:
Daily App Limits:
X-RateLimit-Reached: Set to"true"when soft or hard limit is reachedX-RateLimit-Reset: Timestamp when the limit resets (midnight UTC)
Per-User Limits:
x-user-ratelimit-count: Current request count for the userx-user-ratelimit-limit: Maximum allowed requests (350)X-User-Rate-Limit-Reset: Time until the limit resets
HTTP 429 Response:
When the hard limit is reached, the API responds with HTTP 429 (Too Many Requests). The response may include a Retry-After header (in seconds) indicating when to retry. Implement exponential backoff and retry logic to handle this gracefully, respecting the Retry-After header when present.
Best Practices
To stay within rate limits:
- Use batch requests where possible
- Monitor the rate limit headers in responses
- Set up alerts at 80-90% of your daily quota
If you encounter rate limit errors, contact us and include which endpoint you're calling and the error you're seeing. Using a single user token for all your users often triggers per-second (spike) limits — use unique user tokens per end user where possible.
Transient errors (HTTP 502, 503, 504)
These are transient errors caused by intermediate network components (load balancers, proxies, etc.) between your servers and ours. They are expected to occur occasionally and do not indicate a problem with your integration.
Implement an exponential backoff retry strategy so these do not surface as errors to your end users:
| Attempt | Wait time |
|---|---|
| 1st retry | 5ms |
| 2nd retry | 10ms |
| 3rd retry | 20ms |
| 4th retry | 40ms |
| 5th retry | 80ms |
If the response carries a Retry-After header, respect it instead of the schedule above. This applies to every retryable error, not just 429.
If errors persist beyond 5 retries, log the incident and surface a user-friendly message.
Retries and DDoS protection
To ensure the stability of the API, we use web application firewall solutions that protect against malicious attacks. In many cases, this allows us to mitigate attacks without affecting users. However, it is sometimes hard to distinguish between an attack and an unintentional request overload from well-intended clients, sometimes referred to as friendly fire.
You can decrease the risk that your client gets mistaken for a malicious actor by implementing delays for any request retries, for example, by using the exponential backoff strategy described above.
DDoS mitigation responses
When the web application firewall denies a request, it returns 406 Not Acceptable on audio delivery (pdn.epidemicsound.com). Despite the status name, this is not a content negotiation problem — changing the Accept header will not help.
We do our best to ensure this does not affect requests from legitimate clients, but unfortunately, this can not always be avoided, and therefore we advise you to handle this in your clients.
A 406 most often means automated downloads from a small number of IP addresses have been mistaken for scraping. What triggers it is the sustained, machine-regular pattern rather than any particular request — steady sequential downloads from one IP can reach it at surprisingly modest rates.
Retry after a delay of at least 2 seconds, increasing the delay on each attempt and giving up after a few — an immediate retry from the same IP makes things worse. If a Retry-After header is present in the response, respect that timing instead. Spreading download traffic out over time is the real fix, since the block follows the sustained pattern rather than any single request.
Don't retry indefinitely. A short pause clears a transient block, but once an IP is blocked outright no amount of retrying will get through. If 406s survive your retries, stop and contact us with your egress IP addresses and a time window, and we will adjust the firewall rules for your integration.
Audio download URL errors
GET /v0/tracks/{id}/download and GET /v0/sound-effects/{trackId}/download return a
time-limited signed URL on pdn.epidemicsound.com. Requests to that URL can fail
independently of the API call that produced it:
| Status | Cause |
|---|---|
401 Unauthorized | The URL has expired, the signature was altered, or extra query parameters were appended to it. The signature covers the query string, so adding your own parameters invalidates the URL. |
400 Bad Request | The signature, exp or key_id parameter is missing. |
406 Not Acceptable | Blocked by the web application firewall — see above. |
Signed URL lifetimes depend on the requested quality:
quality=normal(128 kbps) — valid for 24 hoursquality=high(320 kbps) — valid for 1 hour
If you queue downloads for later processing, either use quality=normal or request the
URL at the moment you download, so the URL does not expire while queued.