Documentação

Documentação

Geração de música

Geração de música a partir de texto com Suno V5 / V5.5 — vocais, letras e controle de estilo. Dois formatos de API: um endpoint síncrono de etapa única que aguarda até as faixas ficarem prontas e um par assíncrono de envio e consulta (com webhooks assinados) para produção.

Endpoints: POST /v1/audio/music (síncrono, apresentado primeiro) e POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id} (assíncrono, recomendado para produção). Cada solicitação gera duas faixas; a geração leva cerca de 1–3 minutos. Preço: $0.09 por solicitação de geração em suno-v5, $0.09 em suno-v5-5 — as duas faixas são cobradas uma vez, com saldo pré-pago, e uma geração malsucedida não é cobrada.

Início rápido (síncrono)

Envie um prompt e um modelo Suno. A solicitação permanece aberta até as duas faixas ficarem prontas e, então, retorna as URLs permanentes delas.

import requests

# Synchronous: one request blocks until the tracks are ready (1-3 min).
resp = requests.post(
    "https://api.kunavo.com/v1/audio/music",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "model": "suno-v5",
        "prompt": "upbeat lofi hip hop for late-night coding, mellow piano",
        "instrumental": True,
    },
    timeout=600,  # generation can take a few minutes
)
# Suno returns ~2 tracks per request.
for track in resp.json()["data"]:
    print(track["url"], track.get("image_url"))
As renderizações do Suno levam de 1 a 3 minutos. O endpoint síncrono mantém a conexão aberta no servidor até as faixas ficarem prontas, com um limite de consulta de cerca de 6 minutos; portanto, configure um tempo limite correspondente no cliente HTTP (≥600s). Para qualquer processo mais demorado, tráfego de produção ou redes móveis / instáveis, prefira a API assíncrona — o envio retorna em segundos.

Parâmetros

ParâmetroTipoObservações
modelstring (obrigatório)Um slug de modelo de música — suno-v5 ou suno-v5-5.
promptstring (obrigatório)Descrição da música (ou a letra, no modo personalizado).
instrumentalbooltrue = sem vocais. Padrão: false.
customModeboolModo Suno avançado — controle explicitamente a estrutura / letra / estilo.
stylestringIndicação de estilo / gênero, por exemplo, "lofi, jazz, chill".
titlestringTítulo da faixa.
webhook_urlstring (https)Somente no modo assíncrono — envie aqui um evento terminal assinado. Consulte Webhooks.

Modelos de música

SlugProvedorObservações
suno-v5SunoSuno V5 — vocais, letras e combinação de estilos.
suno-v5-5SunoSuno V5.5 — mais recente, com maior fidelidade e gerações mais longas.

Consulte /models para ver a lista atual e os preços por chamada.

API assíncrona (envio + consulta)

Endpoints: POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}. Segue o padrão da API assíncrona de vídeo, então o mesmo código de consulta / webhook funciona em diferentes modalidades.

O endpoint síncrono mantém uma conexão HTTP aberta por minutos — conveniente para scripts, mas pouco confiável em dispositivos móveis. O par assíncrono retorna imediatamente um ID msc_*; consulte GET /v1/audio/music/jobs/{id} até que status seja completed ou failed. Mesmos modelos, mesmos preços e mesmas URLs permanentes de CDN.

import requests, time

# 1. Submit — returns immediately with a msc_ task id. No long-lived connection.
submit = requests.post(
    "https://api.kunavo.com/v1/audio/music/jobs",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        # Optional: retrying with the same key inside ~24h returns the
        # original task rather than submitting again.
        "Idempotency-Key": "my-song-uuid",
    },
    json={
        "model": "suno-v5",
        "prompt": "dreamy synthwave with a driving bassline",
        "title": "Midnight Drive",
    },
    timeout=60,
).json()

task_id = submit["id"]              # "msc_abc..."
status  = submit["status"]          # "queued"

# 2. Poll until terminal. Recommended cadence: 5s, backing off to 30s.
while status not in ("completed", "failed"):
    time.sleep(5)
    r = requests.get(
        f"https://api.kunavo.com/v1/audio/music/jobs/{task_id}",
        headers={"Authorization": f"Bearer {API_KEY}"},
        timeout=30,
    ).json()
    status = r["status"]

if status == "failed":
    raise RuntimeError(r["error"]["message"])
for track in r["output"]["tracks"]:
    print(track["url"])

Formato da resposta

CampoTipoObservações
idstringID de tarefa com prefixo msc_.
objectstring"music".
statusstringqueued | in_progress | completed | failed.
modelstringO slug do modelo enviado.
created_atintSegundos Unix em que aceitamos o envio.
completed_atint | nullSegundos Unix em que a tarefa terminou — null enquanto estiver pendente.
expires_atintSegundos Unix após os quais o resultado é removido (~30 dias).
progressint0 até a tarefa terminar; depois, 100.
outputobject | null{tracks[], archived} quando concluído.
output.tracksarrayCada um: {url, stream_url, image_url}. url / image_url são links permanentes de CDN.
errorobject | null{code, message} quando falha.

Cabeçalhos e convenções

  • Idempotency-Key (opcional, ≤128 caracteres) — se você enviar duas vezes a mesma chave na mesma conta, receberá a tarefa original em vez de criar uma duplicata.
  • POST /v1/audio/music/jobs retorna 202 Accepted em um novo envio e 200 OK quando uma chave de idempotência reproduz um resultado.
  • GET é restrito ao proprietário: consultar uma tarefa pertencente a outra conta retorna 404.
  • Frequência de consulta recomendada: 5 s, aumentando gradualmente até 30 s.

Webhooks

Envie webhook_url (https) ao submeter a solicitação, e Kunavo fará um POST de um evento assinado music.completed / music.failed assim que a tarefa terminar — com entrega e novas tentativas com intervalo crescente. O campo data do evento corresponde exatamente ao conteúdo da solicitação GET acima.

# Pass webhook_url on submit to be pushed a signed event on terminal —
# instead of (or alongside) polling:
#   {"model": "suno-v5", "prompt": "...", "webhook_url": "https://you.com/hook"}
#
# Verify the HMAC signature on your receiver (Flask shown):
import hmac, hashlib
from flask import request, abort

def verify(secret: str) -> dict:
    ts  = request.headers["X-Kunavo-Webhook-Timestamp"]
    sig = request.headers["X-Kunavo-Webhook-Signature"]   # "sha256=<hex>"
    raw = request.get_data(as_text=True)
    expected = "sha256=" + hmac.new(
        secret.encode(), f"{ts}.{raw}".encode(), hashlib.sha256
    ).hexdigest()
    if not hmac.compare_digest(expected, sig):
        abort(401)
    return request.get_json()

# Event body:
#   { "id": "evt_...", "object": "event",
#     "type": "music.completed" | "music.failed",
#     "created_at": 1700000000,
#     "data": { ...the GET /v1/audio/music/jobs/{id} payload... } }
A assinatura é HMAC-SHA256 sobre {timestamp}.{rawBody}, enviada como X-Kunavo-Webhook-Signature: sha256=<hex>. O mesmo método dos webhooks de vídeo, então um único verificador atende a ambos.

Quando usar cada um

Síncrono /v1/audio/musicAssíncrono /v1/audio/music/jobs
Melhor paraScripts e notebooks de uso pontualProdução, dispositivos móveis e webhooks
RedeMantém a conexão aberta por 1–3 minEnvie em segundos; consulte ou receba a atualização automaticamente
Recuperação de falhasPerder a resposta = perder o resultadoConsulte o ID novamente a qualquer momento antes de expires_at
Webhooks—Eventos music.completed / music.failed assinados

Resposta e armazenamento

O url (áudio) e o image_url (arte da capa) de cada faixa são links permanentes files.kunavo.com — Kunavo arquiva cada resultado em sua própria CDN, então, ao contrário das URLs brutas do Suno, eles nunca expiram. stream_url é o link original de streaming do Suno (útil para reprodução instantânea). Cada faixa também aparece em /app/assets.

Se o arquivamento falhar, output.archived será false e as URLs voltarão a ser links temporários do Suno (que expiram após cerca de 24 h) — nesse caso, hospede-os novamente por conta própria.

Próximos passos