Developers
The Stillmore Group API
- OpenAPI 3.1Every endpoint, field and error, for code generators
- Postman collectionImport it, set apiKey, send
- TypeScript clientOne file, no dependencies, retries and webhooks
- StatusWhether the API is up right now
Getting started
The API does what the workspace does: labels, artists and releases with their tracks, covers and masters, sending them to review and distribution, following them to the stores, smart links, cover licences and the money they make. It is turned on per organization: an owner or admin asks for it in the workspace's API tab, or it comes with the plan.
- In Workspace › API, make a sandbox key (
sm_test_…): it works in a copy of your organization where nothing is real. - Create a release with its tracks, upload the cover and masters to the addresses the API gives you, and submit it.
- Play review and the stores with the sandbox simulations, and watch the webhooks arrive.
- Make a live key (
sm_live_…) with only the scopes your system needs.
curl https://api.stillmoregroup.com/api/v1/me \ -H "Authorization: Bearer $STILLMORE_API_KEY"
curl https://api.stillmoregroup.com/api/v1/releases \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"title":"Night Signals","primaryArtistIds":["<artist id>"],"primaryGenre":"Pop","language":"en","tracks":[{"title":"Night Signals"}]}'Keys and scopes
Send the key as Authorization: Bearer <key>. Only its SHA-256 is stored and it is shown once. A key acts for the member who holds it and is pinned to one organization: a call may do what the key's scopes allow and what that member may do in the workspace, both checked on every call. Keys can be limited to IP addresses or ranges, given an end date, rolled with a grace period and revoked; changing what a key may do takes an authenticator code.
| Scope | What it allows |
|---|---|
| releases:read | Releases, their tracks, review and delivery status, codes and store links. |
| releases:write | Drafts, tracks, splits, artwork and audio files. |
| releases:submit | Submit releases for review and ask for takedowns. |
| artists:read | The organization's artist roster. |
| artists:write | Add artists to the roster and change their details. |
| labels:read | The organization's labels and imprints. |
| labels:write | Add labels and imprints and change their details. |
| finance:read | Balance, ledger, earnings, published royalty statements and payouts. |
| payouts:write | Ask for payouts to the organization's saved payout methods, once an owner or admin allows it in the API tab. |
| webhooks:manage | Register, change and test webhook endpoints. |
Write scopes include the read scope of the same thing. Payout requests also need an owner or admin to allow them in the API tab, and go only to payout methods saved in the workspace.
Answers and errors
Every answer is JSON: { data }, or { data, hasMore, nextCursor } for lists. Timestamps are ISO 8601 in UTC, dates YYYY-MM-DD, amounts decimal strings. Fields are only ever added within v1, never renamed or removed: ignore the ones you don't know. Every answer carries X-Request-Id; send it to support with any question.
{
"error": {
"type": "invalid_request_error",
"code": "VALIDATION_ERROR",
"message": "tracks[0].title: Required",
"details": [{ "path": "tracks[0].title", "message": "Required", "code": "invalid_type" }],
"requestId": "req_…"
}
}Error codes (50)
- 401 API_KEY_REQUIRED
- No key was sent. Send it as `Authorization: Bearer <key>`.
- 401 INVALID_API_KEY
- The key is malformed, unknown or does not match.
- 401 API_KEY_REVOKED
- The key was revoked. Create a new one in the API tab.
- 401 API_KEY_EXPIRED
- The key passed its expiry date.
- 403 API_KEY_PAUSED
- Stillmore Group paused the key. Contact support.
- 403 API_KEY_OWNER_INACTIVE
- The member the key acts for lost access to the organization. An owner or admin can take the key over.
- 403 API_ACCESS_DISABLED
- API access is not turned on for this organization.
- 400 INVALID_ORGANIZATION_HEADER
- The Stillmore-Organization header must be an organization id from GET /v1/organizations.
- 403 SUB_LABELS_NOT_ALLOWED
- The key may not act for sub-labels. An owner or admin allows it on the key in the API tab.
- 403 SUB_LABEL_NOT_ALLOWED
- The organization in Stillmore-Organization is not a sub-label below the key's organization, or the member the key acts for can't open it.
- 403 SANDBOX_ONLY
- Simulations run in the sandbox only; call them with a test key (sm_test_…).
- 400 SANDBOX_NO_SUB_LABELS
- Test keys work in the organization's sandbox only; leave out the Stillmore-Organization header.
- 401 OAUTH_TOKEN_INVALID
- The OAuth access token is malformed, unknown or revoked.
- 401 OAUTH_TOKEN_EXPIRED
- The OAuth access token is over an hour old. Get a new one with the refresh token.
- 401 OAUTH_CONNECTION_REVOKED
- The organization disconnected the app, or the app was deleted. It has to be connected again.
- 403 OAUTH_APP_SUSPENDED
- Stillmore Group suspended the app.
- 403 OAUTH_MEMBER_INACTIVE
- The member who connected the app lost access to the organization. An owner or admin can connect it again.
- 403 IP_NOT_ALLOWED
- The request came from an address the key does not allow.
- 403 INSUFFICIENT_SCOPE
- The key lacks the scope this endpoint needs.
- 403 OWNER_PERMISSION_MISSING
- The member the key acts for no longer holds the permission this endpoint needs.
- 429 TOO_MANY_FAILED_ATTEMPTS
- Too many requests with a wrong key came from this address. Wait and try again.
- 429 RATE_LIMITED
- The key or the organization sent too many requests this minute. Retry after `Retry-After` seconds.
- 400 VALIDATION_ERROR
- The request did not pass validation; `details` lists each field.
- 400 INVALID_JSON
- The body is not valid JSON.
- 413 PAYLOAD_TOO_LARGE
- The body is larger than 1 MB. Files are uploaded separately.
- 415 UNSUPPORTED_MEDIA_TYPE
- Send JSON with `Content-Type: application/json`.
- 400 INVALID_ID
- An id in the request is not a valid identifier.
- 404 ROUTE_NOT_FOUND
- No endpoint answers at this method and path.
- 400 INVALID_CURSOR
- Pass `nextCursor` from the previous page as it is.
- 412 REVISION_MISMATCH
- The record changed since you read it (If-Match). Read it again and retry.
- 409 EXTERNAL_ID_IN_USE
- Another record of the same kind in your organization already has this externalId.
- 409 UPC_IN_USE
- Another release already carries this UPC.
- 409 LABEL_ARCHIVED
- Releases can't be added to an archived label.
- 403 API_PAYOUTS_OFF
- Payout requests through the API are off. An owner or admin turns them on in Workspace › API › Settings.
- 429 SUBMISSION_LIMIT_REACHED
- The organization used today's submissions through the API; the limit resets at midnight UTC.
- 422 RELEASE_SUBMISSION_INVALID
- The release misses what submission needs; `details.issues` lists each field (GET …/checks shows the same before submitting).
- 409 UPLOAD_NOT_RECEIVED
- Complete was called before the file arrived at the upload address. Finish the PUT first.
- 422 ARTWORK_CMYK
- The cover is CMYK; stores take RGB covers only.
- 400 IMPORT_URL_NOT_ALLOWED
- Imports take public http or https links without credentials in them.
- 422 IMPORT_FAILED
- The link could not be downloaded, or what came back was not usable (shown on the import).
- 422 IMPORT_TOO_LARGE
- The file at the link is larger than the limit for its kind.
- 422 IMPORT_TIMED_OUT
- The download took too long; upload large files with the upload endpoints.
- 410 STATEMENT_VOID
- Stillmore Group withdrew the statement after publishing it; a corrected statement follows. It stays listed with status VOID, without its lines.
- 400 IDEMPOTENCY_KEY_INVALID
- The Idempotency-Key header must be 1 to 255 visible characters.
- 422 IDEMPOTENCY_KEY_REUSED
- The Idempotency-Key was already used with a different request.
- 409 IDEMPOTENCY_IN_PROGRESS
- A request with this Idempotency-Key is still running. Retry shortly.
- 503 MAINTENANCE
- The platform is being updated. Retry after `Retry-After` seconds.
- 503 MAINTENANCE_READ_ONLY
- Reads work, changes are paused while the platform is updated.
- 503 DATABASE_UNAVAILABLE
- A short outage on our side. Retry after `Retry-After` seconds.
- 500 INTERNAL_ERROR
- Something failed on our side. Retry with the same Idempotency-Key, or send the request id to support.
Lists, retries and limits
- Pages: lists are newest first; pass
nextCursorback ascursoruntilhasMoreis false.limitgoes up to 100 (500 for statement lines).updatedSincekeeps a copy in sync. - Idempotency: send
Idempotency-Key(a UUID) on writes. A retry with the same key and body gets the first answer (Idempotent-Replayed: true) for 24 hours; another body with the same key is422 IDEMPOTENCY_KEY_REUSED. - Lost updates: every object has
revision(also theETag); send it asIf-Matchand a change made since answers412 REVISION_MISMATCH. - Rate limits: 120 requests a minute per key and three times that for the organization, unless agreed otherwise; every answer has
X-RateLimit-Limit,-Remainingand-Reset, and a 429 saysRetry-After. Releases sent to review: 100 a day by default. - Updates: while the platform is updated, reads may go on and writes answer
503 MAINTENANCE_READ_ONLYwithRetry-After.
Sub-labels
A master or white label running sub-labels from one system can allow a key to act for them (an owner or admin, with an authenticator code). Name the sub-label in the Stillmore-Organization header: ids, lists, permissions, review and events are then the sub-label's, while logs, usage and the rate limit stay with the key's organization. GET /v1/organizations lists where a key can act.
Sandbox
Sandbox keys (sm_test_…) work in a copy of your organization made on first use. Nothing there reaches review, the stores, payouts or anyone's inbox, and its webhooks say "livemode": false. These calls play the parts people and stores play, with the same events the real steps raise:
POST /v1/sandbox/releases/{id}/review: approve, request changes or reject a submitted release.POST /v1/sandbox/releases/{id}/deliver: live with a UPC, ISRCs and store links, or refused by the stores.POST /v1/sandbox/royalties: a month of royalties, a published statement and the balance credited.POST /v1/sandbox/payouts/{id}/payandPOST /v1/sandbox/reset.
Webhooks
Register https endpoints in the API tab or with /v1/webhooks. Each delivery is a POST with { id, event, occurredAt, organizationId, livemode, data }; release events carry the release as GET /v1/releases/{id} shows it. A failed delivery is tried twice more, about a minute and then fifteen minutes later (the endpoint's log in the API tab shows each try); GET /v1/events keeps every event for 30 days to catch up.
Check the X-Stillmore-Signature header (t=…,v1=…): an HMAC-SHA256 of `${t}.${rawBody}` with the endpoint's secret. While a secret is rotated, two v1 signatures come.
import { verifyWebhook } from "./stillmore-api";
const ok = await verifyWebhook(rawBody, request.headers.get("x-stillmore-signature"), process.env.WEBHOOK_SECRET!);
if (!ok) return new Response("bad signature", { status: 400 });Events: release.submitted, release.changes_requested, release.rejected, release.approved, release.sent, release.codes_assigned, release.store_links_updated, release.live, release.provider_rejected, release.taken_down, takedown.requested, payout.requested, payout.approved, payout.rejected, payout.paid, payout.failed, statement.published, claim.created, claim.status_changed
OAuth apps
Software other labels connect without giving you a key: make an app in the API tab (it is private to your organization until Stillmore Group opens it to everyone), then use the authorization code flow with PKCE (S256) and your client secret. Tokens act for the member who connected the app, within the scopes they allowed and their role.
https://app.stillmoregroup.com/oauth/authorize?response_type=code&client_id=smc_… &redirect_uri=https://your.app/callback&scope=releases:read%20finance:read &state=…&code_challenge=<base64url(sha256(verifier))>&code_challenge_method=S256
curl https://api.stillmoregroup.com/api/oauth/token \ -u "smc_…:smcs_…" \ -d grant_type=authorization_code -d code=… \ -d redirect_uri=https://your.app/callback -d code_verifier=…
The access token (sm_oat_…) lasts an hour; swap the refresh token (sm_ort_…, 60 days) for a new pair with grant_type=refresh_token. A refresh token works once: using one again ends the connection. POST https://api.stillmoregroup.com/api/oauth/revoke withdraws a token.
Reference
Base address https://api.stillmoregroup.com/api/v1. Fields of every object are in the OpenAPI document.
Account
GET
/v1/meWho the key is
The organization, the key's scopes and limits, and the release lead time. A cheap call to check a key works.
GET
/v1/organizationsOrganizations the key can act for
The key's own organization, and the sub-labels below it when the key may act for them. To act for a sub-label, send its id in the Stillmore-Organization header: every id, list and limit is then that sub-label's, as if it had its own key.
Reference
GET
/v1/referenceGenres, languages, countries and stores
The values the catalogue accepts. Genres and languages are checked against these lists; store codes go in `stores.codes`.
Labels
GET
/v1/labelslabels:readList labels
POST
/v1/labelslabels:writeCreate a label or imprint
Errors: EXTERNAL_ID_IN_USE, PLAN_QUOTA_REACHED, DUPLICATE
GET
/v1/labels/{labelId}labels:readRead a label
Errors: LABEL_NOT_FOUND
PATCH
/v1/labels/{labelId}labels:writeChange a label
Errors: LABEL_NOT_FOUND, REVISION_MISMATCH, EXTERNAL_ID_IN_USE
Artists
GET
/v1/artistsartists:readList artists
POST
/v1/artistsartists:writeAdd an artist to the roster
Errors: EXTERNAL_ID_IN_USE, PLAN_QUOTA_REACHED, DUPLICATE_EXTERNAL_ARTIST_ID
GET
/v1/artists/{artistId}artists:readRead an artist
Errors: ARTIST_NOT_FOUND
PATCH
/v1/artists/{artistId}artists:writeChange an artist
Errors: ARTIST_NOT_FOUND, REVISION_MISMATCH, PLAN_QUOTA_REACHED
Releases
GET
/v1/releasesreleases:readList releases
Newest first. Filter by status, label, artist, UPC or your externalId; `updatedSince` returns what changed since your last sync.
POST
/v1/releasesreleases:writeCreate a draft release
Creates the draft and, when `tracks` is given, its tracks in order. A SINGLE always has exactly one track, created with the release.
Errors: EXTERNAL_ID_IN_USE, UPC_IN_USE, LABEL_NOT_FOUND, ARTIST_NOT_FOUND, LABEL_TRACK_LIMIT_REACHED
GET
/v1/releases/{releaseId}releases:readRead a release with its tracks
Errors: RELEASE_NOT_FOUND
PATCH
/v1/releases/{releaseId}releases:writeChange a draft release
Only drafts and releases sent back for changes can change. `null` clears a field that can be empty.
Errors: RELEASE_NOT_FOUND, RELEASE_NOT_EDITABLE, REVISION_MISMATCH, UPC_IN_USE
DELETE
/v1/releases/{releaseId}releases:writeArchive a draft release
Drafts and releases sent back for changes are archived (status ARCHIVED); nothing that went to review is deleted.
Errors: RELEASE_NOT_FOUND, RELEASE_NOT_EDITABLE
POST
/v1/releases/batchreleases:writeCreate many draft releases
Each release is created on its own, as POST /v1/releases would; the answer lists every result in the order sent. One failing doesn't stop the others.
Tracks
GET
/v1/tracksreleases:readFind tracks
Across the organization, newest first: by ISRC, by your externalId, or every track changed since a time.
GET
/v1/releases/{releaseId}/tracksreleases:readA release's tracklist
Every track, in order (not paged).
Errors: RELEASE_NOT_FOUND
POST
/v1/releases/{releaseId}/tracksreleases:writeAdd a track
At the end of the tracklist, or at `position` (the tracks from there move down). Primary artists default to the release's.
Errors: RELEASE_NOT_FOUND, RELEASE_NOT_EDITABLE, RELEASE_SINGLE_TRACK_LIMIT, LABEL_TRACK_LIMIT_REACHED, EXTERNAL_ID_IN_USE
PUT
/v1/releases/{releaseId}/tracks/orderreleases:writeReorder the tracklist
Errors: RELEASE_NOT_FOUND, INVALID_TRACK_REORDER
GET
/v1/tracks/{trackId}releases:readRead a track
Errors: TRACK_NOT_FOUND
PATCH
/v1/tracks/{trackId}releases:writeChange a track
Errors: TRACK_NOT_FOUND, RELEASE_NOT_EDITABLE, REVISION_MISMATCH
DELETE
/v1/tracks/{trackId}releases:writeRemove a track
The tracks after it move up.
Errors: TRACK_NOT_FOUND, RELEASE_NOT_EDITABLE
Splits
GET
/v1/releases/{releaseId}/splitreleases:readThe release-wide royalty split
Errors: RELEASE_NOT_FOUND, TRACK_NOT_FOUND, ARTIST_NOT_FOUND, LABEL_NOT_FOUND
PUT
/v1/releases/{releaseId}/splitreleases:writeSet the release-wide royalty split
Applies to every track without a split of its own. An empty `parties` removes it.
Errors: SPLITS_LOCKED
GET
/v1/tracks/{trackId}/splitreleases:readA track's own royalty split
Errors: RELEASE_NOT_FOUND, TRACK_NOT_FOUND, ARTIST_NOT_FOUND, LABEL_NOT_FOUND
PUT
/v1/tracks/{trackId}/splitreleases:writeSet a track's own royalty split
Errors: SPLITS_LOCKED
Files
POST
/v1/releases/{releaseId}/artworkreleases:writeStart a cover upload
Returns a signed address valid for an hour. PUT the file there with the given headers, then call complete. Covers are square JPEG or PNG, exactly 3000 × 3000 pixels, in RGB, up to 25 MB.
Errors: RELEASE_NOT_EDITABLE, UPLOAD_RATE_LIMITED, INVALID_ARTWORK_FILE_TYPE, INVALID_AUDIO_FILE_TYPE
POST
/v1/releases/{releaseId}/artwork/completereleases:writeFinish a cover upload
Checks the stored file and puts it on the release, replacing any cover it had. Calling it again for the same upload changes nothing.
Errors: UPLOAD_NOT_RECEIVED, UPLOAD_SESSION_EXPIRED, UPLOAD_SESSION_FORBIDDEN, ARTWORK_DIMENSIONS_INVALID, ARTWORK_CMYK
POST
/v1/releases/{releaseId}/artwork/importreleases:writeFetch a cover from a link
Stillmore Group downloads the file in the background and checks it like an upload. Follow the import with GET /v1/imports/{importId}. The link must answer with Content-Length.
Errors: IMPORT_URL_NOT_ALLOWED, RELEASE_NOT_EDITABLE
GET
/v1/releases/{releaseId}/artworkreleases:readDownload the cover
Errors: ARTWORK_NOT_FOUND
DELETE
/v1/releases/{releaseId}/artworkreleases:writeRemove the cover
Errors: RELEASE_NOT_EDITABLE
POST
/v1/tracks/{trackId}/audioreleases:writeStart a master upload
Returns a signed address valid for an hour. Masters are WAV or FLAC, up to 500 MB.
Errors: RELEASE_NOT_EDITABLE, UPLOAD_RATE_LIMITED, INVALID_ARTWORK_FILE_TYPE, INVALID_AUDIO_FILE_TYPE
POST
/v1/tracks/{trackId}/audio/completereleases:writeFinish a master upload
Checks the stored file (it must really be WAV or FLAC), reads its duration, sample rate and bit depth, and starts the copyright scan.
Errors: UPLOAD_NOT_RECEIVED, UPLOAD_SESSION_EXPIRED, UPLOAD_SESSION_FORBIDDEN, ARTWORK_DIMENSIONS_INVALID, ARTWORK_CMYK
POST
/v1/tracks/{trackId}/audio/importreleases:writeFetch a master from a link
Errors: IMPORT_URL_NOT_ALLOWED, RELEASE_NOT_EDITABLE
GET
/v1/tracks/{trackId}/audioreleases:readDownload the master
Errors: AUDIO_NOT_FOUND
DELETE
/v1/tracks/{trackId}/audioreleases:writeRemove the master
Errors: RELEASE_NOT_EDITABLE
GET
/v1/imports/{importId}releases:readFollow a file import
Errors: IMPORT_NOT_FOUND
Distribution
GET
/v1/releases/{releaseId}/checksreleases:readCheck a release before sending it
Everything submission requires, plus the store rules reviewers check by eye: audio quality, titles (no "feat.", promotional words, emoji or shouting capitals), artist names, codes already used elsewhere, cover licences. ERROR items block a submission (submission rules) or automatic approval (store rules); WARNING items are for a person to judge.
Errors: RELEASE_NOT_FOUND
POST
/v1/releases/{releaseId}/submitreleases:submitSend a release to distribution
The release joins Stillmore Group's review queue exactly as one submitted in the workspace does (paid plans are reviewed first). On an account with automatic approval it is approved without a person once its checks are clean, and goes straight to delivery. Follow it with the release.* webhooks or GET /v1/events.
Errors: RELEASE_SUBMISSION_INVALID, INVALID_RELEASE_STATUS, PLAN_QUOTA_REACHED, SUBMISSION_LIMIT_REACHED, ORGANIZATION_SUSPENDED
POST
/v1/releases/submitreleases:submitSend many releases to distribution
Up to 50 releases, each submitted on its own; the answer lists every result. The daily submission limit counts each one.
Errors: SUBMISSION_LIMIT_REACHED
POST
/v1/releases/{releaseId}/takedownreleases:submitAsk for a live release to come down
Stillmore Group's team takes it down from the stores; the release.taken_down webhook tells you when it's done.
Errors: TAKEDOWN_NOT_ALLOWED, TAKEDOWN_ALREADY_REQUESTED
POST
/v1/releases/{releaseId}/documentsreleases:writeStart a document upload
When review asks for documents (proof of rights, licences, agreements: review.documentsRequested), upload them here: PDF, Word, JPEG or PNG up to 20 MB.
POST
/v1/releases/{releaseId}/documents/completereleases:writeFinish a document upload
Errors: UPLOAD_NOT_RECEIVED
Events
GET
/v1/eventsRead back events
Every event your webhooks can receive, newest first, kept for 30 days whether or not an endpoint was listening. Use it to catch up after downtime or instead of webhooks. A key sees the events its scopes cover: release and takedown events need releases:read, payout and statement events finance:read, claim events either.
Webhooks
GET
/v1/webhookswebhooks:manageList webhook endpoints
POST
/v1/webhookswebhooks:manageRegister an endpoint
Up to ten https endpoints. The answer shows the signing secret once.
Errors: WEBHOOK_LIMIT
PATCH
/v1/webhooks/{webhookId}webhooks:manageChange or pause an endpoint
Errors: WEBHOOK_NOT_FOUND
DELETE
/v1/webhooks/{webhookId}webhooks:manageRemove an endpoint
Errors: WEBHOOK_NOT_FOUND
POST
/v1/webhooks/{webhookId}/testwebhooks:manageSend a test ping
Errors: WEBHOOK_NOT_FOUND
GET
/v1/webhooks/{webhookId}/deliverieswebhooks:manageThe endpoint's last 25 deliveries
Errors: WEBHOOK_NOT_FOUND
POST
/v1/webhooks/{webhookId}/rotate-secretwebhooks:manageRotate the signing secret
A new secret, shown once. The old one keeps signing alongside it (two v1= signatures) for graceHours, 24 by default.
Errors: WEBHOOK_NOT_FOUND
Money
GET
/v1/balancefinance:readThe balance, per currency
What the organization has earned, the advance still to recoup, payouts on their way, and what can be paid out now.
GET
/v1/transactionsfinance:readLedger entries
Every credit and debit of the balance, newest first: royalties, fees, payouts, adjustments, recoupments, transfers.
GET
/v1/earningsfinance:readEarnings by month, release, track, store or territory
What the stores reported, summed by groupBy over the royalty lines matched to the catalogue, biggest first (months in order). Filter by reporting months, currency, release, track, store or territory. Gross, before commission: statements carry the net.
GET
/v1/statementsfinance:readPublished royalty statements
Statements Stillmore Group published to the organization, newest first. Drafts never show; one withdrawn after publishing stays listed with status VOID.
GET
/v1/statements/{statementId}finance:readOne statement
Errors: STATEMENT_NOT_FOUND
GET
/v1/statements/{statementId}/linesfinance:readThe royalty lines behind a statement
Each store line of the statement's period and currency, up to 500 a page.
Errors: STATEMENT_NOT_FOUND, STATEMENT_VOID
GET
/v1/statements/{statementId}/exportfinance:readThe statement's lines as CSV
Every line in one text/csv file (UTF-8, comma separated, a header row), the same columns as the lines endpoint.
Errors: STATEMENT_NOT_FOUND, STATEMENT_VOID
GET
/v1/payout-methodsfinance:readSaved payout methods
The bank, PayPal and Payoneer accounts saved in the workspace, masked. Payouts through the API can only go to these.
GET
/v1/payoutsfinance:readPayout requests
GET
/v1/payouts/{payoutId}finance:readOne payout request
Errors: PAYOUT_NOT_FOUND
POST
/v1/payoutspayouts:writeRequest a payout
Asks Stillmore Group to pay out part of the available balance to a saved payout method. An owner or admin must first allow payout requests through the API in Workspace › API › Settings (with an authenticator code), and each request is told to them. Stillmore Group reviews it as any other: it stays PENDING until approved, then PAID. Send an Idempotency-Key so a retry never asks twice.
Errors: API_PAYOUTS_OFF, PAYOUT_METHOD_NOT_FOUND, INSUFFICIENT_BALANCE, BELOW_MINIMUM_PAYOUT
POST
/v1/payouts/{payoutId}/cancelpayouts:writeCancel a pending payout
Errors: PAYOUT_NOT_FOUND, PAYOUT_NOT_PENDING
Smart links
GET
/v1/releases/{releaseId}/smart-linkreleases:readThe release's smart link
The public page fans open to choose a store. null until one is made: by PUT, or when staff record store links at delivery.
Errors: RELEASE_NOT_FOUND
PUT
/v1/releases/{releaseId}/smart-linkreleases:writeMake or change the smart link
Made on the first call with the release title as its address unless you give a slug; later calls change only what they name.
Errors: RELEASE_NOT_FOUND, SLUG_TAKEN
GET
/v1/releases/{releaseId}/smart-link/statsreleases:readClicks and sign-ups
Clicks per store and per day for the last 30 days, and fans waiting for the release.
Errors: RELEASE_NOT_FOUND
Cover licences
GET
/v1/cover-licensesreleases:readCover licence requests
GET
/v1/cover-licenses/{licenseId}releases:readOne request
Errors: COVER_LICENSE_NOT_FOUND
POST
/v1/cover-licensesreleases:writeAsk for a cover licence
A track marked as a cover needs a mechanical licence before it goes to the stores. OWN: upload the licence you hold with …/document, Stillmore Group checks it for free. PURCHASE: Stillmore Group gets it for a fixed price, from the balance (WALLET, at once) or by card (a person pays at checkoutUrl). One open request per track.
Errors: TRACK_NOT_A_COVER, COVER_LICENSE_EXISTS, COVER_LICENSING_CLOSED, INSUFFICIENT_BALANCE
POST
/v1/cover-licenses/{licenseId}/documentreleases:writeStart uploading the licence file
OWN requests: PDF, Word, JPEG or PNG up to 20 MB, also to answer a refusal.
Errors: COVER_LICENSE_NOT_FOUND, COVER_LICENSE_STATE
POST
/v1/cover-licenses/{licenseId}/document/completereleases:writeFinish uploading the licence file
The request goes to Stillmore Group (PENDING).
Errors: COVER_LICENSE_NOT_FOUND, COVER_LICENSE_STATE, UPLOAD_NOT_RECEIVED
POST
/v1/cover-licenses/{licenseId}/cancelreleases:writeCancel a request not sent in yet
Before payment (CARD) or before the file (OWN).
Errors: COVER_LICENSE_NOT_FOUND, COVER_LICENSE_STATE
Sandbox
POST
/v1/sandbox/releases/{releaseId}/reviewreleases:readPlay review
Test keys only. Decides a submitted release as a reviewer would: APPROVE, REQUEST_CHANGES or REJECT, with the same status changes, review notes and events (release.approved, release.changes_requested, release.rejected).
Errors: SANDBOX_ONLY, INVALID_RELEASE_STATUS
POST
/v1/sandbox/releases/{releaseId}/deliverreleases:readPlay delivery
Test keys only. Sends an approved release to make-believe stores: LIVE gives it a UPC, ISRCs and store links (release.sent, release.codes_assigned, release.live, release.store_links_updated); REFUSED_BY_STORES refuses it with your reason (release.provider_rejected).
Errors: SANDBOX_ONLY, RELEASE_NOT_APPROVED
POST
/v1/sandbox/royaltiesfinance:readPlay a royalty month
Test keys only. Reports gross royalties for a month over the sandbox's live releases (store and territory lines), publishes the statement and credits the balance (statement.published).
Errors: SANDBOX_ONLY, NOTHING_LIVE, STATEMENT_EXISTS
POST
/v1/sandbox/payouts/{payoutId}/payfinance:readPlay paying a payout
Test keys only. Approves and pays a pending payout request (payout.approved, payout.paid), taking it off the balance.
Errors: SANDBOX_ONLY, PAYOUT_NOT_FOUND, PAYOUT_NOT_PENDING
POST
/v1/sandbox/resetEmpty the sandbox
Test keys only. Deletes everything made in the sandbox: catalogue, files, smart links, licences, statements, ledger, payouts and events. Webhook endpoints and keys stay.
Errors: SANDBOX_ONLY