# Gemini Image API

> LMU AI のネイティブ Gemini v1beta エンドポイントを使って、テキストから画像生成、画像編集、画像から画像への生成を、1K / 2K / 4K、一般的なアスペクト比、Base64 解析とともに実現します。

URL: https://docs.lmuai.com/ja/docs/api/gemini-image



LMU AI は Gemini ネイティブの `v1beta` 互換 API を提供しており、Gemini 画像モデルを直接呼び出して**テキストから画像生成、画像編集、画像から画像への生成**を行えます。

<Callout type="info" title="API プロトコル">
  Gemini 画像生成は Google のネイティブ Gemini `generateContent` プロトコルを使用します — OpenAI の `/v1/chat/completions` でも、OpenAI Images の `/v1/images/generations` でもありません。

  メインエンドポイント：

  ```text
  POST https://api.lmuai.com/v1beta/models/{model}:generateContent
  ```
</Callout>

***

## 1. API 概要 [#1-api-概要]

| メソッド   | パス                                                     | 説明                                                                                            |
| ------ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------- |
| `GET`  | `/v1beta/models`                                       | 現在の API キーで Gemini グループ配下に利用可能なネイティブモデルを一覧表示                                                  |
| `GET`  | `/v1beta/models/{model}`                               | 特定のモデルに関する情報を取得                                                                               |
| `POST` | `/v1beta/models/{model}:generateContent`               | テキストから画像生成、画像編集、画像から画像への生成のメインエンドポイント                                                         |
| `POST` | `/v1beta/models/{model}:streamGenerateContent?alt=sse` | ストリーミング生成。画像ユースケースの第一選択としては推奨しません                                                             |
| `GET`  | `/v1/models`                                           | OpenAI 互換のモデル一覧。汎用的なモデルセレクターに適しています                                                           |
| `POST` | `/v1/images/batches`                                   | LMU AI Gemini 非同期バッチ画像拡張エンドポイント。[Gemini バッチ画像 API](/ja/docs/api/gemini-image-batch) を参照してください |

**ベース URL：**

```text
https://api.lmuai.com
```

***

## 2. 認証 [#2-認証]

### 推奨：Gemini ネイティブヘッダー [#推奨gemini-ネイティブヘッダー]

```http
x-goog-api-key: YOUR_API_KEY
```

### 互換：Bearer ヘッダー [#互換bearer-ヘッダー]

```http
Authorization: Bearer YOUR_API_KEY
```

サーバーは次の優先順位で API キーを読み取ります：

1. `x-goog-api-key`；
2. `Authorization: Bearer ...`；
3. `x-api-key`；
4. `/v1beta` パスの `?key=...` クエリパラメータ。

<Callout type="warn" title="キーを URL に入れないでください">
  `?api_key=...` は非推奨で `400` を返します。`?key=...` は依然として機能しますが、ブラウザの履歴、リバースプロキシ、アクセスログに簡単に記録されます — 本番環境ではヘッダーを使用してください。
</Callout>

典型的な認証エラー：

```json
{
  "error": {
    "code": 401,
    "message": "Invalid API key",
    "status": "UNAUTHENTICATED"
  }
}
```

API キーは `gemini` プラットフォームグループにバインドされている必要があります。そうでなければネイティブ Gemini API を呼び出せません。

***

## 3. モデルと利用可否 [#3-モデルと利用可否]

この画像サービスは主に次のクライアント側モデル ID を使用します：

| モデル ID                           | 推奨用途         | 画像編集に関する注記                                        |
| -------------------------------- | ------------ | ------------------------------------------------- |
| `gemini-3.1-flash-image`         | デフォルト推奨      | `inlineData` 画像編集で本番環境にて検証済み                      |
| `gemini-3.1-flash-image-preview` | プレビュー互換      | 同じ `generateContent` 編集プロトコルを使用。本番統合前に個別に検証してください |
| `gemini-3-pro-image`             | 品質優先 / 複雑な編集 | 同じ `generateContent` 編集プロトコルを使用。現在のキーの利用可否に依存します  |
| `gemini-3-pro-image-preview`     | Pro プレビュー互換  | 同じ編集プロトコルを使用。実行モデルはサーバーレスポンスが示すものです               |
| `gemini-3.1-flash-lite-image`    | 軽量ユースケース     | モデル一覧で返され、かつ画像出力が検証済みの場合にのみ使用してください               |

### 現在のキーの Gemini モデルを一覧表示 [#現在のキーの-gemini-モデルを一覧表示]

```bash
curl 'https://api.lmuai.com/v1beta/models' \
  -H 'x-goog-api-key: YOUR_API_KEY'
```

OpenAI 互換のモデル一覧：

```bash
curl 'https://api.lmuai.com/v1/models' \
  -H 'Authorization: Bearer YOUR_API_KEY'
```

<Callout type="info" title="モデル ID はサーバー側でマッピングされる場合があります">
  クライアントはリクエストモデル ID を送信します。LMU AI は互換モデルエイリアスをサポートしているため、リクエストしたモデル名がレスポンスの最終的なモデルバージョンと必ずしも同じとは限りません。

  モデル名だけから利用可否を推測しないでください。現在のキーで `/v1beta/models` を呼び出した実際の結果を頼りにしてください。
</Callout>

***

## 4. クイックスタート：テキストから画像生成 [#4-クイックスタートテキストから画像生成]

```bash
curl --request POST \
  'https://api.lmuai.com/v1beta/models/gemini-3.1-flash-image:generateContent' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "contents": [
      {
        "role": "user",
        "parts": [
          {
            "text": "An orange cat wearing an astronaut helmet, cinematic lighting, exquisite detail"
          }
        ]
      }
    ],
    "generationConfig": {
      "responseModalities": ["TEXT", "IMAGE"],
      "imageConfig": {
        "aspectRatio": "1:1",
        "imageSize": "1K"
      }
    }
  }'
```

成功時は、次から画像を読み取ります：

```text
candidates[].content.parts[].inlineData.data
```

***

## 5. テキストから画像生成のリクエスト構造 [#5-テキストから画像生成のリクエスト構造]

```json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "A cinematic rainy-night city street, neon lights reflected on the wet pavement, wide-angle composition"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "16:9",
      "imageSize": "2K"
    }
  }
}
```

### リクエストフィールド [#リクエストフィールド]

| フィールド                                 |         型 |       必須       | 説明                                                 |
| ------------------------------------- | --------: | :------------: | -------------------------------------------------- |
| `contents`                            |     array |       はい       | 会話コンテンツの配列。少なくとも 1 つのユーザーメッセージを含む必要があります           |
| `contents[].role`                     |    string |       推奨       | ユーザー入力には `user` を使用                                |
| `contents[].parts`                    |     array |       はい       | テキストまたは入力画像のパート                                    |
| `parts[].text`                        |    string | テキストから画像生成では必須 | 画像プロンプト                                            |
| `generationConfig`                    |    object |       はい       | 生成パラメータ                                            |
| `generationConfig.responseModalities` | string\[] |       はい       | 画像生成には `IMAGE` を含める必要があります。`['TEXT', 'IMAGE']` を推奨 |
| `generationConfig.imageConfig`        |    object |       はい       | 画像の解像度とアスペクト比の設定                                   |

<Callout type="warn" title="画像パラメータは imageConfig に入れる必要があります">
  `generationConfig.imageConfig` を使用してください。`responseFormat.image` は使用しないでください。そのフィールドはパラメータエラーを発生させないかもしれませんが、ネイティブ Gemini 画像パラメータとしては有効になりません。
</Callout>

***

## 6. 解像度とアスペクト比 [#6-解像度とアスペクト比]

### サポートされる解像度 [#サポートされる解像度]

| `imageSize` | 推奨用途                     | 特徴              |
| ----------- | ------------------------ | --------------- |
| `1K`        | 下書き、クイックプレビュー、バッチスクリーニング | 通常はより高速かつ安価     |
| `2K`        | 標準的な納品、記事画像、EC アセット      | 品質、時間、コストのバランス  |
| `4K`        | 精細な大判画像、高品質な納品           | 通常は生成と転送に時間がかかる |

`imageSize` は大文字である必要があります：

```json
{
  "imageSize": "2K"
}
```

### サポートされるアスペクト比 [#サポートされるアスペクト比]

`aspectRatio` は**モデルレベルの機能**です。Flash の拡張比を Pro モデルで使用することはできません。LMU AI はリクエストされたモデルに対して比率を検証し、既知の無効な組み合わせを上流に送信しないようにします。

**10 種類の一般的な比率：**

```text
1:1
2:3
3:2
3:4
4:3
4:5
5:4
9:16
16:9
21:9
```

**4 種類の Flash 拡張比：**

```text
1:4
1:8
4:1
8:1
```

### モデルの比率マトリクス [#モデルの比率マトリクス]

| クライアントモデル ID                     | 確認済みのサポート比率             |  数 |
| -------------------------------- | ----------------------- | -: |
| `gemini-3.1-flash-image`         | 10 種の一般 + 4 種の Flash 拡張 | 14 |
| `gemini-3.1-flash-image-preview` | 10 種の一般 + 4 種の Flash 拡張 | 14 |
| `gemini-3.1-flash-lite-image`    | 10 種の一般 + 4 種の Flash 拡張 | 14 |
| `gemini-3-pro-image`             | 10 種の一般のみ               | 10 |
| `gemini-3-pro-image-preview`     | 10 種の一般のみ               | 10 |

<Callout type="warn" title="Pro モデルは Flash 拡張比をサポートしません">
  `gemini-3-pro-image` または `gemini-3-pro-image-preview` に `1:4`、`1:8`、`4:1`、`8:1` を渡すと、`INVALID_ARGUMENT` またはリレーの `400` パラメータエラーが返ります。例：

  ```json
  {
    "error": {
      "code": 400,
      "message": "generationConfig.imageConfig.aspectRatio has an unsupported value",
      "status": "INVALID_ARGUMENT"
    }
  }
  ```
</Callout>

上記のマトリクスは、Google 公式のモデルドキュメントと LMU AI 本番 API テストを組み合わせたものです：3 つの Flash / Flash Lite モデルはすべて拡張比テストに合格し、両方の Pro モデルは 4 つの拡張比すべてを明示的に拒否します。未知または新しいモデルについては、検証が済むまで 10 種の一般的な比率を使用してください。

`aspectRatio` を指定しない場合、モデルは入力コンテンツとデフォルトポリシーに基づいてアスペクト比を決定します。任意の小数や任意の `WIDTHxHEIGHT` を渡さないでください。対象モデルが受け付ける比率 enum を使用する必要があります。

例：

```json
{
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "9:16",
      "imageSize": "4K"
    }
  }
}
```

<Callout type="info" title="解像度ティアは固定のピクセル寸法ではありません">
  `1K`、`2K`、`4K` はモデルの解像度ティアです。実際の幅と高さはモデルがティアとアスペクト比から計算します。クライアントは常に `1024×1024`、`2048×2048`、`4096×4096` であると仮定してはいけません。
</Callout>

***

## 7. 画像編集 / 画像から画像への生成 [#7-画像編集--画像から画像への生成]

Gemini は**画像編集をサポートしています** — GPT のような専用の `/v1/images/edits` エンドポイントがないだけです。

テキストから画像生成も画像編集もどちらも次を呼び出します：

```text
POST /v1beta/models/{model}:generateContent
```

両者の違いは次のとおりです：

| ユースケース        | `contents[].parts[]` の内容     |
| ------------- | ---------------------------- |
| テキストから画像生成    | テキストプロンプトのみ                  |
| 画像編集 / 画像から画像 | テキスト編集指示 + `inlineData` 入力画像 |

<Callout type="info" title="本番環境で検証済み">
  `gemini-3.1-flash-image` で、`inlineData` 経由で JPEG 入力画像を送信したところ、次が正常に返されました：

  * HTTP `200`；
  * `finishReason: STOP`；
  * `image/png` の編集結果；
  * 空でない `inlineData.data`；
  * `usageMetadata` の画像モダリティトークン数。

  レスポンスには画像パートのみが含まれ、テキストパートがない場合があるため、クライアントはレスポンスにテキストが存在することを要求してはいけません。
</Callout>

### 7.1 最小限の画像編集リクエスト [#71-最小限の画像編集リクエスト]

```json
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "Keep the person, composition, and lighting; change the background to a rainy-night neon street"
        },
        {
          "inlineData": {
            "mimeType": "image/png",
            "data": "INPUT_IMAGE_BASE64"
          }
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": ["TEXT", "IMAGE"],
    "imageConfig": {
      "aspectRatio": "1:1",
      "imageSize": "1K"
    }
  }
}
```

### 7.2 入力画像フィールド [#72-入力画像フィールド]

| フィールド                     |      型 |  必須 | 説明                                      |
| ------------------------- | -----: | :-: | --------------------------------------- |
| `contents[].parts[].text` | string |  はい | 編集指示。何を保持し何を変更するかを明確に述べてください            |
| `inlineData.mimeType`     | string |  はい | 例：`image/png`、`image/jpeg`、`image/webp` |
| `inlineData.data`         | string |  はい | 生の Base64。Data URL プレフィックスなし            |
| `imageConfig.aspectRatio` | string | いいえ | 出力アスペクト比。入力比を維持する必要がある場合は一致する比率を設定      |
| `imageConfig.imageSize`   | string | いいえ | 出力ティア：`1K`、`2K`、`4K`。モデルの機能に依存          |

<Callout type="warn" title="Base64 に Data URL プレフィックスを含めないでください">
  正しい例：

  ```text
  /9j/4AAQSkZJRgABAQ...
  ```

  次を渡さないでください：

  ```text
  data:image/jpeg;base64,/9j/4AAQSkZJRgABAQ...
  ```

  過度に大きな入力画像はアップロードと処理時間を増大させ、ゲートウェイのリクエストボディ制限により `413` を返す可能性があります。
</Callout>

### 7.3 完全な curl の例 [#73-完全な-curl-の例]

まずローカル画像を 1 行の Base64 に変換します：

```bash
IMAGE_BASE64=$(base64 < input.jpg | tr -d '\n')
```

次に画像モデルを呼び出します：

```bash
curl --request POST \
  'https://api.lmuai.com/v1beta/models/gemini-3.1-flash-image:generateContent' \
  --header 'x-goog-api-key: YOUR_API_KEY' \
  --header 'Content-Type: application/json' \
  --data-raw "{
    \"contents\": [{
      \"role\": \"user\",
      \"parts\": [
        {
          \"text\": \"Keep the cup, composition, lighting, and background unchanged; only change the cup from blue to purple, and add three white star patterns on the cup body; do not add any text\"
        },
        {
          \"inlineData\": {
            \"mimeType\": \"image/jpeg\",
            \"data\": \"${IMAGE_BASE64}\"
          }
        }
      ]
    }],
    \"generationConfig\": {
      \"responseModalities\": [\"TEXT\", \"IMAGE\"],
      \"imageConfig\": {
        \"aspectRatio\": \"3:2\",
        \"imageSize\": \"1K\"
      }
    }
  }"
```

### 7.4 Python の画像編集の例 [#74-python-の画像編集の例]

```python
import base64
import requests

api_key = "YOUR_API_KEY"
model = "gemini-3.1-flash-image"
input_path = "input.jpg"

with open(input_path, "rb") as f:
    image_base64 = base64.b64encode(f.read()).decode("utf-8")

payload = {
    "contents": [{
        "role": "user",
        "parts": [
            {
                "text": "Keep the subject and composition; change the background to a rainy-night neon street"
            },
            {
                "inlineData": {
                    "mimeType": "image/jpeg",
                    "data": image_base64,
                }
            },
        ],
    }],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {
            "aspectRatio": "3:2",
            "imageSize": "1K",
        },
    },
}

response = requests.post(
    f"https://api.lmuai.com/v1beta/models/{model}:generateContent",
    headers={
        "x-goog-api-key": api_key,
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=300,
)
response.raise_for_status()
result = response.json()

saved = False
for candidate in result.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        inline_data = part.get("inlineData", {})
        if inline_data.get("data"):
            mime_type = inline_data.get("mimeType", "image/png")
            extension = "jpg" if "jpeg" in mime_type else "webp" if "webp" in mime_type else "png"
            with open(f"gemini-edited.{extension}", "wb") as f:
                f.write(base64.b64decode(inline_data["data"]))
            saved = True
            break
    if saved:
        break

if not saved:
    raise RuntimeError("HTTP request succeeded, but the response contains no edited image")
```

### 7.5 編集プロンプトのヒント [#75-編集プロンプトのヒント]

画像編集プロンプトでは、「保持するもの」と「変更するもの」を明確に分けるのが最善です：

```text
Keep: subject identity, pose, camera angle, composition, and lighting.
Change: change the background to a rainy-night neon street.
Forbidden: do not add text; do not change the person's face.
```

この構造は、単に「もっと良く見せて」と書くよりも一貫した結果をもたらします。

### 7.6 複数の参照画像 [#76-複数の参照画像]

一部の Gemini 画像モデルは、スタイル参照、キャラクター参照、またはアセットのブレンドのために、同じ `parts[]` 内に複数の `inlineData` 画像を受け付けることができます。ただし、許可される参照画像の枚数とリクエストボディの合計サイズはモデルによって異なるため、本番使用前に特定のモデルで検証してください。

`/v1beta/models` が返したからといって、あるモデルが無制限の参照画像をサポートすると仮定してはいけません。

***

## 8. 成功時のレスポンス [#8-成功時のレスポンス]

典型的なレスポンス：

```json
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "text": "Image generated as requested."
          },
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "BASE64_IMAGE_DATA"
            }
          }
        ]
      },
      "finishReason": "STOP",
      "index": 0
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 123,
    "candidatesTokenCount": 1120,
    "totalTokenCount": 1450,
    "candidatesTokensDetails": [
      {
        "modality": "IMAGE",
        "tokenCount": 1024
      }
    ]
  },
  "modelVersion": "MODEL_VERSION"
}
```

### 主要なレスポンスフィールド [#主要なレスポンスフィールド]

| フィールド                          | 説明                                   |
| ------------------------------ | ------------------------------------ |
| `candidates[]`                 | 候補出力のリスト                             |
| `candidates[].content.parts[]` | テキストまたは画像のパート                        |
| `parts[].inlineData.mimeType`  | 返された画像の MIME タイプ                     |
| `parts[].inlineData.data`      | 返された画像の Base64 コンテンツ                 |
| `candidates[].finishReason`    | 終了理由。一般的な成功値は `STOP`                 |
| `usageMetadata`                | 入力、出力、画像モダリティのトークン数                  |
| `modelVersion`                 | 上流から返された実際のモデルバージョン。存在する場合はそのまま渡されます |

### 画像生成の成功を正しく判定する [#画像生成の成功を正しく判定する]

クライアントは次のすべてを確認する必要があります：

1. HTTP ステータスコードが `2xx`；
2. `candidates` が空でない；
3. 少なくとも 1 つの `parts[]` に空でない `inlineData.data` が含まれる；
4. Base64 が正常にデコードできる；
5. 必要に応じて `finishReason` を確認する。

<Callout type="warn" title="HTTP 200 は画像生成を保証しません">
  上流はレスポンスに `inlineData.data` を含まない HTTP `200` を返す場合があります。そのようなリクエストは「ビジネス上の画像生成失敗」として扱い、成功画像としてカウントしてはいけません。
</Callout>

***

## 9. Node.js の例 [#9-nodejs-の例]

```js
import { writeFile } from 'node:fs/promises';

const BASE_URL = process.env.GEMINI_BASE_URL || 'https://api.lmuai.com';
const API_KEY = process.env.GEMINI_API_KEY;
const MODEL = 'gemini-3.1-flash-image';

if (!API_KEY) throw new Error('Missing GEMINI_API_KEY');

const payload = {
  contents: [
    {
      role: 'user',
      parts: [
        { text: 'A seaside lighthouse at sunset, watercolor illustration, warm tones, delicate paper texture' },
      ],
    },
  ],
  generationConfig: {
    responseModalities: ['TEXT', 'IMAGE'],
    imageConfig: {
      aspectRatio: '16:9',
      imageSize: '2K',
    },
  },
};

const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 300_000);

try {
  const response = await fetch(
    `${BASE_URL}/v1beta/models/${encodeURIComponent(MODEL)}:generateContent`,
    {
      method: 'POST',
      headers: {
        'x-goog-api-key': API_KEY,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify(payload),
      signal: controller.signal,
    },
  );

  const text = await response.text();
  let data;
  try {
    data = JSON.parse(text);
  } catch {
    throw new Error(`Non-JSON response from the service: HTTP ${response.status}`);
  }

  if (!response.ok) {
    throw new Error(
      `HTTP ${response.status}: ${data?.error?.message || JSON.stringify(data)}`,
    );
  }

  const parts = data.candidates?.flatMap((candidate) => candidate.content?.parts || []) || [];
  const imagePart = parts.find((part) => part.inlineData?.data);

  if (!imagePart) {
    const reasons = data.candidates?.map((candidate) => candidate.finishReason).filter(Boolean);
    throw new Error(`Request completed but no image, finishReason=${reasons?.join(',') || 'unknown'}`);
  }

  const mimeType = imagePart.inlineData.mimeType || 'image/png';
  const extension = mimeType === 'image/jpeg'
    ? 'jpg'
    : mimeType === 'image/webp'
      ? 'webp'
      : 'png';

  await writeFile(
    `gemini-output.${extension}`,
    Buffer.from(imagePart.inlineData.data, 'base64'),
  );

  console.log('Image saved, usageMetadata:', data.usageMetadata || null);
} finally {
  clearTimeout(timer);
}
```

***

## 10. Python の例 [#10-python-の例]

```python
import base64
import os
from pathlib import Path
import requests

BASE_URL = os.getenv("GEMINI_BASE_URL", "https://api.lmuai.com")
API_KEY = os.environ["GEMINI_API_KEY"]
MODEL = "gemini-3.1-flash-image"

payload = {
    "contents": [
        {
            "role": "user",
            "parts": [
                {"text": "A futuristic building complex, early-morning mist, ultra-wide-angle photography, realistic materials"}
            ],
        }
    ],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {
            "aspectRatio": "16:9",
            "imageSize": "2K",
        },
    },
}

response = requests.post(
    f"{BASE_URL}/v1beta/models/{MODEL}:generateContent",
    headers={
        "x-goog-api-key": API_KEY,
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=300,
)

data = response.json()
if not response.ok:
    message = data.get("error", {}).get("message", data)
    raise RuntimeError(f"HTTP {response.status_code}: {message}")

image_part = None
for candidate in data.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        if part.get("inlineData", {}).get("data"):
            image_part = part
            break
    if image_part:
        break

if not image_part:
    reasons = [candidate.get("finishReason") for candidate in data.get("candidates", [])]
    raise RuntimeError(f"Request completed but no image was returned, finishReason={reasons}")

inline_data = image_part["inlineData"]
mime_type = inline_data.get("mimeType", "image/png")
extension = {
    "image/jpeg": "jpg",
    "image/webp": "webp",
}.get(mime_type, "png")

Path(f"gemini-output.{extension}").write_bytes(
    base64.b64decode(inline_data["data"])
)

print("Image saved")
print("usageMetadata:", data.get("usageMetadata"))
```

***

## 11. よくあるエラー [#11-よくあるエラー]

ネイティブ Gemini エンドポイントは通常、Google 形式のエラーを返します：

```json
{
  "error": {
    "code": 429,
    "message": "upstream rate limit exceeded",
    "status": "RESOURCE_EXHAUSTED"
  }
}
```

|    HTTP ステータス | よくある原因                           | 推奨対応                                |
| ------------: | -------------------------------- | ----------------------------------- |
|         `400` | 不正なリクエスト構造、モデルパス、またはグループプラットフォーム | リクエストを修正してください。単にリトライしないでください       |
|         `401` | API キーの欠落、無効、または無効化              | キーとヘッダーを確認してください                    |
| `402` / `403` | 残高不足、サブスクリプション、請求資格、または権限の問題     | アカウントとグループ権限を確認してください               |
|         `413` | 画像から画像へのリクエストボディが大きすぎる           | 入力画像を圧縮してください                       |
|         `429` | ユーザー同時実行制限または上流のレート制限            | 指数バックオフ。同時実行数と RPM を削減してください        |
|         `500` | 内部または容量エラー                       | エラーコードとリクエスト ID を記録し、限定的にリトライしてください |
|         `502` | 一時的な上流の認証、権限、またはサービス障害           | バックオフしてリトライ。必要なら管理者に連絡してください        |
|         `503` | 利用可能な Gemini アカウントがない、または上流が過負荷  | 遅延後にリトライし、トラフィックを削減してください           |
|         `504` | ゲートウェイまたは上流のタイムアウト               | 独立したリクエストとして再発行してください               |

エラーメッセージがすべてのトークンが無効、クールダウン中、ロック、または期限切れであると示している場合、これはプロンプト形式のエラーではなくサービス容量の問題です。積極的なリトライを止め、エラーコードとリクエスト ID を管理者に提供してください。

***

## 12. タイムアウト、リトライ、同時実行 [#12-タイムアウトリトライ同時実行]

### クライアントのタイムアウト推奨値 [#クライアントのタイムアウト推奨値]

| 解像度  | 推奨する合計タイムアウト |
| ---- | -----------: |
| `1K` |     最低 120 秒 |
| `2K` |     最低 180 秒 |
| `4K` |     300 秒を推奨 |

これらは統合の推奨値であり、固定の SLA ではありません。リクエストが独自の Nginx、CDN、または API ゲートウェイも通過する場合は、それらのコンポーネントの読み取りタイムアウトを適宜調整してください。

### リトライの推奨事項 [#リトライの推奨事項]

リトライを推奨するケース：

* `429`；
* `502`、`503`、`504`；
* ネットワーク中断、接続リセット、読み取りタイムアウト；
* HTTP `200` が返るのに画像がない場合、1 回（限定的に）リトライし、生のレスポンスを保存できます。

通常はリトライしないケース：

* `400`；
* `401`；
* 明示的な残高または権限のエラー；
* リクエストパラメータまたはコンテンツポリシーのエラー。

リトライは最大 2〜3 回とし、指数バックオフを使用してください：

```text
Attempt 1: 1–2 seconds random jitter
Attempt 2: 3–5 seconds random jitter
Attempt 3: 8–12 seconds random jitter
```

### 複数のリアルタイム画像 [#複数のリアルタイム画像]

リアルタイムエンドポイントは現在「1 リクエストあたり主要画像 1 枚」として使用されます。複数の画像が必要な場合は、複数の独立したリクエストに分割し、同時に次を制限してください：

* 最大の同時実行中リクエスト数；
* 1 分あたりのリクエスト数（RPM）；
* ユーザーごとのタスク数；
* タイムアウトと最大リトライ回数。

数十から数百のプロンプトを送信して結果を非同期で待つ必要がある場合は、[Gemini バッチ画像 API](/ja/docs/api/gemini-image-batch) を使用してください。

***

## 13. 使用量と課金 [#13-使用量と課金]

レスポンス内の `usageMetadata` は、入力、出力、画像モダリティのトークンを分析するために使用できますが、必ずしも最終的な課金額と等しいわけではありません。

実際の課金額は次の影響を受ける場合があります：

* リクエストされたモデル ID と実際にマッピングされたモデル；
* `1K`、`2K`、`4K` の画像ティア；
* グループの画像あたりの価格；
* ユーザーグループ倍率と上流アカウント倍率；
* デプロイ環境の課金ルール。

最終的な金額については、LMU AI コンソールの使用量詳細とアカウント残高の変化を頼りにしてください。

品質または同時実行のテストを実行する際は、次を記録してください：

1. テスト前の残高；
2. テスト後の残高；
3. 成功したリクエスト数；
4. 実際に返された画像数；
5. モデル、解像度、アスペクト比；
6. 残高の差；
7. 成功画像 1 枚あたりの平均コスト。

使用量記録は非同期で反映される場合があるため、テスト後にしばらく待ってから最終的な金額を照合してください。

***

## 14. セキュリティに関する推奨事項 [#14-セキュリティに関する推奨事項]

* API キーはサーバー側の環境変数またはシークレットマネージャーにのみ保存してください；
* キーをブラウザのフロントエンド、モバイルアプリのパッケージ、公開コードリポジトリに埋め込まないでください；
* 完全な API キーや完全な画像 Base64 をログに記録しないでください；
* 入力画像の MIME タイプ、ファイルサイズ、Base64 の有効性を検証してください；
* レスポンスを保存する際は `inlineData.mimeType` に基づいてファイル拡張子を選択してください；
* 各ビジネスリクエストについて、独自のトレース ID、リクエスト時刻、モデル、解像度、HTTP ステータスを記録してください；
* タイムアウト後、ごく短時間に大量の同一リクエストを再作成しないでください。

***

## 15. 統合の受け入れチェックリスト [#15-統合の受け入れチェックリスト]

* [ ] `/v1beta/models` を使って現在のキーの Gemini モデル一覧を取得できる；
* [ ] `x-goog-api-key` または Bearer ヘッダーで認証できる；
* [ ] `1K / 1:1` のテキストから画像生成を完了できる；
* [ ] `2K` および `4K` のテキストから画像生成を完了できる；
* [ ] 少なくとも 1 回の画像編集 / 画像から画像への生成を完了できる；
* [ ] `inlineData.mimeType` と `inlineData.data` を読み取れる；
* [ ] HTTP 200 で画像がない場合を失敗としてフラグ付けできる；
* [ ] 画像リクエストにタイムアウトを設定している；
* [ ] 429 と 5xx に対して限定的な指数バックオフを実装している；
* [ ] 価格、残高、同時実行、RPM を確認している；
* [ ] ログが API キーや完全な Base64 を漏洩しない。

***

## 次のステップ [#次のステップ]

* 多数のプロンプトの非同期生成：[Gemini バッチ画像 API](/ja/docs/api/gemini-image-batch)
* 現在のキーで利用可能なモデルを一覧表示：[モデルギャラリー](/ja/docs/guide/models)
* プロトコルとベース URL の詳細：[API プロトコル](/ja/docs/guide/api-protocols)
* リクエストの使用量を照会：[使用量詳細のエクスポート](/ja/docs/api/usage-export)
