- Docs
- Get started
Rate limits and errors
Core + Managed TransfersGuide · 3 min
The rate limit of a partner account, the error shape, the internal error codes, and what to do on a 412 or a 429.
Rate limit
Each partner account has one rate limit for all its keys and credentials together.
- 300 requests per minute by default.
- One fixed 60-second window. The first request starts the window, and the count resets 60 seconds later.
- Over the limit, the API answers
429 Too Many RequestswithRetry-After: 60. The header gives the window length in seconds, not the time left in the window. - The limit counts calls to
/public/*and/api/*. The hosted sign-in pages and webhooks do not count. - Need more? Contact us. We can raise the limit of your account or remove it.
A docs sandbox session has its own limit: 30 calls per minute.
{
"message": "MusicAPI rate limit. You have exceeded the rate limit for this endpoint or server is currently unable to handle the request. Please wait and retry after the indicated time."
}
Handle a 429
async function callMusicApi(url, init, attempt = 0) {
const response = await fetch(url, init);
if (response.status !== 429 || attempt >= 3) {
return response;
}
const waitSeconds = Number(response.headers.get("retry-after") ?? "60");
await new Promise((resolve) => setTimeout(resolve, waitSeconds * 1000));
return callMusicApi(url, init, attempt + 1);
}
Spread bulk work over time instead of sending it in bursts. A music service can also refuse a call because of its own limits. Retry such a call later, with a growing pause.
The error shape
Every error answer is JSON.
{
"internalCode": 14,
"message": "Needs reauthentication",
"sentryId": "b6f1c2d4e5a64f0f9a1b2c3d4e5f6a7b"
}
| Field | What it is |
|---|---|
message | A short text. Show it in your logs, not to your users. |
internalCode | A number for the cases worth branching on (table below). Not every error has one. |
details | More detail, when there is any. |
sentryId | Our error id. Send it to us when you report a problem. |
A body or query that fails validation answers 400 with the field that is wrong:
{
"type": "body",
"message": "\"itemIds\" must contain less than or equal to 20 items",
"details": [{ "message": "\"itemIds\" must contain less than or equal to 20 items", "path": ["itemIds"] }]
}
Status codes
| Status | Meaning | What to do |
|---|---|---|
400 | The request is not valid. | Fix the request. Do not retry it unchanged. |
401 | No credential, or a credential this route does not read. | Check the Authorization header and the route table. |
403 | The credential is valid but not allowed here, or an evaluation account reached its cap. | Use a Client Secret where the route needs one. |
404 | The connected user, item or transfer does not exist in your account. | Check the id. Another account's id also answers 404. |
412 | The user must sign in again. | Send the user through the hosted sign-in. |
418 | The service does not support this operation. | Check Services and features. |
422 | The item is already in the collection. | Treat it as done. |
429 | Rate limit. | Wait Retry-After seconds. |
5xx | Our error, or the music service failed. | Retry later with a growing pause. |
Internal error codes
internalCode | Name | Status |
|---|---|---|
| 12 | InvalidReturnUrl: the returnUrl is not one of your Accepted Return URLs | 400 |
| 14 | IntegrationUserNotAuthenticated: the stored sign-in no longer works | 412 |
| 15 | NotSupportedMethod: the service has no such operation | 418 |
| 18 | ItemAlreadyExistsInCollection | 422 |
| 19 | CollectionDoesNotExists: the playlist or album is gone, or cannot be read | 404 |
| 20 | ManualLoginRequired: the user must sign in on the service's own site first | 403 |
| 21 | ActionInMusicServiceRequired: the user must do something in the service first, for example accept new terms | 403 |
The user must sign in again (412)
A 412 with internalCode: 14 means the music service refused the stored sign-in, and MusicAPI could not renew it. The user changed their password, removed your app, or the refresh token expired.
{
"internalCode": 14,
"message": "Needs reauthentication"
}
What to do:
- Mark the connection as broken in your app.
- Show the user a "Reconnect" button that opens the hosted sign-in for the same service.
- When the same music account signs in again, it keeps its
integrationUserUUID. Your stored id stays valid.
Before it answers 412, MusicAPI already tried to renew the tokens once. Do not retry the call in a loop.