Dokumentasi
Pembuatan musik
Konversi teks ke musik dengan Suno V5 / V5.5 — vokal, lirik, dan kontrol gaya. Dua bentuk API: endpoint sinkron sekali panggil yang menunggu hingga trek siap, serta pasangan API asinkron submit-and-poll (dengan webhook bertanda tangan) untuk penggunaan produksi.
Endpoint: POST /v1/audio/music (sinkron, dibahas terlebih dahulu), serta POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id} (asinkron, disarankan untuk penggunaan produksi). Setiap permintaan menghasilkan dua trek; proses pembuatan berlangsung sekitar 1–3 menit. Harga: $0.09 per permintaan pembuatan di suno-v5, $0.09 di suno-v5-5 — kedua trek ditagih sekali, dari saldo prabayar, dan pembuatan yang gagal tidak ditagih.
Mulai cepat (sinkron)
Kirim prompt dan model Suno. Permintaan akan terus terbuka hingga kedua trek siap, lalu mengembalikan URL permanennya.
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"))Parameter
| Parameter | Tipe | Catatan |
|---|---|---|
model | string (wajib) | Slug model musik — suno-v5 atau suno-v5-5. |
prompt | string (wajib) | Deskripsi musik (atau lirik, dalam mode kustom). |
instrumental | bool | true = tanpa vokal. Default false. |
customMode | bool | Mode Suno lanjutan — atur struktur / lirik / gaya secara eksplisit. |
style | string | Petunjuk gaya / genre, misalnya "lofi, jazz, chill". |
title | string | Judul trek. |
webhook_url | string (https) | Khusus asinkron — kirim event terminal bertanda tangan ke sini. Lihat Webhooks. |
Model musik
| Slug | Penyedia | Catatan |
|---|---|---|
suno-v5 | Suno | Suno V5 — vokal, lirik, dan perpaduan gaya. |
suno-v5-5 | Suno | Suno V5.5 — terbaru, dengan fidelitas lebih tinggi dan generasi yang lebih panjang. |
Periksa /models untuk daftar langsung dan harga per panggilan.
API asinkron (submit + poll)
Endpoint: POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}. Mengikuti pola API video asinkron, sehingga kode polling / webhook yang sama berfungsi untuk semua modalitas.
Endpoint sinkron mempertahankan koneksi HTTP terbuka selama beberapa menit — praktis untuk skrip, tetapi tidak andal di jaringan seluler. Pasangan endpoint asinkron segera mengembalikan ID msc_*; lakukan polling pada GET /v1/audio/music/jobs/{id} hingga status bernilai completed atau failed. Model, harga, dan URL CDN permanen tetap sama.
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"])Bentuk respons
| Kolom | Tipe | Catatan |
|---|---|---|
id | string | ID tugas berawalan msc_. |
object | string | "music". |
status | string | queued | in_progress | completed | failed. |
model | string | Slug model yang Anda kirim. |
created_at | int | Detik Unix saat kami menerima permintaan. |
completed_at | int | null | Detik Unix saat status menjadi terminal — null selama masih tertunda. |
expires_at | int | Detik Unix, 30 hari setelah pengiriman: tugas dapat di-polling setidaknya sampai saat itu. URL hasilnya tidak kedaluwarsa. |
progress | int | 0 hingga status terminal, lalu 100. |
output | object | null | {tracks[], archived} saat selesai. |
output. | array | Masing-masing: {url, stream_url, image_url}. url / image_url adalah tautan CDN permanen. |
error | object | null | {code, message} saat gagal. |
Header dan konvensi
Idempotency-Key(opsional, ≤128 karakter) — mengirimkan permintaan dua kali dengan kunci yang sama pada akun yang sama akan mengembalikan tugas asli, bukan membuat duplikat.POST /v1/audio/music/jobsmengembalikan 202 Accepted pada pengiriman baru dan 200 OK saat kunci idempotensi memutar ulang hasil.GETdibatasi pada pemilik: permintaan untuk tugas milik akun lain mengembalikan 404.- Jeda polling yang disarankan: 5 s, bertambah secara bertahap hingga 30 s.
Webhook
Saat mengirim, berikan webhook_url (https), lalu Kunavo mengirim POST event music.completed / music.failed bertanda tangan segera setelah tugas mencapai status terminal — dengan pengiriman ulang dan jeda bertahap. Kolom data pada event persis sama dengan payload GET di atas.
# 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... } }HMAC-SHA256 atas {timestamp}.{rawBody}, dan dikirim sebagai X-Kunavo-Webhook-Signature: sha256=<hex>. Caranya sama dengan webhook video, sehingga satu verifier dapat menangani keduanya.Kapan menggunakan yang mana
| Sinkron /v1/ | Asinkron /v1/ | |
|---|---|---|
| Paling cocok untuk | Skrip sekali jalan, notebook | Produksi, seluler, webhook |
| Jaringan | Mempertahankan koneksi selama 1-3 menit | Kirim dalam hitungan detik; lakukan polling atau terima dorongan |
| Pemulihan kegagalan | Kehilangan respons = kehilangan hasil | Kirim ulang kueri ID kapan saja sebelum expires_at |
| Webhook | — | music. |
Respons dan penyimpanan
url (audio) dan image_url (sampul) untuk setiap trek adalah tautan permanen files.kunavo.com — Kunavo mengarsipkan setiap hasil ke CDN miliknya sendiri, sehingga berbeda dari URL Suno mentah, tautan tersebut tidak pernah kedaluwarsa. stream_url adalah tautan streaming asli Suno (berguna untuk pemutaran langsung). Setiap trek juga muncul di /app/assets.
output.archived bernilai false dan URL akan beralih ke tautan sementara Suno (yang kedaluwarsa setelah sekitar 24 jam) — jika demikian, host sendiri hasilnya.