チュートリアル
hiapi API で gpt-image-2 のイメージ・トゥ・イメージを使う方法
そのまま実行できるコードレシピで、hiapi 上で gpt-image-2 のイメージ・トゥ・イメージ・エンドポイントを呼び出す方法を解説します。リクエストのエンベロープ、参照画像と aspect_ratio パラメータ、ポーリングとコールバックの使い分け、さらにコピー&ペーストで使える curl、Python、Node.js のサンプルを紹介します。
このレシピでは、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 はすべての画像モデルを同じ非同期タスクインターフェースで公開しています:
POST /v1/tasks—— タスクを送信し、taskIdを返します。GET /v1/tasks/{taskId}をstatus === "success"になるまでポーリングするか、callback.urlを指定して webhook で最終結果を受け取ります。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 つの失敗パターンに遭遇します:
401 permission_deniedと"This API key cannot use the selected model."—— そのキーにはgpt-image-2/image-to-imageを使用する権限がありません。hiapi コンソールで確認し、料金ページでそのモデルがプランに含まれているか確認してください。400とadditional properties not allowed—— 特定のモデルが受け付けないフィールドを送信しています(たとえばaspect_ratioの代わりにsizeを使うなど)。エラーメッセージが違反しているキー名を示すので、それを削除して再試行してください。- ポーリング時の
status: "fail"とdata.errorオブジェクト —— モデル自体が入力(不安全なコンテンツ、到達不能な参照 URL など)を拒否しました。error.codeとerror.messageをログに記録し、盲目的に自動再試行しないでください。
POST /v1/tasks の呼び出しには常にリクエストタイムアウトを設定してください(30 秒で十分 —— すぐに taskId を返すため)。ポーリングループや webhook 受信パスには別途、より長いタイムアウトを設定してください。
関連リンク
- gpt-image-2 モデルページ —— 機能マトリクスと料金階層。
- すべての hiapi モデル —— 他の画像モデルや動画モデルが必要な場合は、完全なカタログがここにあります。
- API ドキュメント ——
/v1/tasksおよびインターフェース全体の完全なリファレンス。 - hiapi API で画像を生成する方法 —— このレシピのテキスト・トゥ・イメージ版。
よくある質問
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 回の呼び出しあたりの料金は料金ページをご覧ください。
関連記事
すべての記事を見る →-
チュートリアル
HiAPI API で hailuo-2.3-fast/image-to-video を呼び出す方法:curl と Python の実践
高速・低コストな画像から動画へのティアにおける最初の実行可能なリクエスト — モデル ID から MP4 のダウンロードまで
-
チュートリアル
HiAPI APIでhailuo-2.3/text-to-videoを呼び出す方法:curl、Python、実行可能なリクエスト例
-
チュートリアル
HiAPI で Kandinsky 6.0 Pro のテキストto動画を使用する:curl と Python チュートリアル
リクエスト優先の実践デモ:プロンプトから動画クリップへの呼び出しを構築し、リクエストを送信し、完了状態をポーリングし、結果をダウンロードする