HiAPI
ブログ

チュートリアル

HiAPI API で gpt-image-2/text-to-image@ext を呼び出す方法:curl と Python

テキストから画像を生成する機能を統合する開発者向けの実践的なリクエスト演習

Oct 31, 2026
黑绿底上,黄铜色与深绿色扁平缎带以经纬交织方式构成开放式网格,这是教程文章的封面图。

gpt-image-2/text-to-image@ext が提供するもの

gpt-image-2/text-to-image@ext は、HiAPI の統一インターフェースを通じて外部に提供されるテキスト生成画像モデルです。同じエンドポイントにプロンプトと任意の生成パラメータを送信するだけで、生成された画像データを取得できます。モデル専用のコンポーネントをインストールする必要も、ベンダーごとに SDK を個別に接続する必要も、独立したアカウントを管理する必要もありません。同じ API key と同じリクエスト構造で、プラットフォームのその他の機能もカバーできます。

あなたの製品が、テキスト記述を新しい画像に変換する必要があるなら、このモデルを選んでください。マーケティングコピーをメインビジュアルに変換する、ユーザープロンプトをサムネイルに変換する、オンデマンドでコンセプト画像をレンダリングするデザインツールなどです。呼び出しは通常の HTTP リクエストであるため、クライアントライブラリを導入することなく、バックエンドサービス、キューワーカー、スクリプトに簡単に組み込めます。

入力がテキストで、出力が自分で保存・配布する予定のビットマップである場合に、まさに適した選択です。将来プラットフォーム上で別の画像ルートに切り替える必要が生じても、統合ロジック(認証、リクエストエンベロープ、出力処理)は変わりません。変更するのはモデル識別子とパラメータブロックだけです。

このガイドの読み方

この演習は段階的に展開します。まず画像を返す最小限のリクエスト、次に Python 版、続いて単一呼び出しと非同期ポーリングの間の構造上の意思決定、最後に出力処理です。各段階は独立してテストできるため、問題が発生したときにどの変更が原因かを明確に特定できます。

前提条件と認証

最初のリクエストを送信する前に、2 つのものが必要です。HiAPI アカウントと、それに紐づく API key です。アカウントダッシュボードで key を作成し、あらゆる秘密鍵を保管するのと同じ方法で保管してください。ローカルでは環境変数、本番環境では secrets manager を使います。コードリポジトリにコミットしたり、ブラウザに送信されるクライアントコードに貼り付けたりしないでください。

認証はリクエストヘッダーの bearer token で行います。形式は常に同じです:

Authorization: Bearer $HIAPI_API_KEY

シェルで一度この変数を設定すれば、以下の例はキーを表示することなくこれを参照できます:

export HIAPI_API_KEY="your-key-here"

開始前に確認すべき事項

  • その key が有効で、画像生成へのアクセス権限を持っていること。
  • あなたの環境が HiAPI エンドポイントへ外向き HTTPS リクエストを送信できること。
  • 生成ファイルをどこに書き込むかを把握していること。テストではローカルディレクトリ、本番ではオブジェクトストレージ。

key が欠落しているか形式が正しくない場合、問題は最初の呼び出し時に認証エラーとして即座に明らかになります。これは問題を発見する最も早く明確なタイミングです。

実行可能な最小の curl リクエスト

画像を生成できる最小のリクエストから始めます。プロンプト以外はすべて任意であり、最初の呼び出しを簡潔に保つことで、エラーはほぼ確実に認証かリクエスト構造に関係しており、パラメータの衝突ではないことが保証されます。

curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/text-to-image@ext",
    "prompt": "折り畳まれた紙の地図の上に置かれた、まだらのある真鍮製のコンパス、柔らかな窓の光、浅い被写界深度",
    "size": "1024x1024",
    "n": 1
  }'

フィールドごとの説明

  • model——モデル識別子。リクエストを gpt-image-2/text-to-image@ext に紐づける唯一の値であり、正確でなければなりません。
  • prompt——内容の記述。被写体、スタイル、照明について具体的に。曖昧なプロンプトは曖昧な画像を生成し、パラメータエラーよりもデバッグが困難です。
  • size——出力サイズ。パイプラインの検証段階では省略でき、デフォルト値を受け入れます。
  • n——呼び出しごとに生成する画像数。統合中は 1 に保ち、失敗が 1 つの出力に正確に対応するようにします。

レスポンスをファイルに書き込めば、ターミナルでバイナリデータが乱れることなく確認できます:

curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @payload.json -o response.json

画像が返ってきた時点で、動作することが既知のベースラインが得られます。以降の各変更は、それに対するロールバック可能な単一の編集であるべきです。

リクエストを Python に移植する

Python 版は同じリクエストで、転送方法だけが異なります。requests を使います。これは最も予期しない問題が起きにくい選択であり、検証済みの curl フィールドと一対一に対応します。

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ["HIAPI_BASE_URL"]

payload = {
    "model": "gpt-image-2/text-to-image@ext",
    "prompt": "折り畳まれた紙の地図の上に置かれた、まだらのある真鍮製のコンパス、柔らかな窓の光",
    "size": "1024x1024",
    "n": 1,
}

response = requests.post(
    f"{BASE_URL}/v1/images/generations",
    headers={
        "Authorization": f"Bearer {API_KEY}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=120,
)

response.raise_for_status()
data = response.json()

重要なポイントの解説

  • json=payload はコンテンツタイプを設定し、リクエストボディをシリアライズします。手動での文字列連結は不要で、エスケープのバグもありません。
  • 実際には timeout は任意ではありません。画像生成は典型的な JSON API 呼び出しよりも遅いため、タイムアウトがないと上流が遅くなったときにワーカーがハングします。
  • raise_for_status() は HTTP 失敗を、キャッチして分類できる例外に変換します。不正なレスポンスボディが下流に流れることはありません。

payload はインライン文字列ではなく dict として保持してください。後でパラメータを追加するときはキーを追加するだけで、リクエスト構造は変わらず、転送層を再デバッグする必要は決してありません。

SDK スタイルのクライアントを好む場合でも、同じエンドポイントとリクエストヘッダーがそのまま適用されます。呼び出し構文が異なるだけです。まず curl で検証し、その後でアプリが標準化しているクライアントを採用してください。

単一呼び出しと非同期ポーリングの選択

これは構文の意思決定ではなく設計の意思決定であり、リトライとストレージのロジックに、統合における他のどの選択よりも大きな影響を与えます。

単一呼び出し

以下の場合に単一のリクエスト・レスポンスサイクルを使用します:

  • オンデマンドで生成し、ユーザーが待っている。
  • あなたの HTTP 層が長い接続を許容できる。
  • バッチではなく一度に 1 枚の画像を生成する。

観測した最も遅い生成時間に対してタイムアウトを余裕を持って設定し、タイムアウトをハードエラーではなくリトライ可能な失敗として扱ってください。

非同期ポーリング

バッチ処理、リクエストがキューワーカーから来る場合、または呼び出し元がブロックされてはならない場合には非同期を選択します。パターンは、送信し、ハンドルを取得し、完了状態をポーリングするというものです。

import time

def poll_until_done(fetch_status, handle, interval=2, max_wait=300):
    deadline = time.monotonic() + max_wait
    while time.monotonic() < deadline:
        status = fetch_status(handle)
        if status["state"] == "succeeded":
            return status
        if status["state"] == "failed":
            raise RuntimeError(status.get("error", "generation failed"))
        time.sleep(interval)
    raise TimeoutError("generation did not finish in time")

信頼性の高い動作をするポーリングループのルール

  • バックオフ。 短い間隔から始めて徐々に増やします。一定の高頻度ポーリングはクォータとレート予算を無駄にします。
  • 待機を制限。 max_wait の期限は、孤立したタスクがワーカーを永久に占有するのを防ぎます。
  • ハンドルを永続化。 ワーカーが再起動した場合、再送信して重複生成のコストを支払うのではなく、ポーリングを復元できなければなりません。
  • 失敗をタスクごとの終態として扱う。 failed 状態は記録されるべきであり、高頻度ループで黙ってリトライすべきではありません。

早めに決断してください。後から非同期セマンティクスを同期コードパスに改造することは、呼び出し元、ストレージ、エラー処理を同時に書き換えることを意味します。

画像出力の処理

レスポンスには生成された画像が含まれますが、それは JSON エンベロープ内のデータであり、ホットリンク可能な URL ではありません。自分が所有するバイナリ出力として扱ってください。

デコードと永続化

import base64

item = data["data"][0]
image_bytes = base64.b64decode(item["b64_json"])

with open("out.png", "wb") as f:
    f.write(image_bytes)

レスポンスがインラインデータではなく URL を持つ場合、直ちに取得し、バイトを自分のストレージに書き込んでください。生成された URL は一時的です。ユーザーに提供するものはすべて、自分のインフラストラクチャの背後にあるべきです。

配布前に検証する

  • マジックナンバーを確認。 PNG は \x89PNG で始まりますが、HTML のエラーページはそうではありません。数バイトの検証で、HTTP 200 を返すがレスポンスボディが誤っているプロキシの問題を捕捉できます。
  • サイズを記録。 バイト長を記録し、切り詰められたダウンロードが監視で明らかになるようにします。
  • 決定論的ストレージ。 ファイル名はプロンプトテキストではなく生成 ID で付け、プロンプト、パラメータ、レスポンスメタデータを画像と一緒に保存します。この組み合わせにより、後で任意の出力を再現または監査できます。
  • コンテンツタイプを正しく設定——仮定ではなく実際のファイルから導出してください。

メタデータを成果物とともに保持する

小さな付随レコードを書きましょう。モデル識別子、完全なプロンプト、サイズと数量、タイムスタンプ、およびレスポンス内の任意のリクエスト ID です。半年後、誰かがこの画像がなぜこのように見えるのかと尋ねたとき、このレコードがあなたの唯一の答えになります。

よくある障害のデバッグ

ほとんどの初回統合の障害は 3 つのカテゴリに分類されます。この順序で確認してください。診断コストはおおよそ低い順から高い順です。

認証エラー

401 または 403 は、key が間違っている、失効している、または送信されていないことを意味します。機密情報を含まないヘッダー構造を表示して、Bearer プレフィックスとスペースが無傷であることを確認し、リクエストを発行するプロセスで環境変数が実際に設定されていることを確認してください。よくある落とし穴は、シェルでは設定されているが、ワーカーやコンテナでは設定されていないことです。

不正なリクエストボディ

400 は通常、リクエストボディを指します。curl セクションの最小リクエストに戻り、フィールドを 1 つずつ追加し直してください。よくある原因:

  • model 文字列が gpt-image-2/text-to-image@ext と完全に一致しない。
  • リクエストボディが有効な JSON ではない——余分なカンマやエスケープされていない引用符。
  • パラメータの型が間違っている。n は数値であり、文字列ではない。
  • Content-Type: application/json が欠落しており、サーバーがリクエストボディを解析できない。

タイムアウトと遅いレスポンス

画像が返る前に接続が切れた場合、モデルの障害ではなく、クライアントのタイムアウトを超えた可能性が高いです。単一呼び出しの設計ではタイムアウトを延ばし、バッチ形態では非同期ポーリングに切り替えてください。リトライ時には重複生成がないことを確認してください。リクエストがすでに成功した可能性がある場合は、再送信する前に結果が存在しないか確認してください。

上記のいずれでもない場合

失敗したリクエストの完全なレスポンス(ステータスコード、レスポンスヘッダー、レスポンスボディ)をキャプチャし、最小の curl コマンドで再現してください。最小リクエストでも残る障害はあなたの環境の統合問題であり、消える障害はあなたが追加したパラメータを指します。

永続的なAIアーティファクトで開発を始める

APIキーを取得して、タスクベースの1つのAPIで画像・動画・音声モデルを呼び出せます。

APIドキュメントを読む