画像生成 API
BetterToken の OpenAI 互換 API で GPT Image の画像を生成。API Key、Base URL、パラメーター、Python と JavaScript の例、エラー対処を解説します。
POST /v1/images/generations
テキストから画像を生成する Endpoint では、application/json のリクエスト本文を使用します。プロンプトを送信し、HTTP リクエストを開いたままにして、同じレスポンスの data[].b64_json から各画像を読み取ります。
目的に合うフローを選ぶ
- テキストから画像を生成して保存する:このページを使用します。
curlの例から始め、続いて 画像を保存する でdata[]の各項目をデコードします。 - 既存の画像を編集する:画像編集 API に 1 枚以上の参照画像をアップロードします。通常の参照画像編集にマスクは不要です。選択範囲を編集する場合のみ、選択したモデルとサイズで利用可能であればマスクを追加します。
- モデルとパラメータを選び、予算を見積もる:利用可能な Model ID と価格はモデル広場で確認してください。全体の手順は GPT Image 2 ガイドを参照してください。
curl でのクイックスタート
Base URL として https://bettertoken.ai/v1 を使用し、https://bettertoken.ai/v1/images/generations にリクエストを送信します。
curl --max-time 300 -X POST "https://bettertoken.ai/v1/images/generations" \ -o response.json \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-image-2", "prompt": "A product photo of a green ceramic mug on a studio table", "size": "1024x1024", "n": 1, "response_format": "b64_json", "output_format": "png" }'推奨値
以下は推奨される初期値で、固定要件ではありません。n=1 を推奨します。Endpoint は 1 から 10 の整数を受け付けますが、返される画像数は要求数より少ない場合があります。
{ "model": "gpt-image-2", "n": 1, "response_format": "b64_json", "output_format": "png"}| パラメーター | 送信する値 | 用途 |
|---|---|---|
model | gpt-image-2、gpt-image-2.5-flare、gpt-image-2.5-sunburst | model plaza で利用可能な Model ID を選択します。有効な ID でもモデル、サイズ、操作が現在利用可能とは限りません。 |
prompt | テキストによる説明 | 必須の画像説明です。被写体、スタイル、構図、重要な制約を含めます。 |
size | 省略、auto、または 1024x1024 などの寸法 | 希望サイズを指定します。実際の寸法は異なる場合があります。 |
n | 1 から 10 の整数 | 要求する最大画像数。1 を推奨しますが、返却数は少ない場合があります。 |
quality | gpt-image-2 は auto、low、medium、high。2.5 の 2 モデルは xhigh、max も受け付けます | 任意の品質設定です。省略するか JSON null を指定すると既定値を使います。設定を受け付けても、値を上げることで画質が向上するとは限りません。 |
response_format | b64_json | 各画像を data[].b64_json に base64 で返します。 |
output_format | 例:png | 出力形式のリクエストであり、実ファイルのエンコード形式を保証しません。保存前にバイト列から形式を判定してください。 |
返される画像数は n より少ない場合があります。data[] の各項目を処理してください。n=1 は推奨値であり、サーバー上限ではありません。
推奨サイズ
size | 比率 | 用途 |
|---|---|---|
auto | 自動 | サイズを自動選択 |
1024x1024 | 1:1 | 正方形の画像、アバター、カバー、アセット |
1536x1024 | 3:2 | 横長のポスター、バナー、シーン |
1024x1536 | 2:3 | 縦長のモバイルカバーとポスター |
1536x1152 | 4:3 | 標準的な横長画像、商品画像、コンテンツグラフィック |
1152x1536 | 3:4 | 標準的な縦長画像、モバイルカバー、縦長ポスター |
2048x2048 | 1:1 | 高解像度の正方形画像 |
2048x1152 | 16:9 | 高解像度の横長画像 |
3840x2160 | 16:9 | 4K 横長画像 |
2160x3840 | 9:16 | 4K 縦長画像 |
表の値は例であり、指定可能な値の一覧ではありません。size を省略するか auto を指定でき、JSON の null も自動選択になります。明示する幅と高さは正の 16 の倍数で、それぞれ 3840 以下、縦横比は 3:1 以下、総画素数は 655360~8294400 です。たとえば 2080x2080 も有効です。実際の出力寸法は異なる場合があるため、画像を確認し、無理に切り抜かないでください。
画像を保存する
成功時のレスポンスは、次の OpenAI 互換画像レスポンス形式に従います。以下の金額はレシート形式の例であり、固定価格ではありません。
{ "created": 1710000000, "data": [ { "b64_json": "iVBORw0KGgoAAAANSUhEUgAA...(truncated)", "revised_prompt": "Optional revised prompt" } ], "bettertoken_image_billing": { "currency": "CNY", "settled_amount": "0.15", "outputs": [ { "index": 0, "width": 1254, "height": 1254, "billing_resolution": "2K", "currency": "CNY", "amount": "0.15" } ] }}data[].b64_json の各画像を読み取り、revised_prompt などの追加フィールドも許可してください。課金情報はルートの bettertoken_image_billing に返されます。settled_amount と各 outputs[].amount は小数文字列で、outputs[].index は 0 始まりです。
output_format は要求する形式であり、実際のエンコード形式や変換を保証しません。画像のバイト列を確認し、対応する拡張子で保存してください。
import base64import jsonfrom pathlib import Path
result = json.loads(Path("response.json").read_text(encoding="utf-8"))for index, item in enumerate(result["data"], start=1): encoded = item["b64_json"] if "," in encoded and "base64" in encoded.split(",", 1)[0]: encoded = encoded.split(",", 1)[1] image_bytes = base64.b64decode(encoded) if image_bytes.startswith(b"\x89PNG\r\n\x1a\n"): extension = "png" elif image_bytes.startswith(b"\xff\xd8\xff"): extension = "jpg" elif image_bytes.startswith(b"RIFF") and image_bytes[8:12] == b"WEBP": extension = "webp" else: raise ValueError("Unsupported image signature") Path(f"output-{index}.{extension}").write_bytes(image_bytes)JavaScript の例(Node.js)
import { writeFile } from "node:fs/promises";
const response = await fetch("https://bettertoken.ai/v1/images/generations", { method: "POST", headers: { Authorization: "Bearer YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ model: "gpt-image-2", prompt: "A green ceramic mug on a studio table", size: "1024x1024", n: 1, response_format: "b64_json", output_format: "png", }),});
if (!response.ok) { throw new Error(await response.text());}
const result = await response.json();const { data } = result;for (const [index, item] of data.entries()) { const b64Json = item.b64_json.replace(/^data:.*;base64,/, ""); const imageBytes = Buffer.from(b64Json, "base64"); let extension; if (imageBytes.subarray(0, 8).equals(Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]))) { extension = "png"; } else if (imageBytes[0] === 0xff && imageBytes[1] === 0xd8 && imageBytes[2] === 0xff) { extension = "jpg"; } else if (imageBytes.toString("ascii", 0, 4) === "RIFF" && imageBytes.toString("ascii", 8, 12) === "WEBP") { extension = "webp"; } else { throw new Error("Unsupported image signature"); } await writeFile(`output-${index + 1}.${extension}`, imageBytes);}PNG、JPEG、WebP のいずれかにエンコードを固定する必要がある場合は、実際の形式を識別してから必要に応じて変換してください。拡張子を変更するだけでは画像の形式は変わりません。
実際の料金を確認する
bettertoken_image_billing は結果とともに返されるため、別の料金確認リクエストは不要です。
| フィールド | 意味 |
|---|---|
currency | 決済通貨。USD または CNY とは限りません。 |
settled_amount | リクエストの決済合計額。小数文字列です。 |
requested_resolution | リクエストから判定された解像度レベル。 |
outputs[].index | data[] に対応する 0 始まりの画像番号。 |
outputs[].width、height | 実際の幅と高さ(ピクセル)。 |
outputs[].billing_resolution | 画像に適用された最終料金レベル。 |
outputs[].currency、amount | 画像ごとの決済通貨と金額。 |
要求サイズと料金レベルは異なる場合があります。1024x1024 の要求から 1254x1254 が返り、2K で課金された例があります。領収情報の金額を使用し、現在の単価は モデル広場で確認してください。表示では文字列を保ち、計算では Decimal を使います。領収情報がない場合に費用をゼロとして扱わないでください。
from decimal import Decimal
billing = result.get("bettertoken_image_billing")if billing is None: print("Billing receipt unavailable; check your usage records.")else: total = Decimal(billing["settled_amount"]) print(f"Total: {billing['currency']} {total}") for output in billing.get("outputs", []): print( f"Image {output['index'] + 1}: " f"{output['width']}x{output['height']}, " f"{output['billing_resolution']}, " f"{output['currency']} {output['amount']}" )レスポンスの流れ
この Endpoint は同期式です。POST /images/generations を送信した後、サーバーが応答するまで現在の HTTP リクエストを開いたままにしてください。成功すると、すべての画像が data[].b64_json に返されます。
この Endpoint は task_id を返さず、個別のステータス照会や結果ダウンロード用の Endpoint もありません。
処理前に BetterToken は、適用される最高単価に n を掛けた上限額を事前承認する場合があります。納品される 1K 画像分の残高があっても、この保留額には不足することがあり、その場合は 403 と error.code=insufficient_user_quota で拒否されます。最終請求は実際に納品された画像に基づきます。
タイムアウトと再試行
- HTTP クライアントのタイムアウトは数分に設定します。
- タイムアウト、切断、曖昧な
5xxでは実行や課金の有無が分かりません。自動再送せず、利用履歴またはリクエストログを確認してください。受信したリクエスト ID とX-BetterToken-Image-Receipt、X-BetterToken-Billing-Stateヘッダーを保存してください。 - 入力エラー、認証エラー、パラメーター不足、形式不正のリクエストは自動再試行しないでください。
429はリクエストが拒否されたことを確認できた場合に限り、バックオフして再試行してください。クライアント独自のリクエスト ID はサーバーの冪等性を保証しません。状態確認用の別 Endpoint はありません。
エラー処理
エラーは通常 JSON で返されます。エラーを表示する場合は、まず error.message、次に message、最後に HTTP ステータステキストを読み取ります。
| HTTP ステータス | 意味 | 対処方法 |
|---|---|---|
400 | JSON の形式不正、パラメーター不足、または未対応サイズ | リクエスト本文を確認します。自動再試行しないでください。 |
401 | API Key がない、または無効 | Authorization: Bearer YOUR_API_KEY ヘッダーを確認します。 |
402 または 403 | 残高またはクォータが不足 | error.code を確認してください。403 と error.code=insufficient_user_quota は、実際の画像分の残高はあっても事前承認額には不足している場合があります。 |
429 | レート制限、同時実行数制限、または上流の混雑 | リクエスト拒否を確認できた場合に限り、バックオフして再試行してください。 |
5xx | ゲートウェイまたは上流の障害 | 実行と課金の状態が不明な場合があります。再送前にログと利用履歴を確認してください。 |
統合チェックリスト
- Base URL は
https://bettertoken.ai/v1です。 - ヘッダーに
Authorization: Bearer sk-...を含めます。 - リクエストには
application/jsonを使用します。 - このリクエストで利用可能な Model ID を選びます:
gpt-image-2、gpt-image-2.5-flare、gpt-image-2.5-sunburst。 response_format=b64_jsonを使用します。output_formatは要求値なので、保存前にバイト列から実際の形式を識別します。nは1から10の整数です。まず1を使い、返却枚数が少ない場合も処理します。sizeは省略、auto、有効な寸法を使用できます。上の表はすべての有効値を列挙したものではありません。- HTTP クライアントは生成完了まで数分待機できるようにします。
- ログやエラーのスクリーンショットで API Key や画像の完全な base64 を公開しません。
関連ドキュメント
/v1/images/generations承認
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
ボディ application/json
GPT Image Model ID. One BetterToken API Key works with all available models.
"gpt-image-2"A detailed description of the image to generate.
"A futuristic AI product poster on a light background, with glass textures, a clean composition, and a premium technology aesthetic."Allowed range: 1–10; start with 1. Fewer images may be delivered than requested. Iterate data[] and use actual-delivery billing.
1Omit or use auto for automatic sizing. For WxH, both dimensions must be positive multiples of 16, each at most 3840, aspect ratio at most 3:1, total pixels 655360–8294400. Examples are not an exhaustive enum; 2080x2080 also meets the geometry rules. Inspect actual decoded dimensions. Valid parameters do not guarantee an available service.
"1024x1024"["auto","1024x1024","2048x2048","2080x2080","3840x2160"]Requested output format; png is recommended, but the response is not guaranteed to have been transcoded to PNG. Detect PNG, JPEG, or WebP from actual bytes before choosing an extension. Convert locally if a specific format is required.
"png"gpt-image-2 accepts auto, low, medium, high. The two 2.5 models also accept xhigh and max. Omit for the model default; JSON null is treated as omitted, while multipart requires a nonempty string. Valid values do not guarantee an available service for every model, size, and editing combination. Acceptance does not guarantee that a higher setting improves image quality.
"auto"レスポンス
200BetterToken billing extension. Settlement follows the actual delivered pixels and billing tier, which can differ from the requested tier. Amounts are decimal strings; use the returned values.
OpenAI-compatible image response. Iterate data[] and read each image from b64_json. Fewer images may be delivered than requested.
1710000000Show child attributes
BetterToken billing extension. Settlement follows the actual delivered pixels and billing tier, which can differ from the requested tier. Amounts are decimal strings; use the returned values.
Show child attributes
Settlement currency; do not assume a fixed currency.
Final request amount as a decimal string; use decimal arithmetic for calculations.
Delivered image indices, actual dimensions, billing tiers, and per-image amounts. index is zero-based and corresponds to data[].
Settled amount for this image as a decimal string.
Resolution tier inferred from the request; it may differ from the actual billing tier.
{
"created": 1710000000,
"data": [
{
"b64_json": "iVBORw0KGgoAAAANSUhEUgAA...(truncated)",
"revised_prompt": "<string>"
}
],
"bettertoken_image_billing": {
"currency": "<string>",
"settled_amount": "<string>",
"outputs": [
{
"index": 0,
"width": 1,
"height": 1,
"billing_resolution": "1K",
"currency": "<string>",
"amount": "<string>"
}
],
"partial": false,
"requested_resolution": "<string>"
}
}400Invalid request format, missing parameters, malformed JSON or multipart data, or invalid dimensions.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}401The BetterToken API Key is missing or invalid.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}402The account has insufficient credit or balance.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}403Insufficient balance or token quota: error.code is insufficient_user_quota. Funds must also cover the reservation of the highest-tier unit price times the image-count upper bound, before actual-delivery settlement. Inspect error.code rather than treating every 403 as an authorization error.
{
"error": {
"code": "insufficient_user_quota",
"message": "Insufficient balance or token quota."
}
}429A rate or concurrency limit was reached, or the upstream service is busy.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}500The gateway or upstream service returned an error.
Show child attributes
"invalid request""invalid_request_error""invalid_request""insufficient quota"{
"error": {
"message": "invalid request",
"type": "invalid_request_error",
"code": "invalid_request"
},
"message": "insufficient quota"
}
