API tạo nhạc chế độ đơn giản
Mô tả endpoint
Tạo nhạc ở chế độ đơn giản dùng để biến một câu mô tả thành một bài hát hoàn chỉnh. Hệ thống tự viết lời, giai điệu, phối khí và phần hát theo mô tả của bạn.
Endpoint: POST /api/music/create
Tính phí: Có phí, hiện mặc định 0,6 ¥ mỗi lần gọi. Mỗi lần thường trả về 2 bài hát; số tiền thực trừ tuân theo cấu hình giá hiện tại trong phần quản trị.
Max Mode / Variety: endpoint này hỗ trợ hai tham số tùy chọn max_mode và variety (0-4). Khi bật
max_mode, lần gọi này bị tính gấp đôi (0,6 ¥ → 1,2 ¥ mỗi lần); variety không phát sinh phí thêm.
Ý nghĩa và cách gửi xem mục "Tham số nâng cao" trong
Tổng quan API mới.
Mô hình khuyến nghị: suno-v6
Thời gian chờ và timeout (quan trọng): đây là endpoint đồng bộ — đơn chỉ được tiếp nhận và đưa vào tạo nhạc khi phản hồi trả về. Theo đo đạc, phần lớn yêu cầu trả về trong 1-3 giây, khoảng 10% mất hơn 30 giây và lâu nhất khoảng 230 giây. Hãy đặt timeout phía client từ 300 giây trở lên; không nhận được phản hồi không có nghĩa là chưa tạo gì, và đừng thử lại ngay sau khi timeout (sẽ trùng đơn và bị tính phí hai lần). Nếu kết nối bị ngắt, hãy kiểm tra lại sau bằng
GET /api/music/songs. Xem "Thời gian chờ và thiết lập timeout" trong Tổng quan API mới.
Tham số yêu cầu
Headers
| Tham số | Kiểu | Bắt buộc | Ghi chú |
|---|---|---|---|
| Authorization | string | có | Bearer YOUR_API_KEY |
| Content-Type | string | có | application/json |
Tham số body
| Tham số | Kiểu | Bắt buộc | Mặc định | Ghi chú |
|---|---|---|---|---|
| description | string | có | - | Mô tả bài hát, dùng được mọi ngôn ngữ; tối đa 3000 ký tự (dài hơn trả về 400 và không tính phí) |
| model | string | không | suno-v6 | Tên mô hình cho khách hàng: suno-v6, suno-v6-wild hoặc suno-v6-mini |
| instrumental | boolean | không | false | Bài hát có phải nhạc không lời hoàn toàn không |
| wait_completion | boolean | không | false | Có chờ tạo xong mới trả về không |
| references | array | không | - | Danh sách tư liệu tham chiếu: bài hát tham chiếu / giọng cũ / ảnh tham chiếu; tối đa 5 bài hát, 1 giọng và 1 ảnh. Xem "Tư liệu tham chiếu references (không bắt buộc)" bên dưới |
Ví dụ yêu cầu
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": "một bài nhạc pop tiếng Quan Thoại sôi động về mùa hè bên biển",
"instrumental": false,
"wait_completion": false
}'
Tư liệu tham chiếu references (không bắt buộc)
references là một mảng dùng để gắn "tư liệu tham chiếu" cho lần tạo nhạc này. Có thể bỏ qua hoàn toàn (bỏ qua thì hành vi y hệt trước đây), và có thể gắn một loại hoặc kết hợp bất kỳ.
Các loại phần tử
| type | Trường bắt buộc | Trường tùy chọn | Số lượng tối đa | Ghi chú |
|---|---|---|---|---|
song |
song_id |
style_prompt, lyrics, duration_s |
5 | Bài hát tham chiếu; song_id lấy từ API truy vấn và lịch sử bài hát, và bài hát phải đã hoàn tất |
voice |
voice_id |
- | 1 | Giọng cũ; voice_id lấy từ API nhân bản giọng và tạo nhạc bằng giọng |
image |
base64 |
- | 1 | Ảnh tham chiếu; gửi nội dung base64 dạng data:image/jpeg;base64,... |
Quy tắc
- Thứ tự bài hát tham chiếu chính là thứ tự ngữ nghĩa: truyền theo thứ tự bạn muốn thể hiện (ví dụ "giai điệu của bài thứ nhất, giọng hát của bài thứ hai").
style_prompt/lyrics/duration_sđều có thể bỏ trống; hệ thống sẽ tự bổ sung từ thông tin bài hát, và giá trị bạn gửi sẽ được ưu tiên.- Với bài hát thuần nhạc cụ,
lyricscó thể là""hoặc"[Instrumental]". - Ảnh tham chiếu hỗ trợ
jpeg/png/webp, mỗi ảnh không quá 10MB, gửi kèm body dưới dạng base64. - Khi gắn nhiều bài hát tham chiếu, nên dùng thêm
accept_mode=async(xem "Chế độ nhận biên nhận" ở trên): hệ thống phải chuẩn bị tư liệu trước nên chờ đồng bộ có thể lâu.
Ví dụ: gắn 2 bài hát tham chiếu
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": "kết hợp những ý tưởng này thành một bài hát",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
]
}'
Ví dụ: bài hát tham chiếu + giọng cũ
{
"model": "suno-v6",
"description": "hát những ý tưởng này bằng giọng này",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
]
}
Ví dụ: bài hát tham chiếu + ảnh tham chiếu
{
"model": "suno-v6",
"description": "tái hiện không khí của bức ảnh này",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
]
}
Lỗi tham số
Những trường hợp sau trả về HTTP 400, bị chặn trước khi tính phí nên không tốn tiền:
| Trường hợp | Thông báo lỗi |
|---|---|
| Quá 5 bài hát tham chiếu | references supports at most 5 song references |
| Quá 1 giọng | references supports at most 1 voice reference |
| Quá 1 ảnh tham chiếu | references supports at most 1 image reference |
type không hợp lệ |
references[0].type must be one of song, voice, image |
Bài hát thiếu song_id |
references[0].song_id is required |
| Bài hát chưa hoàn tất | references[0].song_id must be a real completed clip |
| Cùng một bài hát gửi hai lần | references[0].song_id is duplicated |
Số trong
references[0]là chỉ số của phần tử đó trong mảng, giúp xác định nhanh phần tử bị lỗi.
Phản hồi
Một mảng bài hát, thường gồm 2 tác vụ hoặc bài hát.
[
{
"song_id": "clip_id",
"song_title": "Gió biển mùa hè",
"status": "pending",
"description": "một bài nhạc pop tiếng Quan Thoại sôi động về mùa hè bên biển",
"audio_url": "",
"cover_url": "",
"video_url": "",
"model_version": "suno-v6",
"generation_type": "generate",
"created_at": "2026-05-21T10:00:00Z"
}
]
Chế độ nhận biên nhận (không bắt buộc, khuyến nghị cho client không nên giữ kết nối lâu)
Mặc định endpoint này chạy đồng bộ: phản hồi trả về mới là dấu hiệu đơn đã được tiếp nhận, và thời gian chờ đo được có thể tới khoảng 230 giây. Nếu client của bạn không phù hợp để giữ kết nối lâu, hãy bật chế độ nhận biên nhận — dùng cách nào cũng được:
- thêm
"accept_mode": "async"vào body - thêm header
X-Accept-Mode: async
Khi bật, endpoint trả về HTTP 202 ngay lập tức, chỉ có nghĩa "đã tiếp nhận và vào hàng đợi tạo nhạc", còn việc tạo vẫn chạy nền:
{
"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" }
]
}
}
Giai đoạn tiếp nhận không trả về
song_id. Lúc này chưa có ID bài hát thật, và cảrequest_idlẫntasks[].indexđều không phải ID bài hát — đừng lưu chúng nhưsong_id.song_idthật sẽ xuất hiện ở phần tra tiến độ bên dưới.
Tra tiến độ tiếp nhận
Endpoint: GET /api/music/requests/{request_id} (miễn phí, xác thực bằng cùng khóa 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" }
]
}
}
Ý nghĩa từng giá trị status:
| status | Ý nghĩa |
|---|---|
queued |
Đã tiếp nhận, chưa gắn với bài hát cụ thể (tasks có thể là mảng rỗng) |
processing |
Đã đưa vào tạo nhạc |
partial |
Một trong hai bài đã xong |
completed |
Cả hai đã xong, đọc được tasks[].song_id |
failed |
Gửi thất bại, đã hoàn tiền toàn bộ, error_message nêu lý do |
Mỗi tác vụ còn có tasks[].status riêng, giá trị giống API truy vấn bài hát:
pending (đã gửi, đang tạo), processing, completed, failed. Mục tác vụ cũng có thể kèm title,
duration và audio_url đã đăng ký; thiếu nghĩa là chưa tạo xong.
Khi đã có song_id thật, tiếp tục bằng API truy vấn bài hát hoặc các endpoint tải xuống.
Ví dụ 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": "một bài pop sôi động", "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
Tương thích và lưu ý
- Không có
accept_mode, hành vi giống hệt trước đây: chờ đồng bộ, trả về200và mảng bài hát. Các tích hợp hiện có không cần sửa gì. - Công tắc này hiện chỉ hoạt động với
POST /api/music/createvàPOST /api/music/create/custom; các endpoint tạo nhạc khác chưa hỗ trợ. - Nên gửi kèm
Idempotency-Key(chuỗi duy nhất do bạn tự đặt, ≤128 ký tự): cùng một khóa gửi lại chỉ được tiếp nhận một lần, gửi lại trả về cùng biên nhận và không bị trừ tiền hai lần. Ở chế độ bất đồng bộ, điều này càng quan trọng. - Khi bật
accept_mode=async,wait_completionbị bỏ qua (biên nhận trả về ngay, không chờ bài hát). - Chi phí vẫn được trừ trước khi tiếp nhận; tạo nhạc thất bại sẽ được hoàn lại toàn bộ tự động.
- Giới hạn trường văn bản:
descriptiontối đa 3000 ký tự (đếm theo ký tự Unicode, một chữ Hán tính là 1). Dài hơn sẽ trả về HTTP400ngay, không vào tạo nhạc và không bị tính phí; thông báo lỗi có kèm số ký tự đo được, ví dụdescription must not exceed 3000 characters; received 4120. Endpoint này không có trường lời/phong cách; nếu cần, xem "Giới hạn trường văn bản" trong API tạo nhạc chế độ tùy chỉnh. Quy ước chung nằm ở "Giới hạn trường văn bản" trong Tổng quan API mới. - Không có
references, hành vi, giá và phản hồi giống hệt trước đây: các tích hợp hiện có không cần sửa gì. - Khi gắn tư liệu tham chiếu (nhất là nhiều bài hát), nên chuyển sang chế độ nhận biên nhận
accept_mode=asyncthay vì chờ đồng bộ lâu; thời gian chuẩn bị tuỳ số lượng và nguồn tư liệu.
Bước tiếp theo
Nếu khi phản hồi trả về mà bài hát chưa xong, hãy dùng API truy vấn bài hát để lấy kết quả cuối cùng.
Ví dụ tích hợp Node/Electron
Nếu bạn tích hợp tạo nhạc tiêu chuẩn trong tiến trình chính của Electron, máy chủ Node.js hoặc ứng dụng desktop, đây là luồng khuyến nghị:
- Gọi
POST /api/music/createđể tạo tác vụ. - Đọc
song_idhoặcidtừ phản hồi. - Gọi
POST /api/music/querymỗi 2 giây để kiểm tra trạng thái. - Khi kết quả tra về có
audio_urlthì coi như đã tạo xong.
Đừng dùng lại các đường dẫn cũ POST /api/generate hay GET /api/clip?id=...; chúng không thuộc bề mặt tích hợp công khai được khuyến nghị hiện nay.
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);
Trong dự án thực tế, hãy để khóa API trong biến môi trường của máy chủ, cấu hình ứng dụng desktop hoặc kho lưu trữ an toàn — tuyệt đối không đặt trong mã front-end và không commit vào kho mã.
Lấy khóa API
Tạo khóa API trong bảng điều khiển sau khi đăng ký. Mỗi lần tạo tốn 0,6 ¥ và trả về 2 bản nhạc, tải xuống không giới hạn và không cần số điện thoại.
Lấy khóa API Quay lại tổng quan