curl --request POST \
--url https://api.ttapi.io/suno/v1/add-stem \
--header 'Content-Type: application/json' \
--header 'TT-API-KEY: <api-key>' \
--data '
{
"custom": false,
"mv": "chirp-v5",
"music_id": "<string>",
"gpt_description_prompt": "Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \"Under the city lights\"",
"prompt": "<string>",
"title": "<string>",
"tags": "rock, blues, hip-hop, r&b",
"negative_tags": "<string>",
"style_weight": 0.5,
"weirdness_constraint": 0.5,
"audio_weight": 0.5,
"audio_format": "mp3",
"hookUrl": "<string>",
"isStorage": true
}
'import requests
url = "https://api.ttapi.io/suno/v1/add-stem"
payload = {
"custom": False,
"mv": "chirp-v5",
"music_id": "<string>",
"gpt_description_prompt": "Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \"Under the city lights\"",
"prompt": "<string>",
"title": "<string>",
"tags": "rock, blues, hip-hop, r&b",
"negative_tags": "<string>",
"style_weight": 0.5,
"weirdness_constraint": 0.5,
"audio_weight": 0.5,
"audio_format": "mp3",
"hookUrl": "<string>",
"isStorage": True
}
headers = {
"TT-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'TT-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
custom: false,
mv: 'chirp-v5',
music_id: '<string>',
gpt_description_prompt: 'Night city lo-fi piano with rain ambience, soft vocal phrases, theme: "Under the city lights"',
prompt: '<string>',
title: '<string>',
tags: 'rock, blues, hip-hop, r&b',
negative_tags: '<string>',
style_weight: 0.5,
weirdness_constraint: 0.5,
audio_weight: 0.5,
audio_format: 'mp3',
hookUrl: '<string>',
isStorage: true
})
};
fetch('https://api.ttapi.io/suno/v1/add-stem', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ttapi.io/suno/v1/add-stem",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'custom' => false,
'mv' => 'chirp-v5',
'music_id' => '<string>',
'gpt_description_prompt' => 'Night city lo-fi piano with rain ambience, soft vocal phrases, theme: "Under the city lights"',
'prompt' => '<string>',
'title' => '<string>',
'tags' => 'rock, blues, hip-hop, r&b',
'negative_tags' => '<string>',
'style_weight' => 0.5,
'weirdness_constraint' => 0.5,
'audio_weight' => 0.5,
'audio_format' => 'mp3',
'hookUrl' => '<string>',
'isStorage' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"TT-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ttapi.io/suno/v1/add-stem"
payload := strings.NewReader("{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("TT-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ttapi.io/suno/v1/add-stem")
.header("TT-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ttapi.io/suno/v1/add-stem")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["TT-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}"
response = http.request(request)
puts response.read_body{
"status": "SUCCESS",
"message": "success",
"data": {
"jobId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}{
"status": "FAILED",
"message": "<string>",
"data": {}
}{
"status": "FAILED",
"message": "Wrong TT-API-KEY or email is not activated."
}Suno Add Stem API Reference
Use the Suno Add Stem API to layer an additional stem onto an existing Suno track, blending lyrics, style tags, and audio weight to enrich arrangements and multi-track production.
curl --request POST \
--url https://api.ttapi.io/suno/v1/add-stem \
--header 'Content-Type: application/json' \
--header 'TT-API-KEY: <api-key>' \
--data '
{
"custom": false,
"mv": "chirp-v5",
"music_id": "<string>",
"gpt_description_prompt": "Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \"Under the city lights\"",
"prompt": "<string>",
"title": "<string>",
"tags": "rock, blues, hip-hop, r&b",
"negative_tags": "<string>",
"style_weight": 0.5,
"weirdness_constraint": 0.5,
"audio_weight": 0.5,
"audio_format": "mp3",
"hookUrl": "<string>",
"isStorage": true
}
'import requests
url = "https://api.ttapi.io/suno/v1/add-stem"
payload = {
"custom": False,
"mv": "chirp-v5",
"music_id": "<string>",
"gpt_description_prompt": "Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \"Under the city lights\"",
"prompt": "<string>",
"title": "<string>",
"tags": "rock, blues, hip-hop, r&b",
"negative_tags": "<string>",
"style_weight": 0.5,
"weirdness_constraint": 0.5,
"audio_weight": 0.5,
"audio_format": "mp3",
"hookUrl": "<string>",
"isStorage": True
}
headers = {
"TT-API-KEY": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'TT-API-KEY': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
custom: false,
mv: 'chirp-v5',
music_id: '<string>',
gpt_description_prompt: 'Night city lo-fi piano with rain ambience, soft vocal phrases, theme: "Under the city lights"',
prompt: '<string>',
title: '<string>',
tags: 'rock, blues, hip-hop, r&b',
negative_tags: '<string>',
style_weight: 0.5,
weirdness_constraint: 0.5,
audio_weight: 0.5,
audio_format: 'mp3',
hookUrl: '<string>',
isStorage: true
})
};
fetch('https://api.ttapi.io/suno/v1/add-stem', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ttapi.io/suno/v1/add-stem",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'custom' => false,
'mv' => 'chirp-v5',
'music_id' => '<string>',
'gpt_description_prompt' => 'Night city lo-fi piano with rain ambience, soft vocal phrases, theme: "Under the city lights"',
'prompt' => '<string>',
'title' => '<string>',
'tags' => 'rock, blues, hip-hop, r&b',
'negative_tags' => '<string>',
'style_weight' => 0.5,
'weirdness_constraint' => 0.5,
'audio_weight' => 0.5,
'audio_format' => 'mp3',
'hookUrl' => '<string>',
'isStorage' => true
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"TT-API-KEY: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.ttapi.io/suno/v1/add-stem"
payload := strings.NewReader("{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("TT-API-KEY", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.ttapi.io/suno/v1/add-stem")
.header("TT-API-KEY", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.ttapi.io/suno/v1/add-stem")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["TT-API-KEY"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"custom\": false,\n \"mv\": \"chirp-v5\",\n \"music_id\": \"<string>\",\n \"gpt_description_prompt\": \"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \\\"Under the city lights\\\"\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"tags\": \"rock, blues, hip-hop, r&b\",\n \"negative_tags\": \"<string>\",\n \"style_weight\": 0.5,\n \"weirdness_constraint\": 0.5,\n \"audio_weight\": 0.5,\n \"audio_format\": \"mp3\",\n \"hookUrl\": \"<string>\",\n \"isStorage\": true\n}"
response = http.request(request)
puts response.read_body{
"status": "SUCCESS",
"message": "success",
"data": {
"jobId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}{
"status": "FAILED",
"message": "<string>",
"data": {}
}{
"status": "FAILED",
"message": "Wrong TT-API-KEY or email is not activated."
}Authorizations
You can obtain your API key from the TTAPI Dashboard.
Body
Whether to use custom mode.
- true: Audio will be generated from lyrics
- false: Audio will be generated based on inspiration mode prompts
Model to use. After creating a custom model, you can also pass chirp-custom:{model_id}. See Create Model. persona_id and chirp-custom cannot be used together.
chirp-v5-5, chirp-v5, chirp-v4-5+, chirp-v4-5, chirp-v4-5-all, chirp-v4, chirp-v3-5, chirp-v3-0 Audio ID
Prompt for inspiration mode.
When not using custom mode (custom=false), this parameter is always required. Lyrics will be automatically generated from this prompt. Maximum length: 3000 characters.
"Night city lo-fi piano with rain ambience, soft vocal phrases, theme: \"Under the city lights\""
Lyrics.
Used in custom mode (custom=true). Required when instrumental is false. The lyrics will be used and sung in the generated track. Maximum length: 5000 characters.
Music title.
Used in custom mode (custom=true). Maximum length: 80 characters.
Music style or genre.
Used in custom mode (custom=true). Maximum length: 1000 characters.
"rock, blues, hip-hop, r&b"
Music styles or genres that should be excluded from generation.
Used in custom mode (custom=true).
Music style weight, range: 0.00–1.00.
Used in custom mode. Valid range: 0 <= x <= 1.
0.5
Audio creativity (weirdness) weight, range: 0.00–1.00.
Used in custom mode. Valid range: 0 <= x <= 1.
0.5
Audio weight, range: 0.00–1.00.
Used in custom mode. Valid range: 0 <= x <= 1.
0.5
Audio format of audioUrl after the job succeeds.
mp3, m4a, wav "mp3"
Callback notification URL
Whether to store the generated audio.
- true: The audio will be stored and a TTAPI CDN URL will be returned
- false: The original source URL will be returned