API reference
Cover licences
Licences for cover songs: asking for one, documents and cancelling.
On this page
Base address https://api.stillmoregroup.com/api/v1. Every answer is JSON; errors have one shape.
| Endpoint | What it does |
|---|---|
GET /cover-licenses | Cover licence requests |
GET /cover-licenses/{licenseId} | One request |
POST /cover-licenses | Ask for a cover licence |
POST /cover-licenses/{licenseId}/document | Start uploading the licence file |
POST /cover-licenses/{licenseId}/document/complete | Finish uploading the licence file |
POST /cover-licenses/{licenseId}/cancel | Cancel a request not sent in yet |
Cover licence requests#
GET /cover-licenses · scope releases:read
Query parameters#
limitinteger- From 1 to 100. Default
25. cursorstring- Up to 200 characters.
trackIdstring- An id.
releaseIdstring- An id.
statusstring- One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED.
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/cover-licenses?limit=25" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
A page: data holds the items below, hasMore says whether another page follows, and nextCursor is the cursor for it.
idstringnumberstring- Our reference, e.g. CVL-2026-0042.
releaseIdstringtrackIdstringmodestring- OWN: you send in a licence you have; PURCHASE: Stillmore Group gets one for you. One of
PURCHASE,OWN. statusstring- One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED. originalobject- The song being covered.
original.stringtitle
Show 17 more fieldsHide 17 fields
original.stringartist original.string[]writers original.string or nullpublisher original.string or nullisrc original.string or nulllink notesstring or nullpricestring- USD; 0.00 for OWN.
payWithstring or null- One of
CARD,WALLET. documentobject or null- The licence file on the request.
document.stringfileName document.string or nulluploadedAt licenseRefstring or nullreasonstring or null- Why it was refused.
paidAtstring or nulldueAtstring or nulldecidedAtstring or nullcreatedAtstring
{
"data": [
{
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"number": "…",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"status": "AWAITING_PAYMENT",
"original": {
"title": "Night Signals",
"artist": "…",
"writers": [
"…"
],
"publisher": "…",
"isrc": "GBXYZ2600001",
"link": "https://example.com/webhooks/stillmore"
},
"notes": "Sent from our catalogue system",
"price": "250.00",
"payWith": "CARD",
"document": {
"fileName": "cover.jpg",
"uploadedAt": "2026-11-01T09:30:00.000Z"
},
"licenseRef": "…",
"reason": "Sent from our catalogue system",
"paidAt": "2026-11-01T09:30:00.000Z",
"dueAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"createdAt": "2026-11-01T09:30:00.000Z"
}
],
"hasMore": false,
"nextCursor": null
}One request#
GET /cover-licenses/{licenseId} · scope releases:read
Path parameters#
licenseIdstring- 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/cover-licenses/{licenseId}" \
-H "Authorization: Bearer $STILLMORE_API_KEY"Response 200#
data holds the object below.
idstringnumberstring- Our reference, e.g. CVL-2026-0042.
releaseIdstringtrackIdstringmodestring- OWN: you send in a licence you have; PURCHASE: Stillmore Group gets one for you. One of
PURCHASE,OWN. statusstring- One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED. originalobject- The song being covered.
original.stringtitle
Show 17 more fieldsHide 17 fields
original.stringartist original.string[]writers original.string or nullpublisher original.string or nullisrc original.string or nulllink notesstring or nullpricestring- USD; 0.00 for OWN.
payWithstring or null- One of
CARD,WALLET. documentobject or null- The licence file on the request.
document.stringfileName document.string or nulluploadedAt licenseRefstring or nullreasonstring or null- Why it was refused.
paidAtstring or nulldueAtstring or nulldecidedAtstring or nullcreatedAtstring
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"number": "…",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"status": "AWAITING_PAYMENT",
"original": {
"title": "Night Signals",
"artist": "…",
"writers": [
"…"
],
"publisher": "…",
"isrc": "GBXYZ2600001",
"link": "https://example.com/webhooks/stillmore"
},
"notes": "Sent from our catalogue system",
"price": "250.00",
"payWith": "CARD",
"document": {
"fileName": "cover.jpg",
"uploadedAt": "2026-11-01T09:30:00.000Z"
},
"licenseRef": "…",
"reason": "Sent from our catalogue system",
"paidAt": "2026-11-01T09:30:00.000Z",
"dueAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"createdAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
COVER_LICENSE_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.
Ask for a cover licence#
POST /cover-licenses · scope releases:write
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.
Body#
trackIdstringRequired- A track marked as a cover (isCover: true). An id.
modestringRequired- One of
PURCHASE,OWN. originalobjectRequired- The song being covered, as its rights holders know it.
original.stringRequiredtitle - 1 to 160 characters.
original.stringRequiredartist - 1 to 160 characters.
original.string[]Requiredwriters - 1 to 20 items.
original.stringpublisher - Up to 160 characters.
original.stringisrc - Up to 20 characters.
original.stringlink - Up to 500 characters.
payWithstring- PURCHASE only: WALLET takes the price from the balance at once; CARD answers with a checkout link a person pays. One of
CARD,WALLET. notesstring- Up to 2000 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/cover-licenses" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"payWith": "WALLET",
"original": {
"title": "Paper Moons",
"artist": "The Lanterns",
"writers": [
"Ada Quinn"
]
}
}'Response 201#
data holds the object below.
licenseobjectlicense.stringid license.stringnumber - Our reference, e.g. CVL-2026-0042.
license.stringreleaseId license.stringtrackId license.stringmode - OWN: you send in a licence you have; PURCHASE: Stillmore Group gets one for you. One of
PURCHASE,OWN. license.stringstatus - One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED. license.objectoriginal - The song being covered.
Show 11 more fieldsHide 11 fields
license.string or nullnotes license.stringprice - USD; 0.00 for OWN.
license.string or nullpayWith - One of
CARD,WALLET. license.object or nulldocument - The licence file on the request.
license.string or nulllicenseRef license.string or nullreason - Why it was refused.
license.string or nullpaidAt license.string or nulldueAt license.string or nulldecidedAt license.stringcreatedAt checkoutUrlstring or null- CARD purchases: where a person pays; the request starts once paid.
{
"data": {
"license": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"number": "…",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"status": "AWAITING_PAYMENT",
"original": {
"title": "Night Signals",
"artist": "…",
"writers": [
"…"
],
"publisher": "…",
"isrc": "GBXYZ2600001",
"link": "https://example.com/webhooks/stillmore"
},
"notes": "Sent from our catalogue system",
"price": "250.00",
"payWith": "CARD",
"document": {
"fileName": "cover.jpg",
"uploadedAt": "2026-11-01T09:30:00.000Z"
},
"licenseRef": "…",
"reason": "Sent from our catalogue system",
"paidAt": "2026-11-01T09:30:00.000Z",
"dueAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"createdAt": "2026-11-01T09:30:00.000Z"
},
"checkoutUrl": "https://example.com/webhooks/stillmore"
}
}Errors#
| Code | What it means |
|---|---|
TRACK_NOT_A_COVER | From the workspace rule behind this endpoint; message says what to change. |
COVER_LICENSE_EXISTS | From the workspace rule behind this endpoint; message says what to change. |
COVER_LICENSING_CLOSED | From the workspace rule behind this endpoint; message says what to change. |
INSUFFICIENT_BALANCE | 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 uploading the licence file#
POST /cover-licenses/{licenseId}/document · scope releases:write
OWN requests: PDF, Word, JPEG or PNG up to 20 MB, also to answer a refusal.
Path parameters#
licenseIdstring- 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/cover-licenses/{licenseId}/document" \
-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 |
|---|---|
COVER_LICENSE_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
COVER_LICENSE_STATE | 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 uploading the licence file#
POST /cover-licenses/{licenseId}/document/complete · scope releases:write
The request goes to Stillmore Group (PENDING).
Path parameters#
licenseIdstring- 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/cover-licenses/{licenseId}/document/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.
idstringnumberstring- Our reference, e.g. CVL-2026-0042.
releaseIdstringtrackIdstringmodestring- OWN: you send in a licence you have; PURCHASE: Stillmore Group gets one for you. One of
PURCHASE,OWN. statusstring- One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED. originalobject- The song being covered.
original.stringtitle
Show 17 more fieldsHide 17 fields
original.stringartist original.string[]writers original.string or nullpublisher original.string or nullisrc original.string or nulllink notesstring or nullpricestring- USD; 0.00 for OWN.
payWithstring or null- One of
CARD,WALLET. documentobject or null- The licence file on the request.
document.stringfileName document.string or nulluploadedAt licenseRefstring or nullreasonstring or null- Why it was refused.
paidAtstring or nulldueAtstring or nulldecidedAtstring or nullcreatedAtstring
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"number": "…",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"status": "AWAITING_PAYMENT",
"original": {
"title": "Night Signals",
"artist": "…",
"writers": [
"…"
],
"publisher": "…",
"isrc": "GBXYZ2600001",
"link": "https://example.com/webhooks/stillmore"
},
"notes": "Sent from our catalogue system",
"price": "250.00",
"payWith": "CARD",
"document": {
"fileName": "cover.jpg",
"uploadedAt": "2026-11-01T09:30:00.000Z"
},
"licenseRef": "…",
"reason": "Sent from our catalogue system",
"paidAt": "2026-11-01T09:30:00.000Z",
"dueAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"createdAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
COVER_LICENSE_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
COVER_LICENSE_STATE | From the workspace rule behind this endpoint; message says what to change. |
UPLOAD_NOT_RECEIVED | Complete was called before the file arrived at the upload address. Finish the PUT first. |
Every endpoint can also give the errors every call can give, such as VALIDATION_ERROR, INSUFFICIENT_SCOPE and RATE_LIMITED.
Cancel a request not sent in yet#
POST /cover-licenses/{licenseId}/cancel · scope releases:write
Before payment (CARD) or before the file (OWN).
Path parameters#
licenseIdstring- An id.
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/cover-licenses/{licenseId}/cancel" \
-H "Authorization: Bearer $STILLMORE_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"Response 200#
data holds the object below.
idstringnumberstring- Our reference, e.g. CVL-2026-0042.
releaseIdstringtrackIdstringmodestring- OWN: you send in a licence you have; PURCHASE: Stillmore Group gets one for you. One of
PURCHASE,OWN. statusstring- One of
AWAITING_PAYMENT,AWAITING_DOCUMENT,PENDING,IN_PROGRESS,APPROVED,REJECTED,CANCELLED. originalobject- The song being covered.
original.stringtitle
Show 17 more fieldsHide 17 fields
original.stringartist original.string[]writers original.string or nullpublisher original.string or nullisrc original.string or nulllink notesstring or nullpricestring- USD; 0.00 for OWN.
payWithstring or null- One of
CARD,WALLET. documentobject or null- The licence file on the request.
document.stringfileName document.string or nulluploadedAt licenseRefstring or nullreasonstring or null- Why it was refused.
paidAtstring or nulldueAtstring or nulldecidedAtstring or nullcreatedAtstring
{
"data": {
"id": "6731c2a1b3c4d5e6f7a8b9c0",
"number": "…",
"releaseId": "6731c2a1b3c4d5e6f7a8b9c0",
"trackId": "6731c2a1b3c4d5e6f7a8b9c0",
"mode": "PURCHASE",
"status": "AWAITING_PAYMENT",
"original": {
"title": "Night Signals",
"artist": "…",
"writers": [
"…"
],
"publisher": "…",
"isrc": "GBXYZ2600001",
"link": "https://example.com/webhooks/stillmore"
},
"notes": "Sent from our catalogue system",
"price": "250.00",
"payWith": "CARD",
"document": {
"fileName": "cover.jpg",
"uploadedAt": "2026-11-01T09:30:00.000Z"
},
"licenseRef": "…",
"reason": "Sent from our catalogue system",
"paidAt": "2026-11-01T09:30:00.000Z",
"dueAt": "2026-11-01T09:30:00.000Z",
"decidedAt": "2026-11-01T09:30:00.000Z",
"createdAt": "2026-11-01T09:30:00.000Z"
}
}Errors#
| Code | What it means |
|---|---|
COVER_LICENSE_NOT_FOUND | From the workspace rule behind this endpoint; message says what to change. |
COVER_LICENSE_STATE | 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.