API reference
Files
Covers and masters: signed uploads, imports from a link, and downloads.
On this page
Base address https://api.stillmoregroup.com/api/v1. Every answer is JSON; errors have one shape.
| Endpoint | What it does |
|---|---|
POST /releases/{releaseId}/artwork | Start a cover upload |
POST /releases/{releaseId}/artwork/complete | Finish a cover upload |
POST /releases/{releaseId}/artwork/import | Fetch a cover from a link |
GET /releases/{releaseId}/artwork | Download the cover |
DELETE /releases/{releaseId}/artwork | Remove the cover |
POST /tracks/{trackId}/audio | Start a master upload |
POST /tracks/{trackId}/audio/complete | Finish a master upload |
POST /tracks/{trackId}/audio/import | Fetch a master from a link |
GET /tracks/{trackId}/audio | Download the master |
DELETE /tracks/{trackId}/audio | Remove the master |
GET /imports/{importId} | Follow a file import |
Start a cover upload#
POST /releases/{releaseId}/artwork · scope releases:write
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.
Path parameters#
releaseIdstring- An id.
Body#
fileNamestringRequired- The file's name, with its extension. 1 to 255 characters.
contentTypestringRequired- image/jpeg or image/png for covers; audio/wav or audio/flac for masters. 3 to 120 characters.
sizeBytesintegerRequired- Exact size in bytes; the PUT must send the same Content-Length.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/releases/{releaseId}/artwork" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"fileName": "cover.jpg",
"contentType": "image/jpeg",
"sizeBytes": 2483117
}'Response 201#
data holds the object below.
uploadIdstringuploadUrlstring- PUT the file's bytes here.
method"PUT"headersmap of string- Send these headers with the PUT, and Content-Length equal to sizeBytes.
expiresAtstring- Upload and complete before this time.
{
"data": {
"uploadId": "6731c2a1b3c4d5e6f7a8b9c0",
"uploadUrl": "https://storage.example.com/upload/cover.jpg?signature=…",
"method": "PUT",
"headers": {
"key": "…"
},
"expiresAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
UPLOAD_RATE_LIMITED | From the workspace rule behind this endpoint; message says what to change. |
INVALID_ARTWORK_FILE_TYPE | From the workspace rule behind this endpoint; message says what to change. |
INVALID_AUDIO_FILE_TYPE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Finish a cover upload#
POST /releases/{releaseId}/artwork/complete · scope releases:write
Checks the stored file and puts it on the release, replacing any cover it had. Calling it again for the same upload changes nothing.
Path parameters#
releaseIdstring- An id.
Body#
uploadIdstringRequired- An id.
durationSecondsnumber- From 0 to 21600.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/releases/{releaseId}/artwork/complete" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"uploadId": "6731c2a1b3c4d5e6f7a8b9c0"
}'Response 200#
data holds the object below.
idstringlabelIdstringtitlestringversionTitlestring or nulltypestring- One of
SINGLE,EP,ALBUM. statusstring- Where the release is, review and delivery together. One of
DRAFT,LABEL_REVIEW,IN_REVIEW,CHANGES_REQUESTED,REJECTED,APPROVED,SENT_TO_STORES,LIVE,REFUSED_BY_STORES,TAKEDOWN_REQUESTED,TAKEN_DOWN,ARCHIVED. primaryArtistIdsstring[]featuredArtistIdsstring[]
Show 66 more fieldsHide 66 fields
primaryGenrestring or nullsecondaryGenrestring or nulllanguagestring or nullexplicitbooleanreleaseDatestring (date) or nulloriginalReleaseDatestring (date) or nullcopyrightobjectcopyright.objectcLine copyright.objectpLine territoriesobjectterritories.stringmode - One of
WORLDWIDE,CUSTOM. territories.string[]codes storesobjectstores.stringmode - One of
ALL,CUSTOM. stores.string[]codes upcstring or nullartworkobject or null- The cover; null until one is uploaded.
artwork.stringstatus - One of
PENDING_UPLOAD,UPLOADED,VERIFIED,FAILED,DELETED. artwork.string or nullfileName artwork.string or nullmimeType artwork.number or nullsizeBytes artwork.string or nulluploadedAt - ISO 8601 timestamp in UTC.
artwork.number or nullwidth artwork.number or nullheight trackCountinteger- From -9007199254740991 to 9007199254740991.
tracksobject[]- Included when one release is read, created or changed.
tracks[].stringid tracks[].stringreleaseId tracks[].integerposition - From -9007199254740991 to 9007199254740991.
tracks[].stringtitle tracks[].string or nullversionTitle tracks[].string[]primaryArtistIds tracks[].string[]featuredArtistIds tracks[].booleanexplicit tracks[].booleanisCover tracks[].string or nulllanguage tracks[].string or nullisrc tracks[].string or nulllyrics tracks[].objectcredits tracks[].object or nullaudio - The master; null until one is uploaded.
tracks[].string or nullexternalId - Your own id for it, when you set one.
tracks[].map of stringmetadata - Your own keys and values, as you sent them.
tracks[].stringcreatedAt - ISO 8601 timestamp in UTC.
tracks[].stringupdatedAt - ISO 8601 timestamp in UTC.
tracks[].stringrevision - Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
reviewobject- Included when one release is read, created or changed.
review.string or nullsubmittedAt - ISO 8601 timestamp in UTC.
review.string or nulldecidedAt - ISO 8601 timestamp in UTC.
review.booleanautomatic - The account's automatic approval passed the release without a person.
review.string or nullnote - What review asked for when it sent the release back, or why it rejected it.
review.object[]issues review.object or nulldocumentsRequested deliveryobject- On its way to the stores, codes and store pages; included when one release is read, created or changed.
delivery.stringstatus - One of
NOT_SENT,SENT_TO_STORES,LIVE,REFUSED_BY_STORES,TAKEDOWN_REQUESTED,TAKEN_DOWN. delivery.string or nullsentAt delivery.string or nullliveAt delivery.string or nullrefusedReason delivery.object[]storeLinks delivery.object or nullsmartLink submittedAtstring or null- ISO 8601 timestamp in UTC.
approvedAtstring or null- ISO 8601 timestamp in UTC.
externalIdstring or null- Your own id for it, when you set one.
metadatamap of string- Your own keys and values, as you sent them.
createdAtstring- ISO 8601 timestamp in UTC.
updatedAtstring- ISO 8601 timestamp in UTC.
revisionstring- Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"labelId": "6731c2a1b3c4d5e6f7a8b9c0",
"title": "Night Signals",
"versionTitle": "Radio Edit",
"type": "SINGLE",
"status": "DRAFT",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"primaryGenre": "Pop",
"secondaryGenre": "Pop",
"language": "en",
"explicit": false,
"releaseDate": "2027-01-15",
"originalReleaseDate": "2026-10-01",
"copyright": {
"cLine": {
"year": 2026,
"holder": "North Records"
},
"pLine": {
"year": 2026,
"holder": "North Records"
}
},
"territories": {
"mode": "WORLDWIDE",
"codes": [
"123456"
]
},
"stores": {
"mode": "ALL",
"codes": [
"123456"
]
},
"upc": "0612345678905",
"artwork": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"width": 1,
"height": 1
},
"trackCount": 1200,
"tracks": [
{
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"position": 1,
"title": "Night Signals",
"versionTitle": "Radio Edit",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"explicit": false,
"isCover": false,
"language": "en",
"isrc": "GBXYZ2600001",
"lyrics": "…",
"credits": {
"songwriters": [],
"composers": [],
"producers": [],
"publishers": [],
"mixers": [],
"masteringEngineers": [],
"remixers": []
},
"audio": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"durationSeconds": 214,
"sampleRate": 1,
"bitDepth": 1,
"channels": 1
},
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
],
"review": {
"submittedAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"automatic": false,
"note": "Sent from our catalogue system",
"issues": [
{
"category": "…",
"message": "Sent from our catalogue system"
}
],
"documentsRequested": {
"note": "Sent from our catalogue system",
"requestedAt": "2026-11-01T09:30:00.000Z",
"fulfilled": false
}
},
"delivery": {
"status": "NOT_SENT",
"sentAt": "2026-11-01T09:30:00.000Z",
"liveAt": "2026-11-01T09:30:00.000Z",
"refusedReason": "Sent from our catalogue system",
"storeLinks": [
{
"store": "Spotify",
"url": "https://example.com/webhooks/stillmore"
}
],
"smartLink": {
"url": "https://example.com/webhooks/stillmore",
"enabled": true
}
},
"submittedAt": "2026-11-01T09:30:00.000Z",
"approvedAt": "2026-11-01T09:30:00.000Z",
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
}Errors#
| Code | What it means |
|---|---|
UPLOAD_NOT_RECEIVED | Complete was called before the file arrived at the upload address. Finish the PUT first. |
UPLOAD_SESSION_EXPIRED | From the workspace rule behind this endpoint; message says what to change. |
UPLOAD_SESSION_FORBIDDEN | From the workspace rule behind this endpoint; message says what to change. |
ARTWORK_DIMENSIONS_INVALID | From the workspace rule behind this endpoint; message says what to change. |
ARTWORK_CMYK | The cover is CMYK; stores take RGB covers only. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Fetch a cover from a link#
POST /releases/{releaseId}/artwork/import · scope releases:write
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.
Path parameters#
releaseIdstring- An id.
Body#
urlstringRequired- A link the file can be downloaded from without signing in, such as a signed storage URL. Up to 2000 characters.
fileNamestring- Overrides the name taken from the link. 1 to 255 characters.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/releases/{releaseId}/artwork/import" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/stillmore"
}'Response 202#
data holds the object below.
idstringkindstring- One of
ARTWORK,AUDIO. statusstring- One of
PENDING,RUNNING,SUCCEEDED,FAILED. releaseIdstringtrackIdstring or nullsourcestringsizeBytesnumber or nullerrorobject or nullerror.stringcode error.stringmessage createdAtstringfinishedAtstring or null
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"kind": "ARTWORK",
"status": "PENDING",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"source": "…",
"sizeBytes": 2483117,
"error": {
"code": "123456",
"message": "Sent from our catalogue system"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"finishedAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
IMPORT_URL_NOT_ALLOWED | Imports take public http or https links without credentials in them. |
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Download the cover#
GET /releases/{releaseId}/artwork · scope releases:read
Path parameters#
releaseIdstring- An id.
Headers#
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl "https://api.stillmoregroup.com/api/v1/releases/{releaseId}/artwork" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
urlstring- A signed link to download the stored file.
expiresAtstring
{
"data": {
"url": "https://example.com/webhooks/stillmore",
"expiresAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
ARTWORK_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Remove the cover#
DELETE /releases/{releaseId}/artwork · scope releases:write
Path parameters#
releaseIdstring- An id.
Headers#
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X DELETE "https://api.stillmoregroup.com/api/v1/releases/{releaseId}/artwork" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
idstringlabelIdstringtitlestringversionTitlestring or nulltypestring- One of
SINGLE,EP,ALBUM. statusstring- Where the release is, review and delivery together. One of
DRAFT,LABEL_REVIEW,IN_REVIEW,CHANGES_REQUESTED,REJECTED,APPROVED,SENT_TO_STORES,LIVE,REFUSED_BY_STORES,TAKEDOWN_REQUESTED,TAKEN_DOWN,ARCHIVED. primaryArtistIdsstring[]featuredArtistIdsstring[]
Show 66 more fieldsHide 66 fields
primaryGenrestring or nullsecondaryGenrestring or nulllanguagestring or nullexplicitbooleanreleaseDatestring (date) or nulloriginalReleaseDatestring (date) or nullcopyrightobjectcopyright.objectcLine copyright.objectpLine territoriesobjectterritories.stringmode - One of
WORLDWIDE,CUSTOM. territories.string[]codes storesobjectstores.stringmode - One of
ALL,CUSTOM. stores.string[]codes upcstring or nullartworkobject or null- The cover; null until one is uploaded.
artwork.stringstatus - One of
PENDING_UPLOAD,UPLOADED,VERIFIED,FAILED,DELETED. artwork.string or nullfileName artwork.string or nullmimeType artwork.number or nullsizeBytes artwork.string or nulluploadedAt - ISO 8601 timestamp in UTC.
artwork.number or nullwidth artwork.number or nullheight trackCountinteger- From -9007199254740991 to 9007199254740991.
tracksobject[]- Included when one release is read, created or changed.
tracks[].stringid tracks[].stringreleaseId tracks[].integerposition - From -9007199254740991 to 9007199254740991.
tracks[].stringtitle tracks[].string or nullversionTitle tracks[].string[]primaryArtistIds tracks[].string[]featuredArtistIds tracks[].booleanexplicit tracks[].booleanisCover tracks[].string or nulllanguage tracks[].string or nullisrc tracks[].string or nulllyrics tracks[].objectcredits tracks[].object or nullaudio - The master; null until one is uploaded.
tracks[].string or nullexternalId - Your own id for it, when you set one.
tracks[].map of stringmetadata - Your own keys and values, as you sent them.
tracks[].stringcreatedAt - ISO 8601 timestamp in UTC.
tracks[].stringupdatedAt - ISO 8601 timestamp in UTC.
tracks[].stringrevision - Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
reviewobject- Included when one release is read, created or changed.
review.string or nullsubmittedAt - ISO 8601 timestamp in UTC.
review.string or nulldecidedAt - ISO 8601 timestamp in UTC.
review.booleanautomatic - The account's automatic approval passed the release without a person.
review.string or nullnote - What review asked for when it sent the release back, or why it rejected it.
review.object[]issues review.object or nulldocumentsRequested deliveryobject- On its way to the stores, codes and store pages; included when one release is read, created or changed.
delivery.stringstatus - One of
NOT_SENT,SENT_TO_STORES,LIVE,REFUSED_BY_STORES,TAKEDOWN_REQUESTED,TAKEN_DOWN. delivery.string or nullsentAt delivery.string or nullliveAt delivery.string or nullrefusedReason delivery.object[]storeLinks delivery.object or nullsmartLink submittedAtstring or null- ISO 8601 timestamp in UTC.
approvedAtstring or null- ISO 8601 timestamp in UTC.
externalIdstring or null- Your own id for it, when you set one.
metadatamap of string- Your own keys and values, as you sent them.
createdAtstring- ISO 8601 timestamp in UTC.
updatedAtstring- ISO 8601 timestamp in UTC.
revisionstring- Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"labelId": "6731c2a1b3c4d5e6f7a8b9c0",
"title": "Night Signals",
"versionTitle": "Radio Edit",
"type": "SINGLE",
"status": "DRAFT",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"primaryGenre": "Pop",
"secondaryGenre": "Pop",
"language": "en",
"explicit": false,
"releaseDate": "2027-01-15",
"originalReleaseDate": "2026-10-01",
"copyright": {
"cLine": {
"year": 2026,
"holder": "North Records"
},
"pLine": {
"year": 2026,
"holder": "North Records"
}
},
"territories": {
"mode": "WORLDWIDE",
"codes": [
"123456"
]
},
"stores": {
"mode": "ALL",
"codes": [
"123456"
]
},
"upc": "0612345678905",
"artwork": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"width": 1,
"height": 1
},
"trackCount": 1200,
"tracks": [
{
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"position": 1,
"title": "Night Signals",
"versionTitle": "Radio Edit",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"explicit": false,
"isCover": false,
"language": "en",
"isrc": "GBXYZ2600001",
"lyrics": "…",
"credits": {
"songwriters": [],
"composers": [],
"producers": [],
"publishers": [],
"mixers": [],
"masteringEngineers": [],
"remixers": []
},
"audio": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"durationSeconds": 214,
"sampleRate": 1,
"bitDepth": 1,
"channels": 1
},
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
],
"review": {
"submittedAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"automatic": false,
"note": "Sent from our catalogue system",
"issues": [
{
"category": "…",
"message": "Sent from our catalogue system"
}
],
"documentsRequested": {
"note": "Sent from our catalogue system",
"requestedAt": "2026-11-01T09:30:00.000Z",
"fulfilled": false
}
},
"delivery": {
"status": "NOT_SENT",
"sentAt": "2026-11-01T09:30:00.000Z",
"liveAt": "2026-11-01T09:30:00.000Z",
"refusedReason": "Sent from our catalogue system",
"storeLinks": [
{
"store": "Spotify",
"url": "https://example.com/webhooks/stillmore"
}
],
"smartLink": {
"url": "https://example.com/webhooks/stillmore",
"enabled": true
}
},
"submittedAt": "2026-11-01T09:30:00.000Z",
"approvedAt": "2026-11-01T09:30:00.000Z",
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
}Errors#
| Code | What it means |
|---|---|
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Start a master upload#
POST /tracks/{trackId}/audio · scope releases:write
Returns a signed address valid for an hour. Masters are WAV or FLAC, up to 500 MB.
Path parameters#
trackIdstring- An id.
Body#
fileNamestringRequired- The file's name, with its extension. 1 to 255 characters.
contentTypestringRequired- image/jpeg or image/png for covers; audio/wav or audio/flac for masters. 3 to 120 characters.
sizeBytesintegerRequired- Exact size in bytes; the PUT must send the same Content-Length.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/tracks/{trackId}/audio" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"fileName": "cover.jpg",
"contentType": "image/jpeg",
"sizeBytes": 2483117
}'Response 201#
data holds the object below.
uploadIdstringuploadUrlstring- PUT the file's bytes here.
method"PUT"headersmap of string- Send these headers with the PUT, and Content-Length equal to sizeBytes.
expiresAtstring- Upload and complete before this time.
{
"data": {
"uploadId": "6731c2a1b3c4d5e6f7a8b9c0",
"uploadUrl": "https://storage.example.com/upload/cover.jpg?signature=…",
"method": "PUT",
"headers": {
"key": "…"
},
"expiresAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
UPLOAD_RATE_LIMITED | From the workspace rule behind this endpoint; message says what to change. |
INVALID_ARTWORK_FILE_TYPE | From the workspace rule behind this endpoint; message says what to change. |
INVALID_AUDIO_FILE_TYPE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Finish a master upload#
POST /tracks/{trackId}/audio/complete · scope releases:write
Checks the stored file (it must really be WAV or FLAC), reads its duration, sample rate and bit depth, and starts the copyright scan.
Path parameters#
trackIdstring- An id.
Body#
uploadIdstringRequired- An id.
durationSecondsnumber- From 0 to 21600.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/tracks/{trackId}/audio/complete" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"uploadId": "6731c2a1b3c4d5e6f7a8b9c0"
}'Response 200#
data holds the object below.
idstringreleaseIdstringpositioninteger- From -9007199254740991 to 9007199254740991.
titlestringversionTitlestring or nullprimaryArtistIdsstring[]featuredArtistIdsstring[]explicitboolean
Show 27 more fieldsHide 27 fields
isCoverbooleanlanguagestring or nullisrcstring or nulllyricsstring or nullcreditsobjectcredits.string[]songwriters credits.string[]composers credits.string[]producers credits.string[]publishers credits.string[]mixers credits.string[]masteringEngineers credits.string[]remixers audioobject or null- The master; null until one is uploaded.
audio.stringstatus - One of
PENDING_UPLOAD,UPLOADED,VERIFIED,FAILED,DELETED. audio.string or nullfileName audio.string or nullmimeType audio.number or nullsizeBytes audio.string or nulluploadedAt - ISO 8601 timestamp in UTC.
audio.number or nulldurationSeconds audio.number or nullsampleRate audio.number or nullbitDepth audio.number or nullchannels externalIdstring or null- Your own id for it, when you set one.
metadatamap of string- Your own keys and values, as you sent them.
createdAtstring- ISO 8601 timestamp in UTC.
updatedAtstring- ISO 8601 timestamp in UTC.
revisionstring- Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"position": 1,
"title": "Night Signals",
"versionTitle": "Radio Edit",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"explicit": false,
"isCover": false,
"language": "en",
"isrc": "GBXYZ2600001",
"lyrics": "…",
"credits": {
"songwriters": [
"…"
],
"composers": [
"…"
],
"producers": [
"…"
],
"publishers": [
"…"
],
"mixers": [
"…"
],
"masteringEngineers": [
"…"
],
"remixers": [
"…"
]
},
"audio": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"durationSeconds": 214,
"sampleRate": 1,
"bitDepth": 1,
"channels": 1
},
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
}Errors#
| Code | What it means |
|---|---|
UPLOAD_NOT_RECEIVED | Complete was called before the file arrived at the upload address. Finish the PUT first. |
UPLOAD_SESSION_EXPIRED | From the workspace rule behind this endpoint; message says what to change. |
UPLOAD_SESSION_FORBIDDEN | From the workspace rule behind this endpoint; message says what to change. |
ARTWORK_DIMENSIONS_INVALID | From the workspace rule behind this endpoint; message says what to change. |
ARTWORK_CMYK | The cover is CMYK; stores take RGB covers only. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Fetch a master from a link#
POST /tracks/{trackId}/audio/import · scope releases:write
Path parameters#
trackIdstring- An id.
Body#
urlstringRequired- A link the file can be downloaded from without signing in, such as a signed storage URL. Up to 2000 characters.
fileNamestring- Overrides the name taken from the link. 1 to 255 characters.
Headers#
Idempotency-Key- Any unique value, such as a UUID: a retry with the same key and body gets the first answer again for 24 hours.
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X POST "https://api.stillmoregroup.com/api/v1/tracks/{trackId}/audio/import" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhooks/stillmore"
}'Response 202#
data holds the object below.
idstringkindstring- One of
ARTWORK,AUDIO. statusstring- One of
PENDING,RUNNING,SUCCEEDED,FAILED. releaseIdstringtrackIdstring or nullsourcestringsizeBytesnumber or nullerrorobject or nullerror.stringcode error.stringmessage createdAtstringfinishedAtstring or null
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"kind": "ARTWORK",
"status": "PENDING",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"source": "…",
"sizeBytes": 2483117,
"error": {
"code": "123456",
"message": "Sent from our catalogue system"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"finishedAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
IMPORT_URL_NOT_ALLOWED | Imports take public http or https links without credentials in them. |
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Download the master#
GET /tracks/{trackId}/audio · scope releases:read
Path parameters#
trackIdstring- An id.
Headers#
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl "https://api.stillmoregroup.com/api/v1/tracks/{trackId}/audio" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
urlstring- A signed link to download the stored file.
expiresAtstring
{
"data": {
"url": "https://example.com/webhooks/stillmore",
"expiresAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
AUDIO_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Remove the master#
DELETE /tracks/{trackId}/audio · scope releases:write
Path parameters#
trackIdstring- An id.
Headers#
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl -X DELETE "https://api.stillmoregroup.com/api/v1/tracks/{trackId}/audio" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
idstringreleaseIdstringpositioninteger- From -9007199254740991 to 9007199254740991.
titlestringversionTitlestring or nullprimaryArtistIdsstring[]featuredArtistIdsstring[]explicitboolean
Show 27 more fieldsHide 27 fields
isCoverbooleanlanguagestring or nullisrcstring or nulllyricsstring or nullcreditsobjectcredits.string[]songwriters credits.string[]composers credits.string[]producers credits.string[]publishers credits.string[]mixers credits.string[]masteringEngineers credits.string[]remixers audioobject or null- The master; null until one is uploaded.
audio.stringstatus - One of
PENDING_UPLOAD,UPLOADED,VERIFIED,FAILED,DELETED. audio.string or nullfileName audio.string or nullmimeType audio.number or nullsizeBytes audio.string or nulluploadedAt - ISO 8601 timestamp in UTC.
audio.number or nulldurationSeconds audio.number or nullsampleRate audio.number or nullbitDepth audio.number or nullchannels externalIdstring or null- Your own id for it, when you set one.
metadatamap of string- Your own keys and values, as you sent them.
createdAtstring- ISO 8601 timestamp in UTC.
updatedAtstring- ISO 8601 timestamp in UTC.
revisionstring- Changes whenever the record does; send it back in If-Match to refuse an update when someone else changed it first.
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"position": 1,
"title": "Night Signals",
"versionTitle": "Radio Edit",
"primaryArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"featuredArtistIds": [
"6731c2a1b3c4d5e6f7a8b9c0"
],
"explicit": false,
"isCover": false,
"language": "en",
"isrc": "GBXYZ2600001",
"lyrics": "…",
"credits": {
"songwriters": [
"…"
],
"composers": [
"…"
],
"producers": [
"…"
],
"publishers": [
"…"
],
"mixers": [
"…"
],
"masteringEngineers": [
"…"
],
"remixers": [
"…"
]
},
"audio": {
"status": "PENDING_UPLOAD",
"fileName": "cover.jpg",
"mimeType": "…",
"sizeBytes": 2483117,
"uploadedAt": "2026-11-01T09:30:00.000Z",
"durationSeconds": 214,
"sampleRate": 1,
"bitDepth": 1,
"channels": 1
},
"externalId": "6731c2a1b3c4d5e6f7a8b9c0",
"metadata": {
"catalogueId": "1042"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"updatedAt": "2026-11-01T09:30:00.000Z",
"revision": "…"
}
}Errors#
| Code | What it means |
|---|---|
RELEASE_NOT_EDITABLE | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Follow a file import#
GET /imports/{importId} · scope releases:read
Path parameters#
importIdstring- An id.
Headers#
Stillmore-Organization- A sub-label to act for, when the key may (see Sub-labels).
Example request#
curl "https://api.stillmoregroup.com/api/v1/imports/{importId}" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
idstringkindstring- One of
ARTWORK,AUDIO. statusstring- One of
PENDING,RUNNING,SUCCEEDED,FAILED. releaseIdstringtrackIdstring or nullsourcestringsizeBytesnumber or nullerrorobject or nullerror.stringcode error.stringmessage createdAtstringfinishedAtstring or null
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"kind": "ARTWORK",
"status": "PENDING",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"source": "…",
"sizeBytes": 2483117,
"error": {
"code": "123456",
"message": "Sent from our catalogue system"
},
"createdAt": "2026-11-01T09:30:00.000Z",
"finishedAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
IMPORT_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.