- Docs
- Get started
Authentication
Every API call carries one credential in the Authorization header. Which credentials a route accepts depends on its prefix.
The credentials
| Credential | Header | Where it may live |
|---|---|---|
| Client Secret (Basic) | Authorization: Basic base64(clientId:clientSecret) | Your backend only |
| Client ID token | Authorization: Token <clientId> | Anywhere. It is public. |
| One-time token | Authorization: Token <oneTimeToken> | Your app, for 30 seconds after a sign-in |
| DevToken | Authorization: DevToken <ES256 JWT> | Your frontend. Your backend signs it. |
| Docs session | Authorization: DocsSession <token> | This docs site. You never send it yourself. |
Make API keys under API & webhooks in the dashboard. Each key is a Client ID and a Client Secret. The values show only once, when you create the key. Make one key per backend, so you can revoke one without touching the others.
Which route takes which
| Route | Basic | Client ID token | One-time token | DevToken | Docs session |
|---|---|---|---|---|---|
/public/* (catalog, connected users) | Yes | Yes | Yes | Yes | Yes |
/api/{integrationUserUUID}/* (the user's library) | Yes | No | No | Yes | Yes |
DELETE /public/integrations/user/{uuid} | Yes | No | No | No | No |
/public/transfer-sessions/* | Yes | No | No | Only without sub | No |
GET /public/transfers/* (Match Results) | Yes | No | No | No | Yes |
/app/* (hosted sign-in state) | No credential needed |
A call without any credential gets 401. A credential that a route refuses gets 403.
Client Secret (Basic)
The Client ID and the Client Secret together give full access to your account. Send them only from your backend.
curl "https://api.musicapi.com/public/search/introspection" \
-u "$MUSICAPI_CLIENT_ID:$MUSICAPI_CLIENT_SECRET"
Only Basic sees the raw music-service tokens (authData) and only Basic can delete a connected user.
Client ID token
The Client ID is public. Use it from a browser or an app for the catalog endpoints.
curl -X POST "https://api.musicapi.com/public/search" \
-H "Authorization: Token $MUSICAPI_CLIENT_ID" \
-H "Content-Type: application/json" \
-d '{"type": "track", "track": "Numb", "artist": "Linkin Park", "sources": ["spotify", "appleMusic"]}'
DevToken
A DevToken is a short-lived JWT that your backend signs with your own key. Your frontend then calls /api/{integrationUserUUID}/… directly, and your Client Secret stays on the server.
- Make a key pair
Make a P-256 key pair with OpenSSL (the commands are below). Keep
private.ec.keyon your backend. - Upload the public key
Open Settings in the dashboard and add
public.pemunder Dev Token JWT Public EC Keys. Save, and note the Key ID of the key. - Sign tokens on your backend
Algorithm
ES256, the Key ID inkid, your Client ID iniss, and a shortexp.
openssl ecparam -name prime256v1 -genkey -noout -out private.ec.key
openssl ec -in private.ec.key -pubout -out public.pem
import jwt from "jsonwebtoken";
export function signDevToken({ privateKey, keyId, integrationUserUUID }) {
const now = Math.floor(Date.now() / 1000);
return jwt.sign(
{
iss: process.env.MUSICAPI_CLIENT_ID,
sub: integrationUserUUID, // optional: limits the token to this one user
iat: now,
exp: now + 60 * 60,
},
privateKey,
{ algorithm: "ES256", keyid: keyId }
);
}
curl "https://api.musicapi.com/api/3f0b8c1e-6a4d-4c7a-9a55-2f1e7d9b0c11/playlists" \
-H "Authorization: DevToken $DEV_TOKEN"
With and without sub
- With
sub: the token works only for the connected user insub. A call for any otherintegrationUserUUIDgets403. Give the browser of each user a token with their ownsub. - Without
sub: the token works for every connected user of your account. Keep such a token on your servers, for example forPOST /public/transfer-sessions, which refuses a token withsub.
A DevToken never deletes a connected user and never reads raw service tokens.
One-time tokens
Add requestOneTimeToken=true to the sign-in URL. The callback then carries a oneTimeToken. It lives for 30 seconds and is bound to that one sign-in.
Use it as Authorization: Token <oneTimeToken> to read the connected user once, with the raw service tokens. This lets an app without a backend get the tokens. See Raw tokens and refresh.
Keep the secret on your server
- Never put the Client Secret in a browser bundle, a mobile app, a URL, a log or a public repository.
- Read it from your secret store at run time:
MUSICAPI_CLIENT_SECRET. - Frontend code uses a DevToken with
sub, or the Client ID token for the catalog. - Lost a secret, or leaked one? Create a new key under API & webhooks, deploy it, then revoke the old key. Both halves of a revoked key stop working at once.
Tenant isolation
Every lookup by integrationUserUUID, sign-in id or transfer id stays inside your account. A uuid of another account answers 404, the same answer as a uuid that does not exist.