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-ключ Повернутися до огляду