ListenHubDocs
API リファレンス

歌詞生成

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 つのプロバイダーはこの状態機械を共有し、終了状態に至るまでの滞在時間だけが異なります。

  1. POST /v1/lyrics/generate が 202 と taskId、初期 status を返します。
  2. Mureka では初期ステータスがすでに success です——タスクを一度取得すれば歌詞を読めます。Suno では pending なので、GET /v1/lyrics/tasks/{taskId} を数秒おきにポーリングします。
  3. 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'])

リクエストパラメータ:

フィールド型必須説明
promptstringはい歌詞の題材。最大 200 文字——超過するとバリデーション段階で拒否され、クレジットは確保されません
providerstringいいえ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')

クエリパラメータ:

フィールド型必須説明
pageintegerいいえページ番号、最小 1。既定は 1
pageSizeintegerいいえ1 ページあたりの件数、1–100。既定は 20
statusstringいいえ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
  }
}

タスクレスポンスのフィールド:

フィールド型説明
idstringタスク ID
providerstring実際にタスクを実行したプロバイダー:mureka または suno
statusstringpending、generating、success、failed
params.promptstring送信したプロンプトのエコー
variantsarray生成された歌詞。タスクが成功するまでは空
variants[].titlestring提案された曲タイトル
variants[].textstring生成された歌詞の本文
variants[].statusstringcomplete または failed。成功したタスクでも個別の候補が失敗していることがあります
variants[].errorMessagestringその候補が失敗した理由。それ以外は空
creditCostnumber消費したクレジット。タスクが成功するまでは 0 のまま
errorMessagestring失敗の理由(status が failed のときのみ)
createdAtnumber作成時刻(ミリ秒タイムスタンプ)
updatedAtnumber最終更新時刻(ミリ秒タイムスタンプ)

タスクは所有者ごとに分離されています。他のアカウントのタスクを取得しようとすると、タスクではなくエラーが返ります。

クレジット

歌詞生成は 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 キーではなくアカウントログインで認証します。

このページの内容