HiAPI
ブログ

チュートリアル

hiapi API で flux-2-klein-9b/image-to-image を使用する方法:curl、Python、実行可能なリクエスト

Jul 30, 2026
hiapi API で flux-2-klein-9b/image-to-image を使用する方法:curl、Python、実行可能なリクエスト

このチュートリアルでは、hiapi の統合タスク API を通じて flux-2-klein-9b の image-to-image モードを呼び出す方法を示します:正確なリクエスト構造、実行可能な curl コマンド、バックエンドにそのまま組み込める Python スクリプト、そしてプラットフォーム上の他のモデルから移行してきた場合に遭遇するスキーマの癖について解説します。

読み終える頃には、単一の参照画像 URL と編集プロンプトを受け取り、ダウンロード可能な生成画像 URL を返すスクリプトが完成しているでしょう。

準備するもの

  • hiapi アカウントと API キー。hiapi コンソールから取得できます。
  • パブリック HTTPS URL でホストされたちょうど 1 枚の参照画像。複数の参照画像を受け付けるプラットフォーム上の一部の image-to-image モデルとは異なり、flux-2-klein-9b の image_urls 配列は最大 1 項目です——詳細は後述します。
  • 編集または変換を記述したテキストプロンプト。

すべてのリクエストは統合タスクエンドポイントに送信し、キーは Authorization ヘッダーに含めます:

POST https://api.hiapi.ai/v1/tasks
Authorization: Bearer sk-<your-key>
Content-Type: application/json

リクエスト構造(およびつまずきやすいフィールド)

モデル id は flux-2-klein-9b/image-to-image です——/v1/models に記載されているとおりに、そのまま渡してください。その input スキーマは厳格です:

フィールド 型 必須 説明
prompt string はい 編集指示。
image_urls string[] はい ちょうど 1 つの参照画像 URL——minItems と maxItems はどちらも 1 です。
aspect_ratio string いいえ 次のいずれか:1:1、4:3、3:4、16:9、9:16。
seed integer いいえ 固定すると結果を再現できます。
output_format string いいえ 次のいずれか:jpeg、png、webp。

コードを書く前に知っておくべき点が 2 つあります:

  1. image_urls は 1 つの URL のみを受け付け、範囲ではありません。1〜14 枚の参照画像を受け付けるモデルを前提に共通の送信コードを組んでいる場合、ここで 2 つの URL を送ると拒否されます——maxItems: got 2, want 1。このモデルは単一画像の編集を行い、複数参照画像の融合は行いません。
  2. 余分なフィールドは無視されず、拒否されます。resolution、size、n、strength、image_size、num_images——これらはプラットフォーム上の他の画像モデルでは一般的ですが、ここではすべて 400 INVALID_REQUEST: additional properties '<field>' not allowed を返します。このモデルのスキーマを確認せずに別モデルの payload を再利用しないでください。

最小の実行可能な例:curl

タスクを作成します:

curl -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer sk-<your-key>" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-2-klein-9b/image-to-image",
    "input": {
      "prompt": "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
      "image_urls": ["https://your-cdn.example.com/subject.png"],
      "aspect_ratio": "3:4",
      "output_format": "png"
    }
  }'

送信に成功すると data 内にタスク id が返されます:

{"code": 200, "data": {"taskId": "tk-hiapi-..."}}

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

curl https://api.hiapi.ai/v1/tasks/tk-hiapi-... \
  -H "Authorization: Bearer sk-<your-key>"

実行中、data.status は queued → handling → archiving と遷移します。完了すると "success" に変わり、画像は data.output に現れます:

{
  "code": 200,
  "data": {
    "status": "success",
    "output": [{"url": "https://.../result.png", "expireAt": "..."}]
  }
}

出力 URL は短時間で失効します(expireAt に注意)。直ちにバイトをダウンロードして自分で保存してください——ホットリンクや元の URL の永続化は絶対に避けてください。

本番向け Python:送信、ポーリング、ダウンロード

import time
import requests

API_BASE = "https://api.hiapi.ai/v1/tasks"
API_KEY = "sk-<your-key>"
HEADERS = {"Authorization": f"Bearer {API_KEY}"}


def edit_image(prompt: str, image_url: str,
               aspect_ratio: str = "1:1", output_format: str = "png") -> bytes:
    # 1. タスクを作成——このモデルの image_urls はちょうど 1 つの URL のみ受け付けます
    resp = requests.post(API_BASE, headers=HEADERS, json={
        "model": "flux-2-klein-9b/image-to-image",
        "input": {
            "prompt": prompt,
            "image_urls": [image_url],
            "aspect_ratio": aspect_ratio,
            "output_format": output_format,
        },
    }, timeout=60)
    body = resp.json()
    if resp.status_code != 200 or not (body.get("data") or {}).get("taskId"):
        raise RuntimeError(f"create failed [{resp.status_code}]: {body}")
    task_id = body["data"]["taskId"]

    # 2. 終了状態までポーリング
    deadline = time.time() + 600
    while time.time() < deadline:
        task = requests.get(f"{API_BASE}/{task_id}", headers=HEADERS,
                            timeout=30).json().get("data") or {}
        if task.get("status") == "success":
            outputs = task.get("output") or []
            if not outputs or not outputs[0].get("url"):
                raise RuntimeError(f"task {task_id} succeeded but returned no output URL")
            # 3. 直ちにダウンロード——URL は失効します
            img = requests.get(outputs[0]["url"], timeout=120)
            img.raise_for_status()
            return img.content
        if task.get("status") == "fail":
            err = task.get("error") or {}
            raise RuntimeError(f"task failed: {err.get('code')} {err.get('message')}")
        time.sleep(5)
    raise TimeoutError(f"task {task_id} still running after 600s")


if __name__ == "__main__":
    png = edit_image(
        "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
        "https://your-cdn.example.com/subject.png",
        aspect_ratio="3:4",
    )
    with open("edited.png", "wb") as f:
        f.write(png)
    print(f"saved edited.png ({len(png)} bytes)")

seed による再現可能な編集

整数の seed を渡すと、モデルはその生成でそれを再利用します。これは他のすべてを変えずにプロンプトの文言を A/B テストしたい場合に役立ちます:

{
  "model": "flux-2-klein-9b/image-to-image",
  "input": {
    "prompt": "Change the jacket to charcoal grey leather, keep the pose and background unchanged",
    "image_urls": ["https://your-cdn.example.com/subject.png"],
    "seed": 42
  }
}

省略すると、モデルは呼び出しごとに seed をランダムに選択します。これは通常の本番トラフィックで望ましい動作です——異なる見た目の出力が必要なときは、seed ではなくプロンプトを変えてください。

ポーリングの代わりにコールバックを使う

スクリプトやワーカーキューではポーリングで十分です。Web バックエンドでは、タスク作成時にコールバックを登録し、hiapi に終了状態をプッシュさせます——callback オブジェクトはリクエストの最上位にあり、model と同じ階層です:

{
  "model": "flux-2-klein-9b/image-to-image",
  "input": { "...": "..." },
  "callback": {
    "url": "https://your-app.example.com/hooks/hiapi",
    "when": "final"
  }
}

"when": "final" を使用すると、タスクが成功または失敗の状態に達したときに、正確に 1 回の POST を受け取ります。ハンドラーには 2 つのルールがあります:

  • 冪等にしてください。処理ロジックをタスク id をキーにすることで、再配信された webhook が重複処理されません。送信時にタスク id を保存し、コールバックは「取得して確定する」トリガーとして扱い、唯一の信頼できる情報源とはしないでください。
  • 照合パスを残してください。コールバックが発火したときにエンドポイントが利用できない場合、未解決の id を定期的にスキャンして /v1/tasks/<id> を GET すれば、漏れたものを捕捉できます。

コールバックがまったく届かないように見える場合は、hiapi タスクのコールバックが発火しない理由を一つずつ確認してください——一般的な障害パターンを可能性の高い順に網羅しています。

エラー処理:3 つの重要な失敗シナリオ

作成時に 401 permission_denied——キーがこのモデルを使用できません。レスポンスボディは次のとおりです:

{"error": {"code": "permission_denied", "message": "...", "request_id": "...", "type": "hiapi_error"}}

この問題が発生した場合は、API キーが無効かどうかを確認するか、コンソールでキーのモデル権限を確認してください。

作成時に 400 INVALID_REQUEST——input がこのモデルのスキーマと一致していません。メッセージは違反しているフィールドを直接指摘します(例:<root>: additional properties 'resolution' not allowed、または image_urls: maxItems: got 2, want 1)。これらは恒久的なエラーです——同じ payload を再試行しても永遠に失敗します。フィールドを修正して再送信してください。

タスクが status: "fail" を返す——作成は成功しましたが生成に失敗しました(バックエンドが取得できない参照 URL、コンテンツポリシー、上流の容量)。タスクの error.code と error.message がどれに該当するかを示します。400 とは異なり、一部は一時的なものであり、バックオフ付きで 1 回再試行する価値があります。

また知っておくべきこと:存在しない、または期限切れのタスク id に対して GET を実行すると 404 task not found が返されます——照合スキャンではこれを「まだ待機中」ではなく終了状態として扱ってください。

次に読むべきもの

よくある質問

flux-2-klein-9b image-to-image に複数の参照画像を渡せますか? いいえ。image_urls の minItems と maxItems はどちらも 1 に設定されています——ちょうど 1 つの URL で、それ以上でもそれ以下でもありません。複数参照画像の融合が必要な場合は、より広い範囲を記録したスキーマを持つモデル、例えば seedream-5.0-lite を確認してください。

なぜ「additional properties 'resolution' not allowed」が返されるのですか? タスク API の input スキーマはモデルごとに異なります。flux-2-klein-9b/image-to-image は resolution や size フィールドをまったく受け付けません——出力サイズは入力画像と aspect_ratio に従います。他のモデルの payload から持ち込んだサイズ関連のフィールドは削除してください。

参照画像を URL ではなく base64 で送信できますか? このモデルのスキーマは image_urls——URL の配列——を受け付けます。画像をアクセス可能な HTTPS URL(任意の CDN、オブジェクトストレージバケット、または事前署名済み URL で構いません)でホストし、その URL を渡してください。

seed は実際に何を制御しますか? 同じ seed、同じ prompt、参照画像を使用すると同じ生成結果が再現されます。これは制御されたプロンプトの A/B テストに役立ちます。通常のトラフィックでは省略し、各呼び出しに独自のランダム seed を割り当ててください。

同じコードは flux-2-klein-9b text-to-image にも使えますか? エンドポイントとフローは同じですが、text-to-image には独自の input スキーマがあります(image_urls はありません)。モデル id を flux-2-klein-9b/text-to-image に置き換え、参照画像を削除してください——必須フィールドはモードによって異なるため、テスト呼び出しで検証してください。

画像 1 枚あたりのコストはいくらですか? 料金は生成ごとの使用量に基づいて課金されます。最新のレートは料金ページで確認してください。

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

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

APIドキュメントを読む