API генерации в простом режиме
Описание эндпоинта
Генерация в простом режиме превращает описание в одну фразу в готовую песню. Сервис сам пишет текст, мелодию, аранжировку и вокал по вашему описанию.
Эндпоинт: POST /api/music/create
Оплата: платно, сейчас по умолчанию 0,6 ¥ за вызов. За вызов обычно возвращаются 2 песни; фактически списанная сумма следует текущей конфигурации цен в бэк-офисе.
Max Mode / Variety: эндпоинт поддерживает необязательные параметры max_mode и variety (0-4). При включённом
max_mode этот вызов тарифицируется по двойной цене (0,6 ¥ → 1,2 ¥ за вызов); variety не стоит
ничего дополнительно. Что они означают и как их отправлять — в разделе «Расширенные параметры»
Обзора нового API.
Рекомендуемая модель: suno-v6
Время ожидания и тайм-ауты (важно): это синхронный эндпоинт — заказ принимается и передаётся в генерацию только при получении ответа. По измерениям большинство запросов отвечают за 1-3 секунды, около 10% занимают больше 30 секунд, а самый долгий — около 230 секунд. Установите тайм-аут клиента 300 секунд или больше; отсутствие ответа не означает, что ничего не сгенерировано, и не повторяйте запрос сразу после тайм-аута (это дублирует заказ и списывает деньги повторно). Если соединение оборвалось, проверьте позже через
GET /api/music/songs. См. «Время ожидания и настройка тайм-аута» в Обзоре нового API.
Параметры запроса
Headers
| Параметр | Тип | Обязательно | Примечания |
|---|---|---|---|
| Authorization | string | да | Bearer YOUR_API_KEY |
| Content-Type | string | да | application/json |
Параметры тела
| Параметр | Тип | Обязательно | По умолчанию | Примечания |
|---|---|---|---|---|
| description | string | да | - | Описание песни на любом языке; не более 3000 символов (больше — ответ 400, оплата не списывается) |
| model | string | нет | suno-v6 | Клиентское имя модели: suno-v6, suno-v6-wild или suno-v6-mini |
| instrumental | boolean | нет | false | Только инструментальная песня или нет |
| wait_completion | boolean | нет | false | Ждать завершения генерации перед ответом |
| references | array | нет | - | Список референсного материала: референсные песни / старые голоса / референсные изображения; не более 5 песен, 1 голоса и 1 изображения. См. «Референсный материал references (необязательно)» ниже |
Примеры запроса
curl -X POST https://www.suno-api.io/api/music/create \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"description": "бодрая мандаринская поп-песня о лете у моря",
"instrumental": false,
"wait_completion": false
}'
Референсный материал references (необязательно)
references — массив, который прикрепляет к этой генерации «референсный материал». Он полностью необязателен (без него поведение в точности как раньше), и можно прикрепить только один вид или любую комбинацию.
Типы элементов
| type | Обязательное поле | Необязательные поля | Максимум | Примечания |
|---|---|---|---|---|
song |
song_id |
style_prompt, lyrics, duration_s |
5 | Референсная песня; song_id берётся из API запроса песен и истории, и песня должна быть уже завершена |
voice |
voice_id |
- | 1 | Старый голос; voice_id берётся из API клонирования голоса и генерации с голосом |
image |
base64 |
- | 1 | Референсное изображение; отправляйте base64 в форме data:image/jpeg;base64,... |
Правила
- Порядок референсных песен — это их смысловой порядок: передавайте их в нужном порядке (например «мелодия из первой, вокал из второй»).
style_prompt/lyrics/duration_sможно не указывать; платформа дополнит их из информации о песне, а то, что отправили вы, имеет приоритет.- Для чисто инструментальных песен
lyricsможет быть""или"[Instrumental]". - Референсные изображения поддерживают
jpeg/png/webp, до 10 МБ каждое, отправляются вместе с телом в base64. - Прикрепляя несколько референсных песен, дополнительно используйте
accept_mode=async(см. «Режим квитанции-приёмки» выше): сервису нужно сначала подготовить материал, поэтому синхронное ожидание может быть долгим.
Пример: две референсные песни
curl -X POST https://www.suno-api.io/api/music/create \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "suno-v6",
"description": "объедини эти идеи в одну песню",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
]
}'
Пример: референсная песня + старый голос
{
"model": "suno-v6",
"description": "спой эти идеи этим голосом",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
]
}
Пример: референсная песня + референсное изображение
{
"model": "suno-v6",
"description": "передай настроение этого изображения",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
]
}
Ошибки параметров
Эти случаи возвращают HTTP 400, блокируются до любого списания, поэтому ничего не стоят:
| Случай | Сообщение об ошибке |
|---|---|
| Больше 5 референсных песен | references supports at most 5 song references |
| Больше 1 голоса | references supports at most 1 voice reference |
| Больше 1 референсного изображения | references supports at most 1 image reference |
Недопустимый type |
references[0].type must be one of song, voice, image |
У песни нет song_id |
references[0].song_id is required |
| Песня ещё не завершена | references[0].song_id must be a real completed clip |
| Одна и та же песня дважды | references[0].song_id is duplicated |
Число в
references[0]— это индекс этого элемента в массиве, поэтому проблемный элемент легко найти.
Ответ
Массив песен, обычно с 2 задачами или песнями.
[
{
"song_id": "clip_id",
"song_title": "Летний морской бриз",
"status": "pending",
"description": "бодрая мандаринская поп-песня о лете у моря",
"audio_url": "",
"cover_url": "",
"video_url": "",
"model_version": "suno-v6",
"generation_type": "generate",
"created_at": "2026-05-21T10:00:00Z"
}
]
Режим квитанции-приёмки (необязательно, рекомендован клиентам, которым не нужно держать долгие соединения)
По умолчанию эндпоинт синхронный: именно получение ответа означает, что заказ принят, а измеренные ожидания могут доходить до ~230 секунд. Если клиент не должен держать долгое соединение, включите режим квитанции-приёмки — подходит любой вариант:
- добавить
"accept_mode": "async"в тело запроса - добавить заголовок
X-Accept-Mode: async
С ним эндпоинт сразу возвращает HTTP 202, что означает лишь «принято и поставлено в очередь на генерацию», а генерация продолжается в фоне:
{
"success": true,
"data": {
"request_id": "ac_20260920092714315816800d76fv3nq",
"status": "queued",
"accepted_at": 1789896434,
"pre_consumed_quota": 300000,
"tasks": [
{ "index": 0, "status": "queued" },
{ "index": 1, "status": "queued" }
]
}
}
На этапе приёма
song_idне возвращается. Настоящего ID песни ещё нет, и ниrequest_id, ниtasks[].indexне являются ID песни — не сохраняйте их какsong_id. Настоящийsong_idпоявится в запросе прогресса ниже.
Запрос прогресса приёма
Эндпоинт: GET /api/music/requests/{request_id} (бесплатно, аутентификация тем же ключом API)
curl "https://www.suno-api.io/api/music/requests/ac_20260920092714315816800d76fv3nq" \
-H "Authorization: Bearer YOUR_API_KEY"
{
"success": true,
"data": {
"request_id": "ac_20260920092714315816800d76fv3nq",
"status": "processing",
"tasks": [
{ "index": 0, "status": "processing", "song_id": "f3fa09f5-3d55-4953-826c-0d23f043ec57" },
{ "index": 1, "status": "processing", "song_id": "5fcafe3e-3fae-4d64-8f66-c01bc027b0c3" }
]
}
}
Что означает каждое значение status:
| status | Значение |
|---|---|
queued |
Принято, ещё не привязано к конкретным песням (tasks может быть пустым массивом) |
processing |
Передано в генерацию |
partial |
Одна из двух уже завершена |
completed |
Обе завершены, tasks[].song_id читается |
failed |
Передача не удалась, сумма полностью возвращена, error_message даёт причину |
У каждой задачи есть и свой tasks[].status с теми же значениями, что в API запроса песен:
pending (передано, генерируется), processing, completed, failed. Элементы задачи могут также нести title,
duration и уже зарегистрированный audio_url; чего нет — просто ещё не сгенерировано.
Получив настоящий song_id, продолжайте через API запроса песен или эндпоинты загрузки.
Пример на Python
import time
import requests
BASE = "https://www.suno-api.io"
HEADERS = {"Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json"}
accepted = requests.post(
f"{BASE}/api/music/create",
headers={**HEADERS, "Idempotency-Key": "your-own-unique-key"},
json={"description": "бодрая поп-песня", "model": "suno-v6", "accept_mode": "async"},
timeout=300,
).json()["data"]
request_id = accepted["request_id"]
while True:
time.sleep(5)
progress = requests.get(
f"{BASE}/api/music/requests/{request_id}", headers=HEADERS, timeout=60
).json()["data"]
if progress["status"] in ("completed", "failed"):
print(progress)
break
Совместимость и примечания
- Без
accept_modeповедение точно как раньше: синхронное ожидание, ответ200и массив песен. Существующим интеграциям менять код не нужно. - Сейчас этот переключатель работает только на
POST /api/music/createиPOST /api/music/create/custom; остальные эндпоинты генерации его пока не поддерживают. - Дополнительно отправляйте
Idempotency-Key(своя уникальная строка, ≤128 символов): один и тот же ключ принимается лишь один раз, повтор возвращает ту же квитанцию, двойного списания нет. В асинхронном режиме это особенно важно. - При
accept_mode=asyncпараметрwait_completionигнорируется (квитанция возвращается сразу, не дожидаясь песен). - Сумма по-прежнему списывается заранее при приёме заказа; неудачная генерация автоматически возвращается полностью.
- Лимит текстового поля:
descriptionвмещает не более 3000 символов (счёт в символах Unicode, один иероглиф считается за 1). Более длинный текст сразу возвращает HTTP400, не попадает в генерацию и не оплачивается, а в сообщении об ошибке указана измеренная длина, напримерdescription must not exceed 3000 characters; received 4120. В этом эндпоинте нет полей текста/стиля; для них см. «Лимит текстового поля» в API генерации в расширенном режиме. Общие правила — в «Ограничения текстовых полей» Обзора нового API. - Без
referencesповедение, цена и ответ точно как раньше: существующим интеграциям менять код не нужно. - Когда прикреплён референсный материал (особенно несколько песен), предпочитайте режим квитанции
accept_mode=asyncдолгому синхронному ожиданию; время подготовки материала зависит от его объёма и источника.
Дальнейшие шаги
Если песни не завершены к моменту ответа, возьмите итоговый результат через API запроса песен.
Пример интеграции в Node/Electron
Если вы встраиваете стандартную генерацию в главный процесс Electron, сервер Node.js или десктопный клиент, рекомендуется такая последовательность:
- Вызовите
POST /api/music/create, чтобы создать задачу генерации. - Прочитайте
song_idилиidиз ответа. - Каждые 2 секунды вызывайте
POST /api/music/queryдля проверки статуса. - Считайте генерацию завершённой, как только в результате появится
audio_url.
Не используйте старые пути POST /api/generate или GET /api/clip?id=...; они не входят в текущую рекомендуемую публичную поверхность интеграции.
const http = require('http');
const https = require('https');
const BASE_URL = 'https://www.suno-api.io';
const MODEL = 'suno-v6';
const POLL_INTERVAL_MS = 2000;
const MAX_POLL_ATTEMPTS = 60;
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function requestJson(urlString, apiKey, body) {
const url = new URL(urlString);
const transport = url.protocol === 'https:' ? https : http;
const payload = JSON.stringify(body);
return new Promise((resolve, reject) => {
const req = transport.request(
{
method: 'POST',
hostname: url.hostname,
port: url.port || undefined,
path: `${url.pathname}${url.search}`,
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload),
},
},
(res) => {
let raw = '';
res.setEncoding('utf8');
res.on('data', (chunk) => {
raw += chunk;
});
res.on('end', () => {
const data = raw ? JSON.parse(raw) : {};
if (!res.statusCode || res.statusCode < 200 || res.statusCode >= 300) {
reject(new Error(`Suno API request failed: HTTP ${res.statusCode} ${raw}`));
return;
}
resolve(data);
});
}
);
req.on('error', reject);
req.write(payload);
req.end();
});
}
function getPayload(response) {
return response && response.data !== undefined ? response.data : response;
}
function toSongList(payload) {
if (Array.isArray(payload)) return payload;
if (Array.isArray(payload?.songs)) return payload.songs;
if (Array.isArray(payload?.clips)) return payload.clips;
return payload ? [payload] : [];
}
function collectSongIds(createResponse) {
return toSongList(getPayload(createResponse))
.map((song) => song.song_id || song.id)
.filter(Boolean);
}
async function generateSunoSong({ apiKey, description, instrumental = false }) {
const createResponse = await requestJson(`${BASE_URL}/api/music/create`, apiKey, {
description,
model: MODEL,
instrumental,
wait_completion: false,
});
const songIds = collectSongIds(createResponse);
if (songIds.length === 0) {
throw new Error(`Suno API did not return song ids: ${JSON.stringify(createResponse)}`);
}
for (let attempt = 0; attempt < MAX_POLL_ATTEMPTS; attempt += 1) {
await sleep(POLL_INTERVAL_MS);
const queryResponse = await requestJson(`${BASE_URL}/api/music/query`, apiKey, {
song_ids: songIds,
model: MODEL,
});
const songs = toSongList(getPayload(queryResponse));
const completed = songs.find((song) => song.audio_url);
if (completed) {
return {
audioUrl: completed.audio_url,
title: completed.song_title || completed.title || 'Suno Song',
duration: completed.duration,
};
}
const allFailed = songs.length > 0 && songs.every((song) =>
['failed', 'error', 'rejected'].includes(String(song.status || '').toLowerCase())
);
if (allFailed) {
throw new Error(`Suno generation failed: ${JSON.stringify(songs)}`);
}
}
throw new Error('Suno generation timed out after 120 seconds. Please query again later.');
}
// Usage:
// generateSunoSong({
// apiKey: process.env.SUNO_API_KEY,
// description: 'A bright pop song about the ocean in summer',
// }).then(console.log).catch(console.error);
В реальных проектах храните ключ API в переменной окружения сервера, в настройках десктопного клиента или в защищённом хранилище — никогда во фронтенд-коде и никогда в репозитории.
Получить API-ключ
Создайте API-ключ в консоли после регистрации. Одна генерация стоит 0,6 ¥ и возвращает 2 трека, загрузки не ограничены, номер телефона не нужен.
Получить API-ключ Вернуться к обзору