HiAPI
ブログ

チュートリアル

HiAPI API で imagen4-ultra を使う方法:curl と Python のサンプル

HiAPI で高品質なテキストから画像生成を行うための完全なリクエスト実践演習

Oct 31, 2026
博客封面图:淡蓝底上多层半透明玻璃平面叠错排列,折射出克制的冷蓝色带。

HiAPI 上の imagen4-ultra でできること

imagen4-ultra は HiAPI の高品質なテキストから画像生成モデルです。プロンプトを送信すると、生成された画像を受け取れます。開発者にとって本当に実用的な点は、プラットフォーム上の他のすべてのモデルと同様に統一された HiAPI インターフェースの背後で動作するため、ここで学ぶ認証方法、リクエスト構造、タスク処理のパターンをそのまま他のエンドポイントにも流用できることです。

このチュートリアルはパラメータの羅列ではなく、実行可能な実践演習です。読み終えると、以下が手に入ります:

  • テキストから画像生成のタスクを送信するためにそのままコピー&ペーストできる curl リクエスト、
  • 同じリクエストを書き換えた小さな Python クライアント、
  • アスペクト比やその他のオプションが出力にどう影響するかの明確な理解、
  • そしてタスクの完了を待ち、画像をディスクに保存するためのポーリングループ。

まず期待値について説明します。画像生成は即時ではありません。imagen4-ultra は非同期で動作します——タスクを送信し、タスク識別子を取得し、レンダリングが完了するまでポーリングします。HiAPI の他の非同期エンドポイントを使ったことがあれば、この流れは馴染み深いでしょう。使ったことがなくても、ポーリングの章でライフサイクル全体をカバーします。

私たちは常に HiAPI 自身の API の範囲内にとどまります。特定ベンダーの SDK も、サードパーティのコンソールも使いません。ベース URL が 1 つ、キーが 1 つ、リクエスト形式が 1 つだけです。

最初のリクエストを送る前に

最初の呼び出しを成功させるには、3 つのものを用意する必要があります。

1. API キー

HiAPI アカウントのコンソールからキーを生成します。パスワードと同じように扱ってください。ソースファイルに直接貼り付けるのではなく、環境変数に保存しましょう。

export HIAPI_API_KEY="your-key-here"

2. ベース URL

すべての HiAPI リクエストは、プラットフォームのドキュメントに記載された同じ API ホストに送信されます。コード内では一箇所にまとめておけば、複数の場所でハードコードする必要はありません:

export HIAPI_BASE_URL="https://api.hiapi.ai"

アカウントやリージョンが別のホストを使用している場合は、コンソールに表示される値を使用してください——以下のリクエストパスは変わりません。

3. 認証情報の渡し方

HiAPI は Authorization リクエストヘッダー内の bearer トークンを使用します。すべてのリクエスト——送信でもポーリングでも——は同じ 2 つのヘッダーを伴います:

Authorization: Bearer $HIAPI_API_KEY
Content-Type: application/json

認証はこれだけです。リクエスト署名のステップも、呼び出しごとのトークン交換もありません。ヘッダーを設定できれば、この API を呼び出せます。

先に進む前に基本チェックを一つ:キーを curl を実行するのと同じシェルセッションでエクスポートしていることを確認してください。「401 Unauthorized」の報告のかなりの割合が、結局はキーをあるターミナルタブでエクスポートし、別のタブで使用していたことに帰着します。

以下では、モデル識別子は常に imagen4-ultra であると仮定します。ご自身のアカウントで公開されている正確な文字列を確認したい場合は、ドキュメントのモデル一覧を参照してください。

実行可能な curl リクエスト

以下は完全な送信リクエストです。プロンプトを送信し、出力のアスペクト比を設定し、単一の画像を1枚要求します。

curl -sS -X POST "$HIAPI_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "imagen4-ultra",
    "prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
    "aspect_ratio": "16:9",
    "n": 1
  }'

リクエストボディをフィールドごとに解説します:

  • model —— 呼び出しているモデルの識別子。リクエストのルーティングを決定します。これがないと、API はどのモデルを実行すべきか分かりません。
  • prompt —— 画像の自然言語による説明。出力品質に最も影響するレバーです。被写体、照明、スタイル、構図について具体的に記述してください。曖昧なプロンプトは曖昧な画像しか生みません。
  • aspect_ratio —— 出力キャンバスの形状を幅:高さで表します。詳細は後述します。
  • n —— この送信で生成する画像の枚数。テスト期間中は 1 のままにしておけば、毎回の実行コストを簡単に見積もれます。

エンドポイントの設定によって、レスポンスには完了した画像が含まれるか、あるいは——この種のモデルではより一般的ですが——識別子とステータスフィールドを持つタスクオブジェクトが含まれます。その識別子を取得してください。ポーリングの章でそれに依存します。

# 送信レスポンスの典型的な構造
{
  "id": "job_abc123",
  "status": "queued"
}

レスポンスを JSON フォーマッタに通してください(あれば | jq .)。そうすれば、自分のアカウントのレスポンスと照らし合わせてフィールド名を理解でき、一行を目を細めて読む必要はありません。

同じリクエストを Python で書く

Python 版は行ごとに対応する翻訳です——同じ URL、同じヘッダー、同じリクエストボディ。requests を使うと対応関係が一目瞭然になります:

import os
import requests

API_KEY = os.environ["HIAPI_API_KEY"]
BASE_URL = os.environ.get("HIAPI_BASE_URL", "https://api.hiapi.ai")

headers = {
    "Authorization": f"Bearer {API_KEY}",
    "Content-Type": "application/json",
}

payload = {
    "model": "imagen4-ultra",
    "prompt": "A lone lighthouse on a rocky coast at dusk, long exposure, dramatic clouds, cinematic lighting",
    "aspect_ratio": "16:9",
    "n": 1,
}

response = requests.post(
    f"{BASE_URL}/v1/images/generations",
    headers=headers,
    json=payload,
    timeout=30,
)
response.raise_for_status()
job = response.json()
print(job["id"], job["status"])

このコードを実際のサービスに取り込む際に、維持すべき点がいくつかあります:

  • キーは環境変数から読み取る。絶対にファイル内のリテラルから読み取らないでください。os.environ[...] という書き方は変数が欠けている場合に明確にエラーを出しますが、これこそが望ましい動作です。
  • 送信呼び出しには明示的なタイムアウトを設定する。タスク自体は非同期で実行されるため、HTTP リクエストはすぐに返るべきです。30 秒の上限は、プログラムをハングさせるのではなく、ネットワークの問題を捕捉します。
  • JSON に触れる前に raise_for_status() を呼び出す。4xx レスポンスのボディは期待する構造ではありません。3 行後に KeyError を投げるよりも、早く失敗させた方が明確なトレースバックが得られます。
  • 大量のタスクを送信する場合は requests.Session を再利用する——コネクションプーリングの効果は見た目以上に重要です。

httpx や aiohttp の方が好みなら、変換は機械的です。同じ headers 辞書、同じ JSON ボディ、同じパスです。リクエスト自体は HTTP ライブラリに依存しません。

アスペクト比とリクエストオプション

アスペクト比は最も頻繁に調整するオプションです。なぜなら構図と、下流のレイアウトで利用可能な出力サイズの両方を変えるからです。

アスペクト比はリクエストボディ内で "width:height" 形式の文字列として渡します——"1:1"、"16:9"、"9:16"、"4:3"、"3:2" などです。画像が最終的に使われる場面に合った比率を選んでください:

  • 1:1 —— アバター、商品タイル、正方形にトリミングされるソーシャル投稿。
  • 16:9 / 9:16 —— キービジュアルバナー、動画サムネイル、縦型ストーリー形式の広告枠。
  • 4:3 / 3:2 —— クラシックな写真構図、ギャラリーレイアウト。

まず正方形で生成してからトリミングするのではなく、意識的に比率を設定してください。トリミングは、すでにお金を払って生成したピクセルを捨てるうえ、被写体を画面外に切り落とす可能性もあります。最終的な掲載場所が分かっているなら、それをリクエストに組み込みましょう。

アスペクト比以外に、日常使用で重要なオプションは以下の通りです:

  • prompt —— 依然として最も影響力のある入力です。他のどこかで調整する前に、まずここを調整してください。
  • n —— 1 回の送信で生成する画像数。複数のバリエーションから選びたいときに便利です。プロンプト探索段階では低い値に保ちましょう。
  • model —— モデルバリアントの正確な識別子。アカウントで複数の画像モデルが公開されている場合、これがそれらの切り替えスイッチです。

そのエンドポイントのドキュメントに記載されたパラメータに従い、名前を推測しないでください。未知のフィールドは 400 レスポンスのよくある原因であり、スペルミスのオプションは大きなリクエストボディ内で見落とされがちです。迷ったら、最小限のリクエストボディ——model、prompt、aspect_ratio——をまず送信し、それが動作することを確認してから、オプションを1つずつ追加してください。

非同期タスクをポーリングして結果をダウンロードする

画像生成には時間がかかるため、送信呼び出しは画像ではなくタスクを返します。ライフサイクルは:送信 → ステータスポーリング → 出力のダウンロードです。

ステップ 1:送信してタスク ID を取得する

前述のリクエストを再利用し、レスポンスから id を取り出します:

job = response.json()
job_id = job["id"]

ステップ 2:タスクが終端状態になるまでポーリングする

同じ認証ヘッダーでステータスエンドポイントをポーリングし、各試行の間にスリープします。API に過大な負荷をかけないよう、段階的にバックオフします:

import time

def wait_for_job(job_id, headers, base_url, timeout=300):
    deadline = time.time() + timeout
    delay = 2
    while time.time() < deadline:
        r = requests.get(
            f"{base_url}/v1/images/generations/{job_id}",
            headers=headers,
            timeout=30,
        )
        r.raise_for_status()
        data = r.json()
        status = data["status"]
        if status == "succeeded":
            return data
        if status == "failed":
            raise RuntimeError(f"job failed: {data}")
        time.sleep(delay)
        delay = min(delay * 2, 15)
    raise TimeoutError(f"job {job_id} not finished within {timeout}s")

重要なポイント:厳格な締め切り、バックオフ間隔の上限設定、そして失敗状態のための明示的な分岐です。これにより、問題のあるタスクはハングし続けるのではなく、例外として明らかになります。

ステップ 3:画像をダウンロードする

完了したタスクのレスポンスには出力の場所——URL または同等の成果物参照——が含まれます。それを取得し、バイトをディスクに書き込みます:

result = wait_for_job(job_id, headers, BASE_URL)
image_url = result["output"][0]["url"]

img = requests.get(image_url, timeout=60)
img.raise_for_status()
with open("lighthouse.png", "wb") as f:
    f.write(img.content)

本番環境でのほとんどの予期せぬ事態を避ける 2 つの習慣:常にバイトモード("wb")で書き込み、テキストモードは絶対に使わないこと。そしてダウンロード URL は一時的なものとして扱い、リンクが無期限に有効であることを期待するのではなく、ファイルをすぐに自分のストレージに保存することです。

よくあるエラーとその修正方法

ほとんどの失敗はいくつかのカテゴリに分類できます。以下に各カテゴリの症状と解決方法を示します。

401 Unauthorized

キーが欠けている、形式が間違っている、またはリクエストを発行するプロセスから見えない状態です。

  • ヘッダーが正確に Authorization: Bearer <key> になっているか確認してください——Bearer という単語、スペース 1 つ、そしてキーです。
  • 環境変数が同じシェルまたはプロセスで設定されていることを確認してください。コンテナや CI では、ローカルシェルでエクスポートした変数はコードと一緒には引き継がれません。
  • 最近キーをローテーションした場合、古いキーがどこかでまだキャッシュされていないことを確認してください。

400 Bad Request

通常はリクエストボディの問題です。

  • 未知またはスペルミスのフィールド名——ドキュメントに記載されたパラメータに従ってください。
  • エンドポイントが受け付けない aspect_ratio の値——ドキュメントの width:height 形式を使用してください。
  • n が許容範囲を超えている。
  • JSON の形式エラー——余分なカンマや、プロンプト文字列内のエスケープされていない引用符など。これが疑われる場合は、送信前にリクエストボディを整形出力して確認してください。

ステータス確認またはダウンロードのステップで 404 が返る

タスク ID が間違っているか、ポーリングしているパスが送信時に使用したエンドポイントと一致していません。初回統合時には送信レスポンスを完全に記録し、ID を 1 文字ずつ照合してください。

ポーリングのタイムアウト

wait_for_job が締め切りに達した場合:

  • 正しいステータス値を確認しているか確かめてください。認識できない終端状態はハングしているように見えます。
  • 大規模で複雑なレンダリングの場合、ポーリング間隔を短くするのではなく、全体のタイムアウト時間を増やしてください。
  • 統合期間中はすべてのステータスレスポンスを記録してください。そうすれば、自分のプロンプトの組み合わせでタスクが実際にどれくらいかかるか分かります。

タスクステータスが failed を返す

API が返すエラーレスポンスボディを読んでください——そこには理由があるのです。失敗したタスクは通常プロンプトまたはパラメータ側の問題であり、修正箇所はポーリングコードではなくリクエストにあります。

不明な点がある場合、そのモデルの HiAPI ドキュメントがフィールド名と許容値の権威ある情報源です。変更は一度に 1 つだけ検証し、次回統合時の参考として動作することが分かっているリクエストを保存しておいてください。

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

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

APIドキュメントを読む