歌詞生成
Mureka または Suno で短いプロンプトから歌詞を生成し、完成した候補をタスクから読み取ります。
Lyrics API は短いプロンプトから完成した歌詞を生成します。Music API と同じ 2 つのプロバイダー——Mureka と Suno——を使い、リクエストごとに provider フィールドで選択します。すべてのエンドポイントは https://api.marswave.ai/openapi/v1/lyrics 配下にあり、Authorization: Bearer $LISTENHUB_API_KEY で認証します。
生成は常にタスクとして実行されます。POST /v1/lyrics/generate が返すのは taskId とステータスであり、歌詞そのものではありません。完成した歌詞は GET /v1/lyrics/tasks/{taskId} から読み取ります。
すべてのレスポンスは { "code": 0, "message": "", "data": { ... } } の形にラップされます。code が 0 以外ならエラーです——エラーハンドリングを参照してください。以下の例はすべて data からフィールドを読み取ります。
プロバイダー
provider は mureka、suno、default(Mureka に解決されます)のいずれかです。どれを選んでもリクエストの形は変わらず、タスクが終了状態に到達するまでの速さと、返る歌詞候補の数が変わります。
| プロバイダー | 実行方式 | 作成レスポンスの status | 候補数 |
|---|---|---|---|
mureka | 同期。作成リクエストが上流の結果を待ちます。 | success——すでに終了状態 | 1 件 |
suno | コールバック方式。上流が完了時に結果を送り返します。 | pending | 通常 2 件 |
default | サービスの既定プロバイダー、すなわち Mureka に解決されます。 | mureka と同じ | 1 件 |
provider を省略することは default を送ることと同じです。タスクには実際に実行したプロバイダーが記録されるため、default で作成したタスクは mureka として読み出されます。
タスクのライフサイクル
status は pending → generating → success または failed と遷移します。2 つのプロバイダーはこの状態機械を共有し、終了状態に至るまでの滞在時間だけが異なります。
POST /v1/lyrics/generateが202とtaskId、初期statusを返します。- Mureka では初期ステータスがすでに
successです——タスクを一度取得すれば歌詞を読めます。Suno ではpendingなので、GET /v1/lyrics/tasks/{taskId}を数秒おきにポーリングします。 successならvariantsを、failedならerrorMessageを読み取ります。
Suno には歌詞用の照会エンドポイントがないため、success に至る経路はコールバックだけです。Suno のタスクは 30 分間更新がないと failed になり、クレジットは全額返還されます。その後は復旧しません。
歌詞を生成する
POST /v1/lyrics/generate
プロンプトから歌詞タスクを開始します。JSON を送信します。
curl -X POST "https://api.marswave.ai/openapi/v1/lyrics/generate" \
-H "Authorization: Bearer $LISTENHUB_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A hopeful anthem about leaving a small town at dawn",
"provider": "suno"
}'const response = await fetch(
'https://api.marswave.ai/openapi/v1/lyrics/generate',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
prompt: 'A hopeful anthem about leaving a small town at dawn',
provider: 'suno',
}),
}
);
const { data } = await response.json();
console.log('Task:', data.taskId, data.status);import os
import requests
response = requests.post(
'https://api.marswave.ai/openapi/v1/lyrics/generate',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
json={
'prompt': 'A hopeful anthem about leaving a small town at dawn',
'provider': 'suno',
},
)
data = response.json()['data']
print('Task:', data['taskId'], data['status'])リクエストパラメータ:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
prompt | string | はい | 歌詞の題材。最大 200 文字——超過するとバリデーション段階で拒否され、クレジットは確保されません |
provider | string | いいえ | mureka、suno、default のいずれか。既定は default で、Mureka に解決されます |
レスポンス例:
{
"code": 0,
"message": "",
"data": {
"taskId": "68e780390fc5c9a54f695a7e",
"status": "pending"
}
}作成レスポンスに含まれるのは taskId と status だけで、どちらのプロバイダーでも歌詞は含まれません。タスクがすでに success である Mureka でも同様です。歌詞はタスクを取得して variants から読み取ります。
このエンドポイントはレート制限に記載された作成リクエストの制限にカウントされます。
タスク一覧を取得する
GET /v1/lyrics/tasks
歌詞タスクを新しい順に一覧します。
curl -X GET "https://api.marswave.ai/openapi/v1/lyrics/tasks?page=1&pageSize=20&status=success" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
'https://api.marswave.ai/openapi/v1/lyrics/tasks?page=1&pageSize=20',
{ headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const { data } = await response.json();
console.log(`${data.items.length} of ${data.total} tasks`);import os
import requests
response = requests.get(
'https://api.marswave.ai/openapi/v1/lyrics/tasks',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
params={'page': 1, 'pageSize': 20},
)
data = response.json()['data']
print(len(data['items']), 'of', data['total'], 'tasks')クエリパラメータ:
| フィールド | 型 | 必須 | 説明 |
|---|---|---|---|
page | integer | いいえ | ページ番号、最小 1。既定は 1 |
pageSize | integer | いいえ | 1 ページあたりの件数、1–100。既定は 20 |
status | string | いいえ | pending、generating、success、failed で絞り込み |
data が保持するのは配列そのものではなく 1 ページ分のデータです。items にタスク(構造は単一タスクを取得するを参照)が入り、併せて page、pageSize、total が返ります。
単一タスクを取得する
GET /v1/lyrics/tasks/{taskId}
単一のタスクを取得します。Suno に送信した後にポーリングするのはこのエンドポイントで、どちらのプロバイダーでも歌詞はここから読み取ります。
curl -X GET "https://api.marswave.ai/openapi/v1/lyrics/tasks/{taskId}" \
-H "Authorization: Bearer $LISTENHUB_API_KEY"const response = await fetch(
`https://api.marswave.ai/openapi/v1/lyrics/tasks/${taskId}`,
{ headers: { 'Authorization': `Bearer ${process.env.LISTENHUB_API_KEY}` } }
);
const { data } = await response.json();
console.log('Status:', data.status);
if (data.status === 'success') console.log(data.variants[0].text);import os
import requests
response = requests.get(
f'https://api.marswave.ai/openapi/v1/lyrics/tasks/{task_id}',
headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
)
data = response.json()['data']
print('Status:', data['status'])
if data['status'] == 'success':
print(data['variants'][0]['text'])レスポンス例:
{
"code": 0,
"message": "",
"data": {
"id": "68e780390fc5c9a54f695a7e",
"provider": "suno",
"status": "success",
"params": {
"prompt": "A hopeful anthem about leaving a small town at dawn"
},
"variants": [
{
"title": "Dawn Highway",
"text": "Suitcase on the porch light\nEngine turning over slow\n...",
"status": "complete",
"errorMessage": ""
},
{
"title": "First Light Out",
"text": "The bus stop hums awake\nI count the streetlamps one last time\n...",
"status": "complete",
"errorMessage": ""
}
],
"creditCost": 2,
"errorMessage": "",
"createdAt": 1730000000000,
"updatedAt": 1730000021000
}
}タスクレスポンスのフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
id | string | タスク ID |
provider | string | 実際にタスクを実行したプロバイダー:mureka または suno |
status | string | pending、generating、success、failed |
params.prompt | string | 送信したプロンプトのエコー |
variants | array | 生成された歌詞。タスクが成功するまでは空 |
variants[].title | string | 提案された曲タイトル |
variants[].text | string | 生成された歌詞の本文 |
variants[].status | string | complete または failed。成功したタスクでも個別の候補が失敗していることがあります |
variants[].errorMessage | string | その候補が失敗した理由。それ以外は空 |
creditCost | number | 消費したクレジット。タスクが成功するまでは 0 のまま |
errorMessage | string | 失敗の理由(status が failed のときのみ) |
createdAt | number | 作成時刻(ミリ秒タイムスタンプ) |
updatedAt | number | 最終更新時刻(ミリ秒タイムスタンプ) |
タスクは所有者ごとに分離されています。他のアカウントのタスクを取得しようとすると、タスクではなくエラーが返ります。
クレジット
歌詞生成は 1 リクエストあたり固定 2 クレジットです——プロバイダーによらず同じで、返る候補の数にも依存しません。
クレジットはタスク作成時に予約され、成功時に確定します。上流がリクエストを拒否した場合、タスクが失敗した場合、Suno のタスクがタイムアウトした場合は全額返還されます。したがって success に到達しなかったタスクには費用が発生せず、creditCost は 0 のままです。
現在の残高は GET /v1/user/subscription で確認でき、クレジットの全体像は料金を参照してください。
SDK と CLI
API キー経由では、Lyrics API は現時点で HTTP 直接呼び出しのみです。OpenAPIClient SDK も listenhub openapi CLI も、これらのエンドポイントをまだラップしていません。listenhub lyrics コマンドと ListenHubClient の歌詞メソッドは同じエンドポイントを呼びますが、API キーではなくアカウントログインで認証します。