HiAPI
ブログ

チュートリアル

hiapi API で gpt-image-2 のイメージ・トゥ・イメージを使う方法

そのまま実行できるコードレシピで、hiapi 上で gpt-image-2 のイメージ・トゥ・イメージ・エンドポイントを呼び出す方法を解説します。リクエストのエンベロープ、参照画像と aspect_ratio パラメータ、ポーリングとコールバックの使い分け、さらにコピー&ペーストで使える curl、Python、Node.js のサンプルを紹介します。

Jun 26, 2026
hiapi API で gpt-image-2 のイメージ・トゥ・イメージを使う方法

このレシピでは、hiapi の統合タスク API を介して gpt-image-2 のイメージ・トゥ・イメージモードを呼び出す手順を順を追って説明します。そのまま実行できる curl の例、バックエンドに直接組み込める Python スクリプト、サーバーレス環境向けの Node.js 版、そして本当に重要なパラメータと本番環境でつまずきやすい細かい点を手に入れることができます。

この記事を読み終える頃には、参照画像の URL とプロンプトを受け取り、生成された画像の URL を返すスクリプトが完成しています。その URL から直接ダウンロードしたり、ストレージ層に渡したりできます。

準備

  • hiapi アカウントと API キー。hiapi コンソールで取得できます。
  • 公開 HTTPS URL 上でホストされた参照画像(または base64 data URL —— どちらでも構いません)。
  • モデルにその参照画像をどう処理してほしいかを記述したテキストプロンプト。

必要なのはこれだけです。SDK のインストールは不要 —— hiapi は HTTP + JSON なので、POST リクエストを送れる言語なら何でも使えます。

まず純粋なテキスト・トゥ・イメージについて知りたい方は、hiapi API で画像を生成する方法をご覧ください。以下のパターンは同じ非同期タスクフローで、image フィールドが 1 つ増えるだけです。

最小限の動作する呼び出し

hiapi はすべての画像モデルを同じ非同期タスクインターフェースで公開しています:

  1. POST /v1/tasks —— タスクを送信し、taskId を返します。
  2. GET /v1/tasks/{taskId} を status === "success" になるまでポーリングするか、callback.url を指定して webhook で最終結果を受け取ります。
  3. data.output[0].url から画像 URL を読み取り、ダウンロードまたは保存します。

curl

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2/image-to-image",
    "input": {
      "prompt": "transform the subject into a watercolor painting, soft pastel palette",
      "image": "https://example.com/reference.jpg",
      "aspect_ratio": "1:1",
      "resolution": "1K"
    }
  }'

すぐに返されるレスポンスでタスク id が得られます:

{ "data": { "taskId": "task_01HXXXX..." } }

次に結果をポーリングします:

curl https://api.hiapi.ai/v1/tasks/task_01HXXXX... \
  -H "Authorization: Bearer sk-YOUR_KEY"

タスクの準備ができると、レスポンスは次のようになります:

{
  "data": {
    "status": "success",
    "output": [{ "url": "https://cdn.hiapi.ai/...png", "expireAt": "..." }]
  }
}

output[0].url は短期間のみ有効です(expireAt に注意)。そのため、すぐにダウンロードするか、自身のストレージに再アップロードしてください —— エンドユーザーにホットリンクを提供してはいけません。

本当に重要なパラメータ

フィールド 型 説明
model string 裸の id gpt-image-2/image-to-image を使用します。models/ プレフィックスを付けないでください。
input.prompt string 参照画像に適用したい変換内容。
input.image string HTTPS URL または data:image/...;base64,... URL。
input.aspect_ratio string いずれか 1 つ:1:1、3:2、2:3、4:3、3:4、5:4、4:5、16:9、9:16、21:9 または auto。
input.resolution string 1K、2K または 4K。デフォルトは 1K。

重要な動作が 2 つあります:

  • 一部の hiapi モデルは aspect_ratio のみ(resolution なし)を受け付けます。他のモデルはピクセルサイズを必要とします。gpt-image-2/image-to-image は上記の aspect_ratio + resolution の組み合わせを受け付けます —— ここで size: "1024x1024" を渡さないでください。
  • image フィールドは参照画像です。base64 data URL を渡す場合は、ペイロードがプラットフォームのリクエストボディ制限未満であることを確認してください(数 MB なら問題ありません。数メガバイトの画像は先にアップロードして URL で渡すべきです)。

本番運用レベルの Python スクリプト

このバージョンは期限付きでポーリングを処理し、失敗時にはクリーンに終了します:

import os
import time
import requests

API = "https://api.hiapi.ai/v1/tasks"
TOKEN = os.environ["HIAPI_API_KEY"]
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}


def submit(prompt: str, image_url: str, aspect_ratio: str = "1:1") -> str:
    payload = {
        "model": "gpt-image-2/image-to-image",
        "input": {
            "prompt": prompt,
            "image": image_url,
            "aspect_ratio": aspect_ratio,
            "resolution": "1K",
        },
    }
    r = requests.post(API, headers=HEADERS, json=payload, timeout=30)
    r.raise_for_status()
    return r.json()["data"]["taskId"]


def wait(task_id: str, timeout_s: int = 300, interval_s: int = 5) -> str:
    deadline = time.time() + timeout_s
    while time.time() < deadline:
        r = requests.get(f"{API}/{task_id}", headers=HEADERS, timeout=20)
        r.raise_for_status()
        task = r.json()["data"]
        status = task.get("status")
        if status == "success":
            return task["output"][0]["url"]
        if status == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(interval_s)
    raise TimeoutError(f"task {task_id} did not finish in {timeout_s}s")


if __name__ == "__main__":
    task_id = submit(
        prompt="transform the subject into a watercolor painting, soft pastel palette",
        image_url="https://example.com/reference.jpg",
    )
    print("task:", task_id)
    print("url:", wait(task_id))

HIAPI_API_KEY=sk-... python recipe.py で実行します。

Node.js(fetch、依存関係なし)

const API = "https://api.hiapi.ai/v1/tasks";
const TOKEN = process.env.HIAPI_API_KEY;
const headers = {
  Authorization: `Bearer ${TOKEN}`,
  "Content-Type": "application/json",
};

async function submit(prompt, imageUrl, aspectRatio = "1:1") {
  const r = await fetch(API, {
    method: "POST",
    headers,
    body: JSON.stringify({
      model: "gpt-image-2/image-to-image",
      input: { prompt, image: imageUrl, aspect_ratio: aspectRatio, resolution: "1K" },
    }),
  });
  const data = await r.json();
  if (!r.ok) throw new Error(JSON.stringify(data));
  return data.data.taskId;
}

async function wait(taskId, timeoutMs = 300000, intervalMs = 5000) {
  const deadline = Date.now() + timeoutMs;
  while (Date.now() < deadline) {
    const r = await fetch(`${API}/${taskId}`, { headers });
    const task = (await r.json()).data;
    if (task.status === "success") return task.output[0].url;
    if (task.status === "fail") throw new Error(JSON.stringify(task.error));
    await new Promise((res) => setTimeout(res, intervalMs));
  }
  throw new Error(`task ${taskId} timed out`);
}

(async () => {
  const id = await submit(
    "transform the subject into a watercolor painting, soft pastel palette",
    "https://example.com/reference.jpg",
  );
  console.log("task:", id, "\nurl:", await wait(id));
})();

ポーリング vs. コールバック

5 秒ごとのポーリングは一度きりのスクリプトなら問題ありませんが、タスクの間ずっと 1 つのワーカーを占有してしまいます。実際のバックエンドでは、通常 webhook を使いたくなります:

{
  "model": "gpt-image-2/image-to-image",
  "input": { "prompt": "...", "image": "https://example.com/reference.jpg" },
  "callback": { "url": "https://your-app.example.com/api/hiapi-callback", "when": "final" }
}

タスクが確定(成功または失敗)すると、hiapi はその URL に GET /v1/tasks/{id} で得られるものと同じペイロードを POST します。このハンドラは冪等として扱ってください —— 再試行が発生する可能性があります —— また、リクエストを信頼する前に検証してください(URL に独自の署名トークンを含める、Authorization ヘッダーを確認するなど)。

クリーンなパターンは次のとおりです:タスクを送信し、自身の job id をキーにして taskId を永続化し、呼び出し元に 202 Accepted を返し、webhook に保存 + 通知の処理を任せます。

エラーハンドリング

実際には 3 つの失敗パターンに遭遇します:

  1. 401 permission_denied と "This API key cannot use the selected model." —— そのキーには gpt-image-2/image-to-image を使用する権限がありません。hiapi コンソールで確認し、料金ページでそのモデルがプランに含まれているか確認してください。
  2. 400 と additional properties not allowed —— 特定のモデルが受け付けないフィールドを送信しています(たとえば aspect_ratio の代わりに size を使うなど)。エラーメッセージが違反しているキー名を示すので、それを削除して再試行してください。
  3. ポーリング時の status: "fail" と data.error オブジェクト —— モデル自体が入力(不安全なコンテンツ、到達不能な参照 URL など)を拒否しました。error.code と error.message をログに記録し、盲目的に自動再試行しないでください。

POST /v1/tasks の呼び出しには常にリクエストタイムアウトを設定してください(30 秒で十分 —— すぐに taskId を返すため)。ポーリングループや webhook 受信パスには別途、より長いタイムアウトを設定してください。

関連リンク

よくある質問

Q:gpt-image-2/image-to-image は複数の参照画像をサポートしていますか? A:最小限の契約では単一の image フィールドを使用します。ユースケースで複数の参照画像(たとえば被写体画像 + スタイル画像など)が必要な場合は、先に 1 枚に合成するか、モデルページで最新の対応フィールドを確認してください。

Q:URL の代わりにローカルファイルを渡せますか? A:はい —— data:image/png;base64,... URL にエンコードして input.image として渡します。約 3 MB を超えるファイルは、先に自身のストレージにアップロードして公開 URL を渡してください。その方が速く、リクエストボディ制限も回避できます。

Q:1 つのタスクにどれくらい時間がかかりますか? A:ほとんどの gpt-image-2 イメージ・トゥ・イメージタスクは 1K 解像度で 10〜30 秒で完了します。より高い解像度や複雑なプロンプトでは時間がかかることがあります —— 念のため、ポーリングのタイムアウトは 5 分に設定してください。

Q:出力が参照画像とどれだけ異なるかを制御するにはどうすればよいですか? A:プロンプトで明示的に表現してください。「Keep the subject's pose and composition, only restyle to watercolor」は「make this a watercolor」よりも厳密な一貫性を生み出します。gpt-image-2 のイメージ・トゥ・イメージモードはプロンプト駆動です —— リクエストのエンベロープに個別の「strength」スライダーはありません。

Q:output[0].url は永続的ですか? A:いいえ。expireAt タイムスタンプが付いており(通常数時間)、タスク成功後はできるだけ早くバイトをダウンロードして自身のストレージ(R2、S3 など)にアップロードしてください。

Q:画像 1 枚あたりのコストはいくらですか? A:プランと解像度によって異なります。現在の 1 回の呼び出しあたりの料金は料金ページをご覧ください。

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

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

APIドキュメントを読む