Suno Music
curl --request POST \
--url https://api.snapgen.org/v1/music/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"custom": true,
"instrumental": true,
"version": "<string>",
"custom_model_task_id": "<string>",
"prompt": "<string>",
"title": "<string>",
"style": "<string>",
"negative_tags": "<string>",
"auto_lyrics": true,
"persona_task_id": "<string>",
"vocal_gender": "<string>",
"style_weight": 123,
"weirdness": 123,
"audio_weight": 123,
"variety": "<string>",
"max_mode": true,
"audio_format": "<string>",
"duration": 123,
"webhook": "<string>",
"webhook_secret": "<string>"
}
'import requests
url = "https://api.snapgen.org/v1/music/generations"
payload = {
"model": "<string>",
"custom": True,
"instrumental": True,
"version": "<string>",
"custom_model_task_id": "<string>",
"prompt": "<string>",
"title": "<string>",
"style": "<string>",
"negative_tags": "<string>",
"auto_lyrics": True,
"persona_task_id": "<string>",
"vocal_gender": "<string>",
"style_weight": 123,
"weirdness": 123,
"audio_weight": 123,
"variety": "<string>",
"max_mode": True,
"audio_format": "<string>",
"duration": 123,
"webhook": "<string>",
"webhook_secret": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
custom: true,
instrumental: true,
version: '<string>',
custom_model_task_id: '<string>',
prompt: '<string>',
title: '<string>',
style: '<string>',
negative_tags: '<string>',
auto_lyrics: true,
persona_task_id: '<string>',
vocal_gender: '<string>',
style_weight: 123,
weirdness: 123,
audio_weight: 123,
variety: '<string>',
max_mode: true,
audio_format: '<string>',
duration: 123,
webhook: '<string>',
webhook_secret: '<string>'
})
};
fetch('https://api.snapgen.org/v1/music/generations', 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.snapgen.org/v1/music/generations",
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([
'model' => '<string>',
'custom' => true,
'instrumental' => true,
'version' => '<string>',
'custom_model_task_id' => '<string>',
'prompt' => '<string>',
'title' => '<string>',
'style' => '<string>',
'negative_tags' => '<string>',
'auto_lyrics' => true,
'persona_task_id' => '<string>',
'vocal_gender' => '<string>',
'style_weight' => 123,
'weirdness' => 123,
'audio_weight' => 123,
'variety' => '<string>',
'max_mode' => true,
'audio_format' => '<string>',
'duration' => 123,
'webhook' => '<string>',
'webhook_secret' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.snapgen.org/v1/music/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.snapgen.org/v1/music/generations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snapgen.org/v1/music/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyCreate
Suno Music
Generate songs from a description or your own lyrics with Suno V6. 0.075perrequest,0.15 in Max mode.
POST
/
v1
/
music
/
generations
Suno Music
curl --request POST \
--url https://api.snapgen.org/v1/music/generations \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"model": "<string>",
"custom": true,
"instrumental": true,
"version": "<string>",
"custom_model_task_id": "<string>",
"prompt": "<string>",
"title": "<string>",
"style": "<string>",
"negative_tags": "<string>",
"auto_lyrics": true,
"persona_task_id": "<string>",
"vocal_gender": "<string>",
"style_weight": 123,
"weirdness": 123,
"audio_weight": 123,
"variety": "<string>",
"max_mode": true,
"audio_format": "<string>",
"duration": 123,
"webhook": "<string>",
"webhook_secret": "<string>"
}
'import requests
url = "https://api.snapgen.org/v1/music/generations"
payload = {
"model": "<string>",
"custom": True,
"instrumental": True,
"version": "<string>",
"custom_model_task_id": "<string>",
"prompt": "<string>",
"title": "<string>",
"style": "<string>",
"negative_tags": "<string>",
"auto_lyrics": True,
"persona_task_id": "<string>",
"vocal_gender": "<string>",
"style_weight": 123,
"weirdness": 123,
"audio_weight": 123,
"variety": "<string>",
"max_mode": True,
"audio_format": "<string>",
"duration": 123,
"webhook": "<string>",
"webhook_secret": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
model: '<string>',
custom: true,
instrumental: true,
version: '<string>',
custom_model_task_id: '<string>',
prompt: '<string>',
title: '<string>',
style: '<string>',
negative_tags: '<string>',
auto_lyrics: true,
persona_task_id: '<string>',
vocal_gender: '<string>',
style_weight: 123,
weirdness: 123,
audio_weight: 123,
variety: '<string>',
max_mode: true,
audio_format: '<string>',
duration: 123,
webhook: '<string>',
webhook_secret: '<string>'
})
};
fetch('https://api.snapgen.org/v1/music/generations', 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.snapgen.org/v1/music/generations",
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([
'model' => '<string>',
'custom' => true,
'instrumental' => true,
'version' => '<string>',
'custom_model_task_id' => '<string>',
'prompt' => '<string>',
'title' => '<string>',
'style' => '<string>',
'negative_tags' => '<string>',
'auto_lyrics' => true,
'persona_task_id' => '<string>',
'vocal_gender' => '<string>',
'style_weight' => 123,
'weirdness' => 123,
'audio_weight' => 123,
'variety' => '<string>',
'max_mode' => true,
'audio_format' => '<string>',
'duration' => 123,
'webhook' => '<string>',
'webhook_secret' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.snapgen.org/v1/music/generations"
payload := strings.NewReader("{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.snapgen.org/v1/music/generations")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.snapgen.org/v1/music/generations")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"model\": \"<string>\",\n \"custom\": true,\n \"instrumental\": true,\n \"version\": \"<string>\",\n \"custom_model_task_id\": \"<string>\",\n \"prompt\": \"<string>\",\n \"title\": \"<string>\",\n \"style\": \"<string>\",\n \"negative_tags\": \"<string>\",\n \"auto_lyrics\": true,\n \"persona_task_id\": \"<string>\",\n \"vocal_gender\": \"<string>\",\n \"style_weight\": 123,\n \"weirdness\": 123,\n \"audio_weight\": 123,\n \"variety\": \"<string>\",\n \"max_mode\": true,\n \"audio_format\": \"<string>\",\n \"duration\": 123,\n \"webhook\": \"<string>\",\n \"webhook_secret\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodysuno-music generates songs with Suno V6. Describe the song and let the model write it, or send your own lyrics and style tags. The request runs as an asynchronous task, and a finished task can return several tracks. Every track can be the source of a later edit, such as an extension, a cover, or a stem split.
| Property | Value |
|---|---|
| Model ID | suno-music |
| Endpoint | POST /v1/music/generations (asynchronous task) |
| Group | Suno > Create |
| Input | Text: a song description, or lyrics with style tags |
| Result | Tracks in result.tracks with audio_url |
| Versions | v6 (default), v6-wild, v6-mini, or your own model from suno-custom-model |
| Price | $0.075 per request (7.5 credits); $0.15 with max_mode: true |
Two ways to write a song
- Description mode
- Custom mode
Leave
custom out (or false) and describe the song in prompt, up to
3,000 characters. The model writes the lyrics, style, and title.curl https://api.snapgen.org/v1/music/generations \
-H "Authorization: Bearer $SNAPGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-music",
"prompt": "A late-night city lo-fi song with soft piano and rain"
}'
Send For an instrumental, send
custom: true with your lyrics in prompt (up to 5,000
characters), the sound in style, and a title. Custom mode also unlocks
max_mode, a target duration, and a Persona.curl https://api.snapgen.org/v1/music/generations \
-H "Authorization: Bearer $SNAPGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-music",
"custom": true,
"title": "Night Drive",
"style": "synthwave, female vocal",
"prompt": "[Verse]\nCity lights are calling me home\n[Chorus]\nWe keep on driving through the night",
"duration": 120
}'
custom: true and instrumental: true; lyrics
are then optional.string
required
Set to
suno-music.boolean
default:"false"
false (default) is description mode: prompt describes the song. true is custom mode: prompt holds the lyrics, and title, style, negative_tags, auto_lyrics, and persona_task_id apply.boolean
default:"false"
true makes an instrumental with no vocals. In custom mode, prompt is then optional.string
default:"v6"
Suno model version:
v6, v6-wild, or v6-mini. Omit it when you send custom_model_task_id.string
The
id of a succeeded suno-custom-model task. Generates with that custom model instead of a public version, so don’t send version or persona_task_id.string
Description mode: what the song should sound like, up to 3,000 characters. Custom mode: the lyrics, up to 5,000 characters. Required, except for a custom-mode instrumental.
string
Track title, up to 80 characters. Applies in custom mode.
string
Style tags for custom mode, up to 1,000 characters, for example
synthwave, female vocal.string
Styles to avoid, up to 1,000 characters. Applies in custom mode.
boolean
true rewrites the lyrics you send creatively. Applies in custom mode.string
The
id of a succeeded suno-persona task. The song is sung with that Persona. Applies in custom mode. Can’t be combined with custom_model_task_id.string
male or female vocals.number
Style weight, from 0 to 1.
number
Creativity, from 0 to 1. Higher values are more experimental.
number
Audio weight, from 0 to 1.
string
Style variation:
off, normal, high, extra, or max. It doesn’t turn on Max mode or change the price.boolean
default:"false"
true turns on Suno Max mode and bills twice the request price. Requires custom: true.string
Output format:
mp3, m4a, or wav. The provider picks one if you omit it.integer
Target length in seconds, from 10 to 360. The finished track can be shorter or longer. Requires
custom: true.string
Optional public
https URL that receives one signed event when the task finishes. See Task webhooks.string
Required with
webhook: 16 to 256 characters, used to sign the delivery.Request rules
The gateway checks these before it reserves any balance:- Without
custom: true,promptis a description of up to 3,000 characters and is required. - With
custom: true,promptholds lyrics of up to 5,000 characters and is required unlessinstrumentalistrue. max_modeanddurationrequirecustom: true.- Send either
versionorcustom_model_task_id, not both. persona_task_idcan’t be combined withcustom_model_task_id.
Wait for the result
The response is HTTP202 with a task object and a Location: /v1/tasks/{id}
header. Poll GET /v1/tasks/{id} every 10 to 20
seconds until status is succeeded or failed, or pass webhook to be
notified.
import json
import os
import time
from urllib.request import Request, urlopen
API = "https://api.snapgen.org/v1"
AUTH = {"Authorization": f"Bearer {os.environ['SNAPGEN_API_KEY']}"}
submit = Request(
f"{API}/music/generations",
data=json.dumps({
"model": "suno-music",
"prompt": "A late-night city lo-fi song with soft piano and rain",
}).encode(),
headers={**AUTH, "Content-Type": "application/json"},
)
with urlopen(submit) as response:
task = json.load(response)
while task["status"] in ("queued", "processing"):
time.sleep(15)
with urlopen(Request(f"{API}/tasks/{task['id']}", headers=AUTH)) as response:
task = json.load(response)
if task["status"] != "succeeded":
raise RuntimeError(task["error"])
for track in task["result"]["tracks"]:
print(track["index"], track.get("title"), track.get("audio_url"))
const API = "https://api.snapgen.org/v1";
const auth = { Authorization: `Bearer ${process.env.SNAPGEN_API_KEY}` };
const submitted = await fetch(`${API}/music/generations`, {
method: "POST",
headers: { ...auth, "Content-Type": "application/json" },
body: JSON.stringify({
model: "suno-music",
prompt: "A late-night city lo-fi song with soft piano and rain",
}),
});
if (!submitted.ok) throw new Error(await submitted.text());
let task = await submitted.json();
while (task.status === "queued" || task.status === "processing") {
await new Promise((resolve) => setTimeout(resolve, 15_000));
task = await (await fetch(`${API}/tasks/${task.id}`, { headers: auth })).json();
}
if (task.status !== "succeeded") throw new Error(JSON.stringify(task.error));
for (const track of task.result.tracks) {
console.log(track.index, track.title, track.audio_url);
}
Result
result.tracks[] lists every track in its original order, each with its
index and audio_url, plus title, image_url, duration_seconds,
lyrics, and tags when the provider returns them. result.urls lists the
audio URLs. Keep the task id and the track index: they’re how later
operations find the track.
{
"urls": [
"https://cdn.example.com/music/rain-lofi-1.mp3",
"https://cdn.example.com/music/rain-lofi-2.mp3"
],
"tracks": [
{
"index": 1,
"id": "clip_8f3a2c",
"title": "Rain on the Window",
"audio_url": "https://cdn.example.com/music/rain-lofi-1.mp3",
"image_url": "https://cdn.example.com/music/rain-lofi-1.jpg",
"duration_seconds": 146.2,
"tags": "lo-fi, soft piano, rain"
},
{
"index": 2,
"id": "clip_9b4d1e",
"title": "Rain on the Window",
"audio_url": "https://cdn.example.com/music/rain-lofi-2.mp3",
"image_url": "https://cdn.example.com/music/rain-lofi-2.jpg",
"duration_seconds": 152.8,
"tags": "lo-fi, soft piano, rain"
}
]
}
Next steps
Pass this task’sid as source_task_id, and a track index as
source_index, to any Suno edit model:
Extend a track
Continue the song from a chosen second, then join the parts with
suno-concat.Cover in a new style
Re-record the song in another genre or mood.
Split stems
Separate vocals, drums, bass, and other stems.
Export files
Get MP3, M4A, or WAV files of a track.
Result URLs are kept for about 72 hours. Download the files you want to
keep. See Music generation tasks for
task references, webhooks, and errors.