Stems
Split a completed Suno track into separate vocals and instrumental files.
POST /v2/music/suno/action — action: "stems"
Splits one of the parent job's tracks into 2 stems: an isolated vocal track and an instrumental track. Useful for remixing, karaoke versions, or re-using a generation's backing track.
Select the track to split with index (1 or 2) or with the trackId
from the parent's result.tracks[].id — exactly one of the two.
Stems results are plain audio files, not Suno songs. Unlike extend, cover, and add-vocals, a stems job's tracks have the fixed IDs
"vocals"and"instrumental"instead of Suno clip IDs, and a stems job cannot be the parent of any further follow-up action (such requests return409). Run stems last in a chain — or run it on the original job at any time.
Request
| Parameter | Type | Required | Description |
|---|---|---|---|
parentJobId | string (uuid) | Yes | ID of the completed suno job to act on |
action | string | Yes | "stems" |
index | number | One of index/trackId | Which of the parent's tracks to split: 1 or 2 |
trackId | string | One of index/trackId | Track ID from the parent's result.tracks[].id |
webhookUrl | string | No | HTTPS URL that receives a JSON POST when the job reaches a subscribed event — see Webhooks for payload formats |
webhookEvents | string[] | No | Events to be notified about: "progress", "completed", "failed". Defaults to ["completed", "failed"] when webhookUrl is set |
There are no other parameters — stems is a pure split of the source audio.
Credits
11 credits per stems split.
Example result
Once the job is COMPLETED, the result object on
GET /v2/jobs/:id contains exactly 2 tracks:
{
"tracks": [
{
"id": "vocals",
"audioUrl": "https://cdn2.apiframe.ai/audio/d4e5f6a7-b8c9-0123-def4-567890123456-0.mp3",
"imageUrl": null,
"title": "Vocals",
"tags": null,
"duration": 142.8
},
{
"id": "instrumental",
"audioUrl": "https://cdn2.apiframe.ai/audio/d4e5f6a7-b8c9-0123-def4-567890123456-1.mp3",
"imageUrl": null,
"title": "Instrumental",
"tags": null,
"duration": 142.8
}
]
}Both stems cover the full length of the source track.
Code examples
curl -X POST https://api.apiframe.ai/v2/music/suno/action \
-H "X-API-Key: afk_your_api_key_here" \
-H "Content-Type: application/json" \
-d '{
"parentJobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"action": "stems",
"index": 1
}'import requests
response = requests.post(
"https://api.apiframe.ai/v2/music/suno/action",
headers={
"X-API-Key": "afk_your_api_key_here",
"Content-Type": "application/json",
},
json={
"parentJobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"action": "stems",
"index": 1,
},
)
print(response.json())const response = await fetch("https://api.apiframe.ai/v2/music/suno/action", {
method: "POST",
headers: {
"X-API-Key": "afk_your_api_key_here",
"Content-Type": "application/json",
},
body: JSON.stringify({
parentJobId: "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
action: "stems",
index: 1,
}),
});
console.log(await response.json());body := `{
"parentJobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"action": "stems",
"index": 1
}`
req, _ := http.NewRequest("POST", "https://api.apiframe.ai/v2/music/suno/action",
strings.NewReader(body))
req.Header.Set("X-API-Key", "afk_your_api_key_here")
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)Try it
/v2/music/suno/actionTry it