ドキュメント
音楽生成
Suno V5 / V5.5によるテキストからの音楽生成 — ボーカル、歌詞、スタイルを制御できます。API形式は2種類あります。トラックの準備ができるまで待機する単発の同期エンドポイントと、本番環境向けの送信・ポーリング用の非同期エンドポイントのペア(署名付きwebhook対応)です。
エンドポイント:POST /v1/audio/music(同期、最初に説明)、およびPOST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}(非同期、本番環境に推奨)。各リクエストで2つのトラックを生成し、生成には約1〜3分かかります。料金:生成リクエスト1回あたり、suno-v5では$0.09、suno-v5-5では$0.09 — 両方のトラックを合わせて1回分として課金します。前払い残高から請求され、生成に失敗した場合は課金されません。
クイックスタート(同期)
promptとSunoモデルを指定します。リクエストは2つのトラックが準備できるまで接続を維持し、その後、永続的なURLを返します。
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"))パラメーター
| パラメーター | 種類 | 注記 |
|---|---|---|
model | 文字列(必須) | 音楽モデルのスラッグ — suno-v5またはsuno-v5-5。 |
prompt | 文字列(必須) | 音楽の説明(カスタムモードでは歌詞)。 |
instrumental | bool | true = ボーカルなし。デフォルトはfalse。 |
customMode | bool | Sunoの高度なモード — 構成/歌詞/スタイルを明示的に指定します。 |
style | string | スタイル/ジャンルのヒント。例:「lofi, jazz, chill」。 |
title | string | トラックのタイトル。 |
webhook_url | string (https) | 非同期のみ — 署名付きの最終イベントをここに送信します。Webhooksを参照してください。 |
音楽モデル
| スラッグ | プロバイダー | 注記 |
|---|---|---|
suno-v5 | Suno | Suno V5 — ボーカル、歌詞、スタイルのブレンドに対応。 |
suno-v5-5 | Suno | Suno V5.5 — 最新モデル。より高忠実度で、長い音楽を生成できます。 |
最新の一覧と呼び出しごとの料金は/modelsで確認してください。
非同期API(送信 + ポーリング)
エンドポイント:POST /v1/audio/music/jobs + GET /v1/audio/music/jobs/{id}。非同期動画APIと同じ形式のため、ポーリング/webhookのコードを複数のモダリティで共通利用できます。
同期エンドポイントはHTTP接続を数分間維持します。スクリプトでは便利ですが、モバイルでは信頼性に欠けます。非同期APIはすぐにmsc_* IDを返します。statusがcompletedまたはfailedになるまで、GET /v1/audio/music/jobs/{id}をポーリングしてください。同じモデル、同じ料金、同じ永続的なCDN URLを利用できます。
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"])レスポンスの形式
| フィールド | 種類 | 注記 |
|---|---|---|
id | string | msc_ |
object | string | "music". |
status | string | queued | in_progress | completed | failed。 |
model | string | 送信したモデルのスラッグ。 |
created_at | int | 送信が受け付けられた時刻(Unix秒)。 |
completed_at | int | null | 終了した時刻(Unix秒)。処理中はnull。 |
expires_at | int | 結果が削除される時刻(Unix秒、約30日後)。 |
progress | int | 終了するまでは0、終了後は100。 |
output | object | null | 完了時: {tracks[], archived}。 |
output. | array | 各項目: {url, stream_url, image_ |
error | object | null | 失敗時: {code, message}。 |
ヘッダーと規約
Idempotency-Key(任意、≤128文字) — 同一アカウントで同じキーを使って再度送信すると、重複タスクは作成されず、元のタスクが返されます。POST /v1/audio/music/jobsは、新規送信時に202 Acceptedを返し、冪等性キーを使って結果を再送する場合は200 OKを返します。GETは所有者ごとにスコープされます。他のアカウントに属するタスクを照会すると、404が返されます。- 推奨するポーリング間隔:5秒。最大30秒まで段階的に延ばします。
Webhook
送信時にwebhook_url(https)を渡すと、タスクが終了した時点でKunavoが署名付きのmusic.completed / music.failedイベントをPOSTします。リトライとバックオフを伴って配信されます。イベントのdataフィールドは、上記のGETペイロードと完全に同じです。
# 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... } }{timestamp}.{rawBody}に対するHMAC-SHA256で、X-Kunavo-Webhook-Signature: sha256=<hex>として送信されます。動画webhookと同じ方式のため、両方に同じ検証コードを使えます。どちらを使うか
| 同期 /v1/ | 非同期 /v1/ | |
|---|---|---|
| 最適な用途 | 単発のスクリプト、ノートブック | 本番環境、モバイル、webhook |
| ネットワーク | 接続を1〜3分維持 | 数秒で送信し、ポーリングするかプッシュ通知を受け取れます |
| 障害からの復旧 | レスポンスを失う = 結果を失う | 有効期限前であれば、いつでもIDを再照会できます |
| Webhook | — | 署名付きmusic. |
レスポンスと保存先
各トラックのurl(音声)とimage_url(カバーアート)は永続的なfiles.kunavo.comリンクです。Kunavoはすべての結果を自社CDNにアーカイブするため、Sunoの生URLと異なり期限切れになりません。stream_urlはSunoの元のストリーミングリンクで、すぐに再生する場合に便利です。すべてのトラックは/app/assetsにも表示されます。
output.archivedがfalseとなり、URLはSunoの一時リンク(約24時間で期限切れ)にフォールバックします。その場合は、ご自身で再ホストしてください。