Skip to the content
  1. Docs
  2. Get started

Authentication

Core + Managed TransfersGuide · 3 min
The credentials MusicAPI accepts, which route takes which, the Client-Secret-only routes, DevTokens with and without sub, one-time tokens, and how to keep the secret on your server.

Every API call carries one credential in the Authorization header. Which credentials a route accepts depends on its prefix.

The credentials

CredentialHeaderWhere it may live
Client Secret (Basic)Authorization: Basic base64(clientId:clientSecret)Your backend only
Client ID tokenAuthorization: Token <clientId>Anywhere. It is public.
One-time tokenAuthorization: Token <oneTimeToken>Your app, for 30 seconds after a sign-in
DevTokenAuthorization: DevToken <ES256 JWT>Your frontend. Your backend signs it.
Docs sessionAuthorization: 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

RouteBasicClient ID tokenOne-time tokenDevTokenDocs session
/public/* (catalog, connected users)YesYesYesYesYes
/api/{integrationUserUUID}/* (the user's library)YesNoNoYesYes
DELETE /public/integrations/user/{uuid}YesNoNoNoNo
/public/transfer-sessions/*YesNoNoOnly without subNo
GET /public/transfers/* (Match Results)YesNoNoNoYes
/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
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.

  1. Make a key pair

    Make a P-256 key pair with OpenSSL (the commands are below). Keep private.ec.key on your backend.

  2. Upload the public key

    Open Settings in the dashboard and add public.pem under Dev Token JWT Public EC Keys. Save, and note the Key ID of the key.

  3. Sign tokens on your backend

    Algorithm ES256, the Key ID in kid, your Client ID in iss, and a short exp.

Make the key pair
openssl ecparam -name prime256v1 -genkey -noout -out private.ec.key
openssl ec -in private.ec.key -pubout -out public.pem
Node (jsonwebtoken)
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 }
  );
}
Use it
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 in sub. A call for any other integrationUserUUID gets 403. Give the browser of each user a token with their own sub.
  • Without sub: the token works for every connected user of your account. Keep such a token on your servers, for example for POST /public/transfer-sessions, which refuses a token with sub.

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.