API access
Everything the admin does goes through the Mercury REST API at https://api.cadenza.box. You can call it yourself for integrations, reporting or bulk operations. The full interactive reference lives at api.cadenza.box/docs.
Which environment?
Production is
https://api.cadenza.box. The QA environment ishttps://api.qa.cadenza.boxand mirrors the QA admin at admin.qa.cadenza.box. Credentials are not shared between the two.
Two ways to authenticate
1. API key (recommended for integrations)
An API key is issued for a specific user and inherits that user’s organisation and role. Send it in the X-Api-Key header:
curl -H "X-Api-Key: <prefix>_<secret>" \
"https://api.cadenza.box/org/{orgSlug}/tracks?\$limit=10"Keys can be given an expiry date, switched off, and restricted to a set of permissions. The full key is shown once when it is created, so store it somewhere safe. Cadenzabox staff issue keys; ask [email protected] with the user the key should act as and when it should expire.
2. Session token (JWT)
Sign in to get a token, then send it as the bare Authorization header value:
# Sign in as an admin
curl -X POST https://api.cadenza.box/auth \
-H "Content-Type: application/json" \
-d '{ "email": "[email protected]", "password": "••••••••" }'
# → { "token": "…", "refreshToken": "…" }
# Use the token
curl -H "Authorization: <token>" \
"https://api.cadenza.box/org/{orgSlug}/users"No
BearerprefixThe API expects the raw token in the
Authorizationheader.Authorization: Bearer <token>is rejected with a 401 and the message “The token header is not a valid base64url serialized JSON”.
When the token expires, exchange the refresh token for a new pair:
curl -X POST https://api.cadenza.box/refresh-token \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "…" }'Client site users sign in against their organisation instead, with POST /org/{orgSlug}/auth.
Organisation scope
Most endpoints are scoped by organisation slug in the path, for example /org/{orgSlug}/releases. Your slug is shown under the organisation name in the admin sidebar. Requests without credentials are treated as anonymous and see only what your access settings allow anonymous visitors to see.
Common tasks
| Task | Endpoint |
|---|---|
| List tracks | GET /org/{orgSlug}/tracks |
| List releases | GET /org/{orgSlug}/releases |
| Upload a metadata CSV | POST /org/{orgSlug}/imports/upload (multipart, field file) |
| Check an import | GET /org/{orgSlug}/imports/{id} and …/errors |
| Upload audio for a recording | POST /org/{orgSlug}/audio/upload (fields recordingId, file) |
| Create a user | POST /org/{orgSlug}/users |
| Request a download | POST /org/{orgSlug}/downloads |
Use $limit and $skip query parameters to page through lists, and see the docs site for filter syntax and response shapes.