ListenHubOpenAPI
API リファレンス

画像生成

テキストプロンプトと参照画像から AI 画像を生成します。同期実行と非同期タスクに対応し、クレジット消費量の事前見積もりもできます。

画像生成 API は、テキストプロンプト(任意で参照画像による誘導つき)を 1 枚以上の画像に変換します。呼び出し方は 3 通りあります。

  • 同期POST /v1/images/generation は画像が完成するまでブロックし、モデルの生の出力(base64 画像データ)をレスポンスボディで返します。
  • 非同期POST /v1/images/generation/async は即座に taskId を返します。結果(ホスティングされた画像 URL)は GET /v1/images/generation/tasks/{taskId} をポーリングして取得します。
  • 先に見積もりPOST /v1/images/generation/estimate-credits は、何も消費せずにクレジットコストとアカウントが生成可能かどうかを返します。

すべてのエンドポイントで API キー(Authorization: Bearer $LISTENHUB_API_KEY)が必要です。キーは listenhub.ai/settings/api-keys で作成できます。

2 つの生成エンドポイントはデータの返し方が異なります。同期エンドポイントはモデルの生の JSON をそのままボディで返します(標準の { code, message, data } エンベロープでラップされません)。非同期見積もりのエンドポイントは標準のラップ済みエンベロープを使います。レスポンス形式 を参照してください。

画像を生成する(同期)

POST /v1/images/generation

テキストプロンプトから画像を生成し、完成までブロックします。スタイルや内容を誘導するために、任意で参照画像を渡せます。レスポンスボディはモデルの生の出力 — base64 画像データを含む JSON です。

基本的な生成

curl -X POST "https://api.marswave.ai/openapi/v1/images/generation" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "model": "gemini-3-pro-image",
    "prompt": "A serene mountain landscape at sunset with a reflective lake",
    "imageConfig": {
      "aspectRatio": "16:9",
      "imageSize": "2K"
    }
  }'
const response = await fetch(
  'https://api.marswave.ai/openapi/v1/images/generation',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      provider: 'google',
      model: 'gemini-3-pro-image',
      prompt: 'A serene mountain landscape at sunset with a reflective lake',
      imageConfig: {
        aspectRatio: '16:9',
        imageSize: '2K',
      },
    }),
  },
)
const data = await response.json()
// data.candidates[0].content.parts[0].inlineData holds the generated image
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/images/generation',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'provider': 'google',
        'model': 'gemini-3-pro-image',
        'prompt': 'A serene mountain landscape at sunset with a reflective lake',
        'imageConfig': {
            'aspectRatio': '16:9',
            'imageSize': '2K',
        },
    },
)
data = response.json()
# data['candidates'][0]['content']['parts'][0]['inlineData'] holds the generated image

GPT-Image-2 を使うには、provider"openai"model"gpt-image-2" に設定します。リクエストとレスポンスの形式は同じで、異なるのは providermodelimageConfig だけです。プロバイダーとモデルのマトリクス を参照してください。

参照画像を使った生成

参照画像を渡して出力を誘導します。各参照画像は URL(fileData)か base64 エンコードされたインラインデータ(inlineData)のいずれかです。1 回のリクエストで両方の形式を混在させられます。

画像 URL を使う

curl -X POST "https://api.marswave.ai/openapi/v1/images/generation" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "model": "gemini-3-pro-image",
    "prompt": "Transform this scene into a watercolor painting style",
    "referenceImages": [
      {
        "fileData": {
          "fileUri": "https://example.com/my-photo.jpg",
          "mimeType": "image/jpeg"
        }
      }
    ],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "2K"
    }
  }'
const response = await fetch(
  'https://api.marswave.ai/openapi/v1/images/generation',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      provider: 'google',
      model: 'gemini-3-pro-image',
      prompt: 'Transform this scene into a watercolor painting style',
      referenceImages: [
        {
          fileData: {
            fileUri: 'https://example.com/my-photo.jpg',
            mimeType: 'image/jpeg',
          },
        },
      ],
      imageConfig: {
        aspectRatio: '1:1',
        imageSize: '2K',
      },
    }),
  },
)
const data = await response.json()
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/images/generation',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'provider': 'google',
        'model': 'gemini-3-pro-image',
        'prompt': 'Transform this scene into a watercolor painting style',
        'referenceImages': [
            {
                'fileData': {
                    'fileUri': 'https://example.com/my-photo.jpg',
                    'mimeType': 'image/jpeg',
                }
            }
        ],
        'imageConfig': {
            'aspectRatio': '1:1',
            'imageSize': '2K',
        },
    },
)
data = response.json()

base64 インラインデータを使う

curl -X POST "https://api.marswave.ai/openapi/v1/images/generation" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "model": "gemini-3-pro-image",
    "prompt": "Create a cartoon version of this portrait",
    "referenceImages": [
      {
        "inlineData": {
          "data": "<BASE64_ENCODED_IMAGE>",
          "mimeType": "image/png"
        }
      }
    ]
  }'
import { readFileSync } from 'fs'

const imageBase64 = readFileSync('reference.png').toString('base64')

const response = await fetch(
  'https://api.marswave.ai/openapi/v1/images/generation',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      provider: 'google',
      model: 'gemini-3-pro-image',
      prompt: 'Create a cartoon version of this portrait',
      referenceImages: [
        {
          inlineData: {
            data: imageBase64,
            mimeType: 'image/png',
          },
        },
      ],
    }),
  },
)
const data = await response.json()
import os
import base64
import requests

with open('reference.png', 'rb') as f:
    image_base64 = base64.b64encode(f.read()).decode('utf-8')

response = requests.post(
    'https://api.marswave.ai/openapi/v1/images/generation',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'provider': 'google',
        'model': 'gemini-3-pro-image',
        'prompt': 'Create a cartoon version of this portrait',
        'referenceImages': [
            {
                'inlineData': {
                    'data': image_base64,
                    'mimeType': 'image/png',
                }
            }
        ],
    },
)
data = response.json()

リクエストパラメータ

以下のパラメータは POST /v1/images/generationPOST /v1/images/generation/asyncPOST /v1/images/generation/estimate-credits に適用されます。この 3 つのエンドポイントは同じリクエストスキーマを共有します。

フィールド必須説明
providerstringはい¹モデルプロバイダー:googleopenaibytedance
modelstringいいえモデル名。デフォルトは gpt-image-2プロバイダーとモデルのマトリクス を参照
promptstringはい²生成したい画像のテキスト説明
referenceImagesarrayいいえ生成を誘導する参照画像。参照画像の上限 を参照
referenceImages[].fileDataobjectいいえURL 形式で渡す参照画像
referenceImages[].fileData.fileUristringはい画像 URL — スキームは httphttpsgs のいずれか
referenceImages[].fileData.mimeTypestringはいMIME タイプ:image/pngimage/jpegimage/webpimage/heicimage/heif
referenceImages[].inlineDataobjectいいえbase64 エンコードデータ形式で渡す参照画像
referenceImages[].inlineData.datastringはいbase64 エンコードされた画像データ
referenceImages[].inlineData.mimeTypestringはいMIME タイプ:image/pngimage/jpegimage/webpimage/heicimage/heif
imageConfigobjectいいえ画像出力の設定。デフォルトは { "imageSize": "2K" }
imageConfig.imageSizestringいいえ出力解像度:1K2K(デフォルト)、4K
imageConfig.aspectRatiostringいいえアスペクト比。デフォルトは 1:1アスペクト比 を参照
imageConfig.qualitystringいいえレンダリング品質:lowmediumhigh。GPT-Image-2 に適用。省略するとモデルが自動で判断

¹ provider は 2 つの生成エンドポイントでは必須、estimate-credits では任意です。 ² prompt は 2 つの生成エンドポイントでは必須です。estimate-credits では空でも省略でも構いません(入力トークンの見積もりにしか影響しません)。

referenceImages の各要素は、fileDatainlineData のどちらか一方だけを含む必要があります。両方を同時に指定することはできません。

プロバイダーとモデルのマトリクス

provider でベンダーを、model で具体的なモデルを選びます。デフォルトのモデルは gpt-image-2 です。

providermodel備考
googlegemini-3-pro-image高品質でディテールの豊かな出力。NanoBanana Pro
googlegemini-3.1-flash-image生成が高速。追加の 1:4 / 4:1 / 1:8 / 8:1 比率に対応
openaigpt-image-2プロンプト追従性が高い。参照画像は最大 4 枚。aspectRatio は任意
bytedanceseedream-5-0-pro精密編集に対応(座標 / カラーコードは prompt に記述)。参照画像は最大 10 枚。1K / 2K のみ

旧 preview モデル ID の gemini-3-pro-image-previewgemini-3.1-flash-image-preview は入力として引き続き受け付けられ、上記の GA ID に正規化されます。新規に組み込む場合は GA ID を送信してください。

アスペクト比

imageConfig.aspectRatio のデフォルトは 1:1 です。スキーマが受け付ける比率は次のとおりです。

比率説明
1:1正方形
2:3縦長
3:2横長
3:4縦長
4:3横長
9:16縦型 / モバイル
16:9ワイドスクリーン
21:9ウルトラワイド
1:4Flash のみ
4:1Flash のみ
1:8Flash のみ
8:1Flash のみ

1:44:11:88:1 を受け付けるのは gemini-3.1-flash-imageseedream-5-0-pro だけです。GPT-Image-2 は 8 つの標準比率(1:12:33:23:44:39:1616:921:9)に対応し、aspectRatio を省略すれば自動で選択させられます。選択したモデルが対応していない比率を指定すると 400 が返ります。

画像サイズ

imageConfig.imageSize1K2K(デフォルト)、4K を受け付けます。サイズが大きいほどクレジット消費は増え、GPT-Image-2 の場合は 4K(および high 品質)に有効な有料サブスクリプションが必要です。Seedream 5.0 Pro は 1K2K のみ対応で、4K を指定すると 400 が返ります。 クレジットコストをハードコードせず、正確な数値は クレジットの見積もり を呼び出して取得してください。

参照画像の上限

モデル参照画像の上限
gemini-3-pro-image14
gemini-3.1-flash-image14
gpt-image-24
seedream-5-0-pro10

スキーマ全体としては referenceImages を 14 件までに制限しています。GPT-Image-2 はより厳しく 4 枚、Seedream 5.0 Pro は 10 枚を上限として強制し、超えると 400 が返ります。fileDatainlineData のどちらでも受け付ける MIME タイプは image/pngimage/jpegimage/webpimage/heicimage/heif です。

Seedream 5.0 Pro の精密編集

Seedream 5.0 Pro は精密編集に対応しています。画像全体を再生成するのではなく、特定の領域だけを変更できます。

専用の編集エンドポイントはなく、マスクや領域を指定するパラメータもありません。編集は同じ生成エンドポイントで行い、元画像を referenceImages に、「どこを、どう変えるか」を prompt に書きます。モデルは画像の左上を原点とする絶対ピクセル座標と、業界標準のカラーコードをそのまま読み取ります。

{
  "provider": "bytedance",
  "model": "seedream-5-0-pro",
  "prompt": "Treating the top-left corner as the coordinate origin, change the content inside top-left:(376,363) bottom-right:(701,638) to green, and leave everything else unchanged",
  "referenceImages": [
    {
      "fileData": {
        "fileUri": "https://assets.listenhub.ai/your-source-image.png",
        "mimeType": "image/png"
      }
    }
  ],
  "imageConfig": { "imageSize": "2K", "aspectRatio": "1:1" }
}

自社プロダクトに矩形選択・投げ縄・矢印などの視覚的な編集操作がある場合は、フロントエンド側で座標文字列に変換してから(あるいは注釈を参照画像に焼き込んでから)prompt に書き込んでください。サーバーはプロンプトをそのまま透過的に渡すだけで、座標を解析しません。aspectRatio は元画像の実際の比率に合わせてください。比率が食い違うと、モデルが 1 つの領域を編集せずに画像全体を作り直してしまうことがあります。

クレジットの見積もり

POST /v1/images/generation/estimate-credits

指定した設定のクレジットコストと、アカウントが生成可能かどうかを返します。クレジットは消費せず、モデルも呼び出しません。確定前に価格を表示したり、4K / high のリクエストにサブスクリプションが必要かを確認したりするのに使います。ボディは生成エンドポイントと同じものを受け付け、ここでは providerprompt が任意です。

curl -X POST "https://api.marswave.ai/openapi/v1/images/generation/estimate-credits" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "imageConfig": {
      "imageSize": "2K",
      "aspectRatio": "1:1",
      "quality": "medium"
    }
  }'
const response = await fetch(
  'https://api.marswave.ai/openapi/v1/images/generation/estimate-credits',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model: 'gpt-image-2',
      imageConfig: { imageSize: '2K', aspectRatio: '1:1', quality: 'medium' },
    }),
  },
)
const { data } = await response.json()
console.log(data.credits, data.canGenerate)
import os
import requests

response = requests.post(
    'https://api.marswave.ai/openapi/v1/images/generation/estimate-credits',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'model': 'gpt-image-2',
        'imageConfig': {'imageSize': '2K', 'aspectRatio': '1:1', 'quality': 'medium'},
    },
)
data = response.json()['data']
print(data['credits'], data['canGenerate'])

見積もりレスポンス

標準エンベロープでラップされます。data オブジェクトは次のとおりです。

フィールド説明
modelstring見積もりに使われた正規化済みの GA モデル ID
imageSizestring解決された出力サイズ
aspectRatiostring解決されたアスペクト比(モデルが自動選択する場合は返りません)
qualitystring解決された品質(該当しない場合は返りません)
pixelsobject解決できた場合は { "width": number, "height": number, "size": "WxH" }
creditsnumberこの設定で消費されるクレジット
canGeneratebooleanアカウントの有効クレジット残高が足りているか
requiresSubscriptionbooleanその設定に有効な有料プランが必要な場合(4Khigh など)に true
pricingobject価格メタデータ:pricingVersionmodetoken-estimate/fixed
warningsarray注意喚起の文字列。例:reference_image_input_tokens_not_included
{
  "code": 0,
  "message": "",
  "data": {
    "model": "gpt-image-2",
    "imageSize": "2K",
    "aspectRatio": "1:1",
    "quality": "medium",
    "pixels": { "width": 2048, "height": 2048, "size": "2048x2048" },
    "credits": 6,
    "canGenerate": true,
    "requiresSubscription": false,
    "pricing": { "pricingVersion": "...", "mode": "token-estimate" },
    "warnings": []
  }
}

非同期生成

時間のかかるジョブや高解像度のジョブでは、リクエストを開いたままにせず、タスクを送信して結果をポーリングしてください。

非同期タスクを作成する

POST /v1/images/generation/async

リクエストボディは同期エンドポイントと同じです。202taskId を即座に返し、生成はバックグラウンドで実行され、生成された画像はホスティングされた URL として永続化されます。

curl -X POST "https://api.marswave.ai/openapi/v1/images/generation/async" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "provider": "google",
    "model": "gemini-3-pro-image",
    "prompt": "An astronaut riding a horse on Mars, photorealistic",
    "imageConfig": { "imageSize": "4K", "aspectRatio": "16:9" }
  }'
const res = await fetch(
  'https://api.marswave.ai/openapi/v1/images/generation/async',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.LISTENHUB_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      provider: 'google',
      model: 'gemini-3-pro-image',
      prompt: 'An astronaut riding a horse on Mars, photorealistic',
      imageConfig: { imageSize: '4K', aspectRatio: '16:9' },
    }),
  },
)
const { data } = await res.json()
const taskId = data.taskId
import os
import requests

res = requests.post(
    'https://api.marswave.ai/openapi/v1/images/generation/async',
    headers={'Authorization': f'Bearer {os.environ["LISTENHUB_API_KEY"]}'},
    json={
        'provider': 'google',
        'model': 'gemini-3-pro-image',
        'prompt': 'An astronaut riding a horse on Mars, photorealistic',
        'imageConfig': {'imageSize': '4K', 'aspectRatio': '16:9'},
    },
)
task_id = res.json()['data']['taskId']

レスポンス(202):

{
  "code": 0,
  "message": "",
  "data": { "taskId": "65f0...", "status": "pending" }
}

単一タスクを取得する

GET /v1/images/generation/tasks/{taskId}

単一タスクのステータスと結果をポーリングします。statuspendinggeneratingsuccessfail のいずれかです。成功時は images にホスティングされた結果の URL が入ります。

curl "https://api.marswave.ai/openapi/v1/images/generation/tasks/65f0abc..." \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"
{
  "code": 0,
  "message": "",
  "data": {
    "taskId": "65f0abc...",
    "status": "success",
    "images": [
      { "url": "https://.../0.png", "mimeType": "image/png" }
    ],
    "createdAt": 1750000000000,
    "completedAt": 1750000020000
  }
}
フィールド説明
taskIdstringタスク識別子
statusstringpendinggeneratingsuccessfail
imagesarray成功時に返ります。各要素は { url, mimeType }
failMsgstringstatusfail のときの失敗メッセージ
createdAtnumber作成時刻(epoch ミリ秒)
completedAtnumber完了時刻(epoch ミリ秒)。完了後に返ります

タスク一覧を取得する

GET /v1/images/generation/tasks

自分の画像タスクを新しい順に一覧します。

クエリパラメータデフォルト説明
pagenumber1ページ番号、最小値は 1
pageSizenumber201 ページあたりの件数、1100
statusstringpendinggeneratingsuccessfail で絞り込み
curl "https://api.marswave.ai/openapi/v1/images/generation/tasks?page=1&pageSize=20&status=success" \
  -H "Authorization: Bearer $LISTENHUB_API_KEY"
{
  "code": 0,
  "message": "",
  "data": {
    "items": [
      { "taskId": "65f0...", "status": "success", "images": [/* ... */], "createdAt": 1750000000000, "completedAt": 1750000020000 }
    ],
    "page": 1,
    "pageSize": 20,
    "total": 1
  }
}

バックグラウンドタスクが pending または generating のまま 30 分を超えると、まとめて fail に更新され、タイムアウトを示す failMsg が付きます。それより古い非終端ステータスは失敗とみなして再試行してください。

レスポンス形式

エンドポイントエンベロープでラップ?ボディ
POST /v1/images/generationいいえ — モデルの生 JSONbase64 画像データ(下記参照)
POST /v1/images/generation/asyncはい{ taskId, status }
POST /v1/images/generation/estimate-creditsはい見積もりオブジェクト
GET /v1/images/generation/tasksはいページング形式の { items, page, pageSize, total }
GET /v1/images/generation/tasks/{taskId}はいタスクオブジェクト

同期エンドポイントはモデルの生の出力をそのまま返します(ラップされません)。成功時のボディには、生成された画像が base64 データとして含まれます。

{
  "candidates": [
    {
      "content": {
        "parts": [
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "<BASE64_ENCODED_IMAGE>"
            }
          }
        ]
      }
    }
  ]
}

data フィールドを base64 からデコードすると画像ファイルが得られます。非同期の経路では画像がこちらで永続化され、タスクオブジェクトにホスティングされた url が返るため、base64 のデコードは不要です。

NanoBanana Pro 無料枠

API キーからの呼び出しは、Web アプリや Labnana アプリと同じアカウント単位の無料枠(freeUsages)残高を使います。新規登録、招待、チェックインで枠を獲得し続け、それを API 経由で消費できます。現在の残高は GET /v1/user/subscription で取得し、その freeUsages マップを読んでください。

対応する残高が 0 より大きい場合、1K / 2K のリクエストはクレジットではなく無料生成を 1 回消費します。残高が 0 になると、同じリクエストは通常のクレジット課金にフォールバックします。

無料枠が適用されるのは 1K2K のサイズだけです。4K のリクエストが freeUsages を使うことはなく、常にクレジットで課金されます。

NanoBanana Pro の relax 呼び出しの挙動は、アカウント種別によって変わります。

  • 有料または課金実績のあるアカウント(有効なサブスクリプション、チャージ、クレジットパック購入)は、無料枠を消費している間も通常の有料生成と同じ体験になります。優先度は完全、キャパシティも通常、フォールバックも通常どおりです。無料枠は課金だけを変えるもので、制限付きレーンに回されるわけではありません。
  • 完全無料アカウント(一度も支払っていないアカウント)は、最低優先度の無料レーンで NanoBanana Pro relax を実行し、スループットに固定の上限があります。ピーク時にはリクエストがキューに入るか、再試行可能な busy / timeout レスポンスで拒否されることがあります。その場合はクレジットも無料枠も消費されません。時間をおいて再試行してください(深夜のほうが速くなります)。

完全無料の relax が失敗した場合は、ローカライズされたテキストを解析しなくても検知できるよう、機械可読なメタデータが返ります。

  • failReasonfree_relax_busy または free_relax_timeout です。
  • retryabletrue です。
  • 無料枠が払い戻されると freeUsageRolledBacktrue になります。
  • userMessage にはユーザー向けでローカライズ可能な文言が入ります。

同期リクエストではエラーボディに、非同期リクエストでは失敗したタスクの詳細(およびタスク一覧)に現れます。どちらの理由も「後で再試行、課金は発生していない」として扱ってください。

レート制限と参照画像モード

標準的なテキストから画像へのリクエストには、ユーザー単位およびグローバルのレート制限がかかります。

参照画像モードinlineData を伴う referenceImages)には、サーバー側の追加のリソース制約がかかります。ピーク時には base64 リクエストがより強く制限されることがあります。429 を受け取ったら Retry-After ヘッダーを読み、バックオフしてから再試行してください。クライアント側で指数バックオフを実装してください。

エラーコード

エラーは標準エンベロープ(code が非ゼロ)で返ります。同期エンドポイントの場合は、NanoBanana Pro 無料枠 に記載した生のエラーボディで返ります。

HTTP ステータス意味
400リクエストパラメータが不正(選択したモデルが対応しないアスペクト比など)
402クレジット不足
429レート制限、またはサービス混雑 — Retry-After を読んで再試行
500画像生成に失敗 — リクエストを再試行

関連

このページの内容