API de geração no modo simples
Descrição do endpoint
A geração no modo simples serve para transformar uma descrição de uma frase em uma música completa. O serviço escreve a letra, a melodia, o arranjo e o vocal a partir da sua descrição.
Endpoint: POST /api/music/create
Cobrança: Pago, atualmente ¥0,6 por chamada por padrão. Cada chamada costuma devolver 2 músicas; o valor realmente cobrado segue a configuração de preços atual do back-office.
Max Mode / Variety: este endpoint aceita os parâmetros opcionais max_mode e variety (0-4). Com
max_mode ligado, esta chamada é cobrada em 2× o preço (¥0,6 → ¥1,2 por chamada); variety não custa
nada a mais. O que significam e como enviá-los está na seção "Parâmetros avançados" da
Visão geral da nova API.
Modelo recomendado: suno-v6
Tempos de espera e timeouts (importante): este é um endpoint síncrono — o pedido só é aceito e entregue à geração quando a resposta chega. Pelo medido, a maioria das requisições responde em 1-3 segundos, cerca de 10% leva mais de 30 segundos e a mais longa fica em torno de 230 segundos. Defina o timeout do cliente em 300 segundos ou mais; não receber resposta não significa que nada foi gerado, e não repita logo após um timeout (isso duplica o pedido e cobra de novo). Se a conexão caiu, confirme depois com
GET /api/music/songs. Veja "Tempos de espera e configuração de timeout" na Visão geral da nova API.
Parâmetros da requisição
Headers
| Parâmetro | Tipo | Obrigatório | Observações |
|---|---|---|---|
| Authorization | string | sim | Bearer YOUR_API_KEY |
| Content-Type | string | sim | application/json |
Parâmetros do body
| Parâmetro | Tipo | Obrigatório | Padrão | Observações |
|---|---|---|---|---|
| description | string | sim | - | Descrição da música, em qualquer idioma; no máximo 3000 caracteres (mais devolve 400 e não é cobrado) |
| model | string | não | suno-v6 | Nome de modelo para o cliente: suno-v6, suno-v6-wild ou suno-v6-mini |
| instrumental | boolean | não | false | Se a música é somente instrumental |
| wait_completion | boolean | não | false | Se deve esperar a geração terminar antes de responder |
| references | array | não | - | Lista de material de referência, que pode carregar músicas de referência / vozes legadas / imagens de referência; no máximo 5 músicas, 1 voz e 1 imagem. Veja "Material de referência references (opcional)" abaixo |
Exemplos de requisição
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": "uma canção pop em mandarim animada sobre o verão à beira-mar",
"instrumental": false,
"wait_completion": false
}'
Material de referência references (opcional)
references é um array que anexa "material de referência" a esta geração. É totalmente opcional (omitir comporta-se exatamente como antes) e você pode anexar apenas um tipo ou qualquer combinação.
Tipos de elemento
| type | Campo obrigatório | Campos opcionais | Máximo | Observações |
|---|---|---|---|---|
song |
song_id |
style_prompt, lyrics, duration_s |
5 | Música de referência; o song_id vem da API de consulta e histórico de músicas e a música já deve estar concluída |
voice |
voice_id |
- | 1 | Voz legada; o voice_id vem da API de clonagem de voz e geração com voz |
image |
base64 |
- | 1 | Imagem de referência; envie conteúdo base64 no formato data:image/jpeg;base64,... |
Regras
- A ordem das músicas de referência é a ordem semântica: passe-as na ordem que você quer expressar (por exemplo "melodia da primeira, vocal da segunda").
style_prompt/lyrics/duration_spodem ser omitidos; a plataforma preenche a partir das informações da música, e o que você enviar prevalece.- Em músicas puramente instrumentais,
lyricspode ser""ou"[Instrumental]". - As imagens de referência aceitam
jpeg/png/webp, até 10MB cada, enviadas junto ao corpo em base64. - Ao anexar várias músicas de referência, use também
accept_mode=async(ver "Modo de recibo de aceite" acima): o serviço precisa preparar o material primeiro, então a espera síncrona pode ser longa.
Exemplo: duas músicas de referência
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": "combine estas ideias em uma única música",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "song", "song_id": "a90438d2-35fc-4443-88f4-56531e6e5d24" }
]
}'
Exemplo: música de referência + voz legada
{
"model": "suno-v6",
"description": "cante estas ideias com esta voz",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "voice", "voice_id": "5813cbe1-36f1-414a-a9a8-4d399dfeb292" }
]
}
Exemplo: música de referência + imagem de referência
{
"model": "suno-v6",
"description": "capture o clima desta imagem",
"references": [
{ "type": "song", "song_id": "43eb711d-81f8-4e72-a68e-b2498bac88f9" },
{ "type": "image", "base64": "data:image/jpeg;base64,/9j/4AAQ..." }
]
}
Erros de parâmetros
Esses casos devolvem HTTP 400, bloqueados antes de qualquer cobrança, então não custam nada:
| Caso | Mensagem de erro |
|---|---|
| Mais de 5 músicas de referência | references supports at most 5 song references |
| Mais de 1 voz | references supports at most 1 voice reference |
| Mais de 1 imagem de referência | references supports at most 1 image reference |
type inválido |
references[0].type must be one of song, voice, image |
Música sem song_id |
references[0].song_id is required |
| Música ainda não concluída | references[0].song_id must be a real completed clip |
| A mesma música repetida | references[0].song_id is duplicated |
O número em
references[0]é o índice daquele elemento no array, então o item que falhou é fácil de localizar.
Resposta
Um array de músicas, normalmente com 2 tarefas ou músicas.
[
{
"song_id": "clip_id",
"song_title": "Brisa do mar de verão",
"status": "pending",
"description": "uma canção pop em mandarim animada sobre o verão à beira-mar",
"audio_url": "",
"cover_url": "",
"video_url": "",
"model_version": "suno-v6",
"generation_type": "generate",
"created_at": "2026-05-21T10:00:00Z"
}
]
Modo de recibo de aceite (opcional, recomendado para clientes que não devem manter conexões longas)
Por padrão este endpoint é síncrono: a chegada da resposta é o que significa que o pedido foi aceito, e as esperas medidas podem chegar a uns 230 segundos. Se o seu cliente não deve manter uma conexão longa, ligue o modo de recibo de aceite — qualquer um dos dois serve:
- adicionar
"accept_mode": "async"ao corpo da requisição - adicionar o cabeçalho
X-Accept-Mode: async
Com ele ligado, o endpoint devolve HTTP 202 imediatamente, o que significa apenas "aceito e na fila de geração", enquanto a geração continua em segundo plano:
{
"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" }
]
}
}
A fase de aceite não devolve um
song_id. Ainda não existe um ID de música real, e nemrequest_idnemtasks[].indexsão IDs de música — não os guarde comosong_id. Osong_idreal aparece na consulta de progresso abaixo.
Consultar o progresso do aceite
Endpoint: GET /api/music/requests/{request_id} (grátis, autentica com a mesma chave de 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" }
]
}
}
O que cada valor de status significa:
| status | Significado |
|---|---|
queued |
Aceito, ainda sem vínculo com músicas específicas (tasks pode ser um array vazio) |
processing |
Enviado para geração |
partial |
Uma das duas já terminou |
completed |
As duas terminaram, tasks[].song_id é legível |
failed |
O envio falhou, o valor foi totalmente reembolsado e error_message indica o motivo |
Cada tarefa também tem seu próprio tasks[].status, com os mesmos valores da API de consulta de músicas:
pending (enviada, gerando), processing, completed, failed. Os itens de tarefa também podem trazer title,
duration e um audio_url já registrado; se faltar algo, significa apenas que ainda não foi gerado.
Quando tiver o song_id real, siga com a API de consulta de músicas ou os endpoints de download.
Exemplo em 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": "uma canção pop animada", "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
Compatibilidade e observações
- Sem
accept_mode, o comportamento é exatamente o de antes: espera síncrona, devolvendo200e um array de músicas. As integrações existentes não precisam mudar nada. - Este interruptor hoje só funciona em
POST /api/music/createePOST /api/music/create/custom; os outros endpoints de geração ainda não o aceitam. - Envie também um
Idempotency-Key(sua própria string única, ≤128 caracteres): enviar a mesma chave duas vezes é aceito uma só vez, uma repetição devolve o mesmo recibo e nada é cobrado em dobro. Isso importa ainda mais no modo assíncrono. - Com
accept_mode=async,wait_completioné ignorado (o recibo volta na hora, sem esperar as músicas). - O valor continua sendo pré-consumido quando o pedido é aceito; uma geração falha é reembolsada integralmente de forma automática.
- Limite do campo de texto:
descriptionaceita no máximo 3000 caracteres (contados em caracteres Unicode, um caractere Han conta como 1). Texto mais longo devolve HTTP400direto, nunca entra em geração e não é cobrado, e a mensagem de erro traz o comprimento medido, por exemplodescription must not exceed 3000 characters; received 4120. Este endpoint não tem campos de letra/estilo; para isso veja "Limite do campo de texto" na API de geração no modo personalizado. As convenções gerais estão em "Limites de campos de texto" da Visão geral da nova API. - Sem
references, comportamento, preço e resposta são exatamente os de antes: as integrações existentes não precisam mudar nada. - Quando houver material de referência (especialmente várias músicas), prefira o modo de recibo
accept_mode=asynca uma longa espera síncrona; quanto tempo o material leva para ser preparado depende da quantidade e da origem.
Próximos passos
Se as músicas não tiverem terminado quando a resposta chegar, use a API de consulta de músicas para obter o resultado final.
Exemplo de integração em Node/Electron
Se você integra geração padrão dentro do processo principal do Electron, de um servidor Node.js ou de um cliente de desktop, este é o fluxo recomendado:
- Chame
POST /api/music/createpara criar a tarefa de geração. - Leia
song_idouidda resposta. - Chame
POST /api/music/querya cada 2 segundos para conferir o status. - Considere a geração concluída assim que
audio_urlaparecer no resultado da consulta.
Pare de usar os caminhos antigos POST /api/generate ou GET /api/clip?id=...; eles não fazem parte da superfície pública de integração recomendada atualmente.
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);
Em projetos reais, guarde a chave de API em uma variável de ambiente do servidor, nas configurações de um cliente de desktop ou em armazenamento seguro — nunca em código de front-end nem em um repositório.
Obter uma chave de API
Crie uma chave de API no console após o cadastro. Cada geração custa ¥0,6 e devolve 2 faixas, os downloads são ilimitados e não é preciso número de telefone.
Obter chave de API Voltar à visão geral