Skip to content

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.

EndpointWhat it does
POST /releases/{releaseId}/artworkStart a cover upload
POST /releases/{releaseId}/artwork/completeFinish a cover upload
POST /releases/{releaseId}/artwork/importFetch a cover from a link
GET /releases/{releaseId}/artworkDownload the cover
DELETE /releases/{releaseId}/artworkRemove the cover
POST /tracks/{trackId}/audioStart a master upload
POST /tracks/{trackId}/audio/completeFinish a master upload
POST /tracks/{trackId}/audio/importFetch a master from a link
GET /tracks/{trackId}/audioDownload the master
DELETE /tracks/{trackId}/audioRemove 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.

uploadIdstring
uploadUrlstring
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.
Example response
{
  "data": {
    "uploadId": "6731c2a1b3c4d5e6f7a8b9c0",
    "uploadUrl": "https://storage.example.com/upload/cover.jpg?signature=…",
    "method": "PUT",
    "headers": {
      "key": "…"
    },
    "expiresAt": "2026-11-01T09:30:00.000Z"
  }
}

Errors#

CodeWhat it means
RELEASE_NOT_EDITABLEFrom the workspace rule behind this endpoint; message says what to change.
UPLOAD_RATE_LIMITEDFrom the workspace rule behind this endpoint; message says what to change.
INVALID_ARTWORK_FILE_TYPEFrom the workspace rule behind this endpoint; message says what to change.
INVALID_AUDIO_FILE_TYPEFrom 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.

idstring
labelIdstring
titlestring
versionTitlestring or null
typestring
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 fields
primaryGenrestring or null
secondaryGenrestring or null
languagestring or null
explicitboolean
releaseDatestring (date) or null
originalReleaseDatestring (date) or null
copyrightobject
copyright.cLineobject
copyright.pLineobject
territoriesobject
territories.modestring
One of WORLDWIDE, CUSTOM.
territories.codesstring[]
storesobject
stores.modestring
One of ALL, CUSTOM.
stores.codesstring[]
upcstring or null
artworkobject or null
The cover; null until one is uploaded.
artwork.statusstring
One of PENDING_UPLOAD, UPLOADED, VERIFIED, FAILED, DELETED.
artwork.fileNamestring or null
artwork.mimeTypestring or null
artwork.sizeBytesnumber or null
artwork.uploadedAtstring or null
ISO 8601 timestamp in UTC.
artwork.widthnumber or null
artwork.heightnumber or null
trackCountinteger
From -9007199254740991 to 9007199254740991.
tracksobject[]
Included when one release is read, created or changed.
tracks[].idstring
tracks[].releaseIdstring
tracks[].positioninteger
From -9007199254740991 to 9007199254740991.
tracks[].titlestring
tracks[].versionTitlestring or null
tracks[].primaryArtistIdsstring[]
tracks[].featuredArtistIdsstring[]
tracks[].explicitboolean
tracks[].isCoverboolean
tracks[].languagestring or null
tracks[].isrcstring or null
tracks[].lyricsstring or null
tracks[].creditsobject
tracks[].audioobject or null
The master; null until one is uploaded.
tracks[].externalIdstring or null
Your own id for it, when you set one.
tracks[].metadatamap of string
Your own keys and values, as you sent them.
tracks[].createdAtstring
ISO 8601 timestamp in UTC.
tracks[].updatedAtstring
ISO 8601 timestamp in UTC.
tracks[].revisionstring
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.submittedAtstring or null
ISO 8601 timestamp in UTC.
review.decidedAtstring or null
ISO 8601 timestamp in UTC.
review.automaticboolean
The account's automatic approval passed the release without a person.
review.notestring or null
What review asked for when it sent the release back, or why it rejected it.
review.issuesobject[]
review.documentsRequestedobject or null
deliveryobject
On its way to the stores, codes and store pages; included when one release is read, created or changed.
delivery.statusstring
One of NOT_SENT, SENT_TO_STORES, LIVE, REFUSED_BY_STORES, TAKEDOWN_REQUESTED, TAKEN_DOWN.
delivery.sentAtstring or null
delivery.liveAtstring or null
delivery.refusedReasonstring or null
delivery.storeLinksobject[]
delivery.smartLinkobject or null
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.
Example response
{
  "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#

CodeWhat it means
UPLOAD_NOT_RECEIVEDComplete was called before the file arrived at the upload address. Finish the PUT first.
UPLOAD_SESSION_EXPIREDFrom the workspace rule behind this endpoint; message says what to change.
UPLOAD_SESSION_FORBIDDENFrom the workspace rule behind this endpoint; message says what to change.
ARTWORK_DIMENSIONS_INVALIDFrom the workspace rule behind this endpoint; message says what to change.
ARTWORK_CMYKThe 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.

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.

idstring
kindstring
One of ARTWORK, AUDIO.
statusstring
One of PENDING, RUNNING, SUCCEEDED, FAILED.
releaseIdstring
trackIdstring or null
sourcestring
sizeBytesnumber or null
errorobject or null
error.codestring
error.messagestring
createdAtstring
finishedAtstring or null
Example response
{
  "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#

CodeWhat it means
IMPORT_URL_NOT_ALLOWEDImports take public http or https links without credentials in them.
RELEASE_NOT_EDITABLEFrom 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
Example response
{
  "data": {
    "url": "https://example.com/webhooks/stillmore",
    "expiresAt": "2026-11-01T09:30:00.000Z"
  }
}

Errors#

CodeWhat it means
ARTWORK_NOT_FOUNDFrom 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.

idstring
labelIdstring
titlestring
versionTitlestring or null
typestring
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 fields
primaryGenrestring or null
secondaryGenrestring or null
languagestring or null
explicitboolean
releaseDatestring (date) or null
originalReleaseDatestring (date) or null
copyrightobject
copyright.cLineobject
copyright.pLineobject
territoriesobject
territories.modestring
One of WORLDWIDE, CUSTOM.
territories.codesstring[]
storesobject
stores.modestring
One of ALL, CUSTOM.
stores.codesstring[]
upcstring or null
artworkobject or null
The cover; null until one is uploaded.
artwork.statusstring
One of PENDING_UPLOAD, UPLOADED, VERIFIED, FAILED, DELETED.
artwork.fileNamestring or null
artwork.mimeTypestring or null
artwork.sizeBytesnumber or null
artwork.uploadedAtstring or null
ISO 8601 timestamp in UTC.
artwork.widthnumber or null
artwork.heightnumber or null
trackCountinteger
From -9007199254740991 to 9007199254740991.
tracksobject[]
Included when one release is read, created or changed.
tracks[].idstring
tracks[].releaseIdstring
tracks[].positioninteger
From -9007199254740991 to 9007199254740991.
tracks[].titlestring
tracks[].versionTitlestring or null
tracks[].primaryArtistIdsstring[]
tracks[].featuredArtistIdsstring[]
tracks[].explicitboolean
tracks[].isCoverboolean
tracks[].languagestring or null
tracks[].isrcstring or null
tracks[].lyricsstring or null
tracks[].creditsobject
tracks[].audioobject or null
The master; null until one is uploaded.
tracks[].externalIdstring or null
Your own id for it, when you set one.
tracks[].metadatamap of string
Your own keys and values, as you sent them.
tracks[].createdAtstring
ISO 8601 timestamp in UTC.
tracks[].updatedAtstring
ISO 8601 timestamp in UTC.
tracks[].revisionstring
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.submittedAtstring or null
ISO 8601 timestamp in UTC.
review.decidedAtstring or null
ISO 8601 timestamp in UTC.
review.automaticboolean
The account's automatic approval passed the release without a person.
review.notestring or null
What review asked for when it sent the release back, or why it rejected it.
review.issuesobject[]
review.documentsRequestedobject or null
deliveryobject
On its way to the stores, codes and store pages; included when one release is read, created or changed.
delivery.statusstring
One of NOT_SENT, SENT_TO_STORES, LIVE, REFUSED_BY_STORES, TAKEDOWN_REQUESTED, TAKEN_DOWN.
delivery.sentAtstring or null
delivery.liveAtstring or null
delivery.refusedReasonstring or null
delivery.storeLinksobject[]
delivery.smartLinkobject or null
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.
Example response
{
  "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#

CodeWhat it means
RELEASE_NOT_EDITABLEFrom 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.

uploadIdstring
uploadUrlstring
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.
Example response
{
  "data": {
    "uploadId": "6731c2a1b3c4d5e6f7a8b9c0",
    "uploadUrl": "https://storage.example.com/upload/cover.jpg?signature=…",
    "method": "PUT",
    "headers": {
      "key": "…"
    },
    "expiresAt": "2026-11-01T09:30:00.000Z"
  }
}

Errors#

CodeWhat it means
RELEASE_NOT_EDITABLEFrom the workspace rule behind this endpoint; message says what to change.
UPLOAD_RATE_LIMITEDFrom the workspace rule behind this endpoint; message says what to change.
INVALID_ARTWORK_FILE_TYPEFrom the workspace rule behind this endpoint; message says what to change.
INVALID_AUDIO_FILE_TYPEFrom 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.

idstring
releaseIdstring
positioninteger
From -9007199254740991 to 9007199254740991.
titlestring
versionTitlestring or null
primaryArtistIdsstring[]
featuredArtistIdsstring[]
explicitboolean
Show 27 more fields
isCoverboolean
languagestring or null
isrcstring or null
lyricsstring or null
creditsobject
credits.songwritersstring[]
credits.composersstring[]
credits.producersstring[]
credits.publishersstring[]
credits.mixersstring[]
credits.masteringEngineersstring[]
credits.remixersstring[]
audioobject or null
The master; null until one is uploaded.
audio.statusstring
One of PENDING_UPLOAD, UPLOADED, VERIFIED, FAILED, DELETED.
audio.fileNamestring or null
audio.mimeTypestring or null
audio.sizeBytesnumber or null
audio.uploadedAtstring or null
ISO 8601 timestamp in UTC.
audio.durationSecondsnumber or null
audio.sampleRatenumber or null
audio.bitDepthnumber or null
audio.channelsnumber or null
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.
Example response
{
  "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#

CodeWhat it means
UPLOAD_NOT_RECEIVEDComplete was called before the file arrived at the upload address. Finish the PUT first.
UPLOAD_SESSION_EXPIREDFrom the workspace rule behind this endpoint; message says what to change.
UPLOAD_SESSION_FORBIDDENFrom the workspace rule behind this endpoint; message says what to change.
ARTWORK_DIMENSIONS_INVALIDFrom the workspace rule behind this endpoint; message says what to change.
ARTWORK_CMYKThe 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.

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.

idstring
kindstring
One of ARTWORK, AUDIO.
statusstring
One of PENDING, RUNNING, SUCCEEDED, FAILED.
releaseIdstring
trackIdstring or null
sourcestring
sizeBytesnumber or null
errorobject or null
error.codestring
error.messagestring
createdAtstring
finishedAtstring or null
Example response
{
  "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#

CodeWhat it means
IMPORT_URL_NOT_ALLOWEDImports take public http or https links without credentials in them.
RELEASE_NOT_EDITABLEFrom 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
Example response
{
  "data": {
    "url": "https://example.com/webhooks/stillmore",
    "expiresAt": "2026-11-01T09:30:00.000Z"
  }
}

Errors#

CodeWhat it means
AUDIO_NOT_FOUNDFrom 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.

idstring
releaseIdstring
positioninteger
From -9007199254740991 to 9007199254740991.
titlestring
versionTitlestring or null
primaryArtistIdsstring[]
featuredArtistIdsstring[]
explicitboolean
Show 27 more fields
isCoverboolean
languagestring or null
isrcstring or null
lyricsstring or null
creditsobject
credits.songwritersstring[]
credits.composersstring[]
credits.producersstring[]
credits.publishersstring[]
credits.mixersstring[]
credits.masteringEngineersstring[]
credits.remixersstring[]
audioobject or null
The master; null until one is uploaded.
audio.statusstring
One of PENDING_UPLOAD, UPLOADED, VERIFIED, FAILED, DELETED.
audio.fileNamestring or null
audio.mimeTypestring or null
audio.sizeBytesnumber or null
audio.uploadedAtstring or null
ISO 8601 timestamp in UTC.
audio.durationSecondsnumber or null
audio.sampleRatenumber or null
audio.bitDepthnumber or null
audio.channelsnumber or null
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.
Example response
{
  "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#

CodeWhat it means
RELEASE_NOT_EDITABLEFrom 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.

idstring
kindstring
One of ARTWORK, AUDIO.
statusstring
One of PENDING, RUNNING, SUCCEEDED, FAILED.
releaseIdstring
trackIdstring or null
sourcestring
sizeBytesnumber or null
errorobject or null
error.codestring
error.messagestring
createdAtstring
finishedAtstring or null
Example response
{
  "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#

CodeWhat it means
IMPORT_NOT_FOUNDFrom 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.