HiAPI
ブログ

チュートリアル

HiAPI API で grok-4.7 を使う方法:curl、Python、そして実際に動く1回のリクエスト

初回リクエストからレスポンス検証までの実践ガイド

Nov 3, 2026
HiAPI 博客教程封面图:多层半透明玻璃平面在浅色背景上折射出克制的冷蓝色带。

初回リクエストの前に用意するもの

API に何かを送る前に、4つの項目が揃っていることを確認してください。このうちどれか1つを飛ばすことが、初回呼び出しが失敗する最もよくある原因であり、しかも失敗の原因はモデルそのものとは無関係であることがほとんどです。

HiAPI アカウント

有効な HiAPI.ai アカウントが必要です。ダッシュボードにログインして、プロジェクト、キー、使用量を管理します。このチュートリアルの操作はすべて同じ統一 API インターフェースを通じて行われるため、ここで作成したキーはプラットフォームが提供する各モデル間で共通して使えます。

API キー

ダッシュボードで API キーを作成し、安全な場所に保管してください。テスト時はシェルの環境変数、本番で動かすものにはシークレットマネージャーを使います。キーをコードリポジトリにコミットしたり、クライアントアプリに貼り付けたりしないでください。

ローカルテストなら、シェルセッションごとに1回エクスポートするだけで十分です:

export HIAPI_API_KEY="your-api-key-here"

ベース URL

ベース URL は HiAPI API のルートアドレスです。このチュートリアルのすべてのリクエストはこれを基準にします。ダッシュボードを確認して、あなたのアカウントで使うべき正確なベース URL を調べ、変数に保存してスクリプトとアプリコードが同じ値を参照するようにしてください:

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

モデル識別子

このチュートリアルで使うモデル識別子は grok-4.7 です。リクエストボディに素の文字列として渡します。識別子が誤っている場合は、通常は明示的なエラーが返り、黙ってフォールバックすることはないため、スペルミスはすぐに見つかります。

この4つ——アカウント、キー、ベース URL、モデル ID——が揃えば、リクエストの形に必要なものはすべて手に入ります。curl 方式では SDK をインストールする必要はなく、Python 方式でもおそらくすでに手元にある HTTP クライアントだけで済みます。

簡単な環境チェック

キーとベース URL が、これから使うシェルから見えることを確認します:

[ -n "$HIAPI_API_KEY" ] && echo "key set"
[ -n "$HIAPI_BASE_URL" ] && echo "base url set"

両方の行が表示されれば、次のセクションに進めます。

HiAPI 上の grok-4.7 リクエストの形

このチュートリアルのすべてのリクエストは、同じ4つの要素を共有しています:エンドポイント、認証ヘッダー、モデルフィールド、そして messages 配列です。これらを個別に理解しておくと、後でストリーミングやツール呼び出しを理解するのがずっと楽になります。これらの機能はこの形の一部を変えるだけだからです。

エンドポイント

呼び出しは、ベース URL 配下のチャット補完エンドポイントへの POST リクエストです。このチュートリアルでは次のように表します:

POST {HIAPI_BASE_URL}/v1/chat/completions

ダッシュボードに別のパスが表示されている場合は、ダッシュボードのパスを使ってください。どちらでもリクエストボディは同じです。

認証ヘッダー

認証は Authorization ヘッダーの bearer token で行います:

Authorization: Bearer $HIAPI_API_KEY

クエリパラメータではなくヘッダーなので、キーが URL、アクセスログ、ブラウザ履歴に現れることはありません。

コンテンツタイプ

リクエストボディは JSON なので、Content-Type: application/json を送ります。curl や任意の Python HTTP クライアントが設定してくれますが、ヘッダー集合に曖昧さを残さないためにも明示的に書く価値があります。

リクエストボディ:model と messages

リクエストボディは、少なくとも2つのフィールドを持つ JSON オブジェクトです:

  • model — モデル識別子の文字列。ここでは grok-4.7。
  • messages — 順序付けられたメッセージオブジェクトの配列。各オブジェクトは role と content を持ちます。よく使う role は:会話の枠組みを定める指示の system、リクエスト自体の user、会話を継続するときに以前のモデルのターンを渡す assistant です。

最小のリクエストボディは次のようになります:

{
  "model": "grok-4.7",
  "messages": [
    { "role": "system", "content": "You are a concise technical assistant." },
    { "role": "user", "content": "Explain what an idempotent HTTP method is in two sentences." }
  ]
}

基本的な呼び出しの約束事はこれで全部です。それ以外——ストリーミングやツール定義——は同じオブジェクトへの追加フィールドです。だからこそ前のセクションが重要なのです:この形さえ正しければ、残りはすべて追加でしかありません。

レスポンスの見え方

レスポンスは JSON オブジェクトです。ほぼ必ず欲しくなる部分は choices の下にあり、これは配列です。各エントリは role と content を含む message を持ちます。さらに、リクエストを処理したモデルやトークン数を表す usage ブロックなどのメタデータもあります。choices[0].message.content を読めば、それが答えのテキストです。他のフィールドはログ記録やコスト追跡には役立ちますが、入門には必要ありません。

実際に動く curl リクエスト

キーをエクスポートし、リクエストの形を理解した後なら、curl の呼び出しは短く済みます。問題をアプリコードから切り離して確認したいときは、これをコピーしてください。

curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "grok-4.7",
    "messages": [
      { "role": "system", "content": "You are a concise technical assistant." },
      { "role": "user", "content": "In one sentence, what is a bearer token?" }
    ]
  }'

各フラグの役割

  • -sS は出力を静かにしつつ、エラーは表示します。これがないと、失敗したリクエストが空のレスポンスのように見えることがあります。
  • URL はベース URL 変数とチャット補完パスを組み合わせたものなので、スクリプトにホストをハードコードする必要はありません。
  • -H "Authorization: ..." は bearer token を送ります。変数はシェルが展開するので、先にエクスポートしておくことが重要でした。
  • -H "Content-Type: application/json" はリクエストボディが JSON であることをサーバーに伝えます。
  • -d '...' はリクエストボディです。JSON を囲むシングルクォートは、中の波かっこや引用符がシェルに解釈されるのを防ぎます。

リクエストボディをファイルに置きたい場合は、body.json に書き出して -d 引数を -d @body.json に置き換えてください。messages 配列が長くなると、こちらのほうがたいてい見通しがよくなります。

生の JSON を読む

レスポンスは JSON オブジェクトとして標準出力に届きます。目で確認したいときは、フォーマッタにパイプします:

curl -sS "$HIAPI_BASE_URL/v1/chat/completions" \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d @body.json | python -m json.tool

choices 配列が見え、その最初の要素が content 文字列を持つ message オブジェクトを含んでいるはずです——その文字列がモデルの答えです。それと並んで、通常はレスポンスの識別子、エコーバックされたモデル名、プロンプトと補完のトークン数を含む usage オブジェクトも見えます。ここで成功レスポンスを記録しておきましょう。Python クライアントを検証するとき、それが比較の基準になります。

この段階でよくある失敗

401 はほぼ必ず、bearer token が欠けている、形式が誤っている、または現在のシェルで実際にはエクスポートされていないことを意味します。400 にリクエストボディに関するメッセージが伴う場合、通常は JSON の形式エラーです——末尾のカンマや、ドキュメントから貼り付けたスマートクォートがよくある犯人です。他の何かを見る前に、この2つを直してください。

同じリクエストを Python で実装する

Python 版は、同じリクエストボディで同じことをします。書き直す意義は、シェルでのテストからアプリに組み込めるコードへ移行することにあり、リクエストボディが引用符付きの文字列ではなくデータ構造になる点にあります。

標準ライブラリを使う

依存を追加したくないなら、urllib で十分です:

import json
import os
import urllib.request

api_key = os.environ["HIAPI_API_KEY"]
base_url = os.environ["HIAPI_BASE_URL"]

payload = {
    "model": "grok-4.7",
    "messages": [
        {"role": "system", "content": "You are a concise technical assistant."},
        {"role": "user", "content": "In one sentence, what is a bearer token?"},
    ],
}

request = urllib.request.Request(
    f"{base_url}/v1/chat/completions",
    data=json.dumps(payload).encode("utf-8"),
    headers={
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json",
    },
    method="POST",
)

with urllib.request.urlopen(request) as response:
    body = json.loads(response.read().decode("utf-8"))

print(body["choices"][0]["message"]["content"])

requests を使う

環境に requests がすでにあるなら、呼び出しはもっと短くなります:

import os
import requests

response = requests.post(
    f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
    json={
        "model": "grok-4.7",
        "messages": [
            {"role": "system", "content": "You are a concise technical assistant."},
            {"role": "user", "content": "In one sentence, what is a bearer token?"},
        ],
    },
    timeout=60,
)
response.raise_for_status()
print(response.json()["choices"][0]["message"]["content"])

この版がアプリにとってより安全な理由

意図的な選択が3つあることに注目してください。キーとベース URL は環境変数から取得し、ソース中のリテラルからは決して取りません。リクエストボディは Python の辞書なので、引用符の位置を誤ると、紛らわしいサーバー側の拒否ではなく、ただちに SyntaxError になります。そして呼び出しにはタイムアウトを設定しています:タイムアウトがないと、停止した接続がワーカープロセスを無期限にハングさせることがあります。

curl で使ったのと同じプロンプトで Python 版を実行してください。答えの言い回しは実行ごとに多少変わるかもしれません——モデルは決定的ではないからです——が、レスポンスの構造は完全に一致するはずです:choices 配列、content を持つ message、そして usage ブロック。構造が一致すれば、クライアントは正しく接続されており、残りのセクションは任意の強化策です。

ストリーミングを有効にする

ストリーミングはトークンの届き方を変えるもので、リクエストする内容を変えるものではありません。完全な答えを待つのではなく、徐々に受け取るので、チャットインターフェースが応答的に感じられるのはこのためです。

リクエストの変更点

すでにあるリクエストボディにフィールドを1つ追加します:

{
  "model": "grok-4.7",
  "stream": true,
  "messages": [
    { "role": "user", "content": "Count from one to five, one number per line." }
  ]
}

エンドポイント、ヘッダー、messages の他の部分は何も変わりません。先に基本の形を学ぶことが重要なのはまさにこのためです:ストリーミングは追加のフラグであり、第二の API ではありません。

何が返るか

stream を有効にすると、レスポンスは単一の JSON オブジェクトではなくなります。サーバー送信イベント(SSE)の列になります。各イベントは data: 行を1つ運び、そのペイロードは JSON の断片で、形は通常のレスポンスと同じですが、choices[0] には完全な message ではなく delta オブジェクトが入っています。最初の断片は role だけを含むことがあり、中間の断片は content の断片を運び、ストリームは番兵行 data: [DONE] で終わります。

クライアント側のあなたの仕事は、delta.content 文字列を順番に連結し、番兵で止めることです。content を持たない断片はエラーではなく何もしないものとして扱ってください。

Python でデータブロックを消費する

import json
import os
import requests

with requests.post(
    f"{os.environ['HIAPI_BASE_URL']}/v1/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"},
    json={
        "model": "grok-4.7",
        "stream": True,
        "messages": [{"role": "user", "content": "Count from one to five."}],
    },
    stream=True,
    timeout=60,
) as response:
    response.raise_for_status()
    for line in response.iter_lines():
        if not line:
            continue
        line = line.decode("utf-8")
        if not line.startswith("data: "):
            continue
        data = line[len("data: "):]
        if data == "[DONE]":
            break
        delta = json.loads(data)["choices"][0].get("delta", {})
        text = delta.get("content")
        if text:
            print(text, end="", flush=True)

ストリーミングが正常に動くか、ハングしたように見えるかを決めるのは2つの細部です。HTTP クライアントに stream=True を渡してレスポンスボディ全体をバッファリングさせず、レスポンスを一度に読むのではなく行単位で反復します。print の flush=True は画面上で見えるものにだけ関係します。これがないと、データブロックが届くたびに処理していても、出力が最後にまとめて噴き出したように見えることがあります。

ストリーミングを単独で検証する

同じテストでストリーミングとツール呼び出しを同時に検証しないでください。まず、連結したテキストが単純なプロンプトに対して妥当な答えになっていることを確認し、それから機能を1つずつ追加します。ストリームが番兵なしで終わるなら、それはモデルではなく接続を確認するシグナルです。

ツール呼び出しのオプション

ツール呼び出しを使うと、モデルはテキストを生成するだけでなく、あなたのコードで定義された関数を要求できるようになります。リクエスト側への追加の仕方はストリーミングとまったく同じです。

オプションをどこに置くか

ツール定義はリクエストボディ上の tools 配列です。各エントリは呼び出し可能な項目を記述します:名前、いつ使うかの説明、そしてその引数の JSON schema 記述です。説明は見た目以上に重要です——モデルがツールをいつ適用すべきか判断する唯一の手がかりだからです。

{
  "model": "grok-4.7",
  "messages": [
    { "role": "user", "content": "What is the weather in Lisbon right now?" }
  ],
  "tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Return the current weather for a named city.",
        "parameters": {
          "type": "object",
          "properties": {
            "city": { "type": "string", "description": "City name, e.g. Lisbon" }
          },
          "required": ["city"]
        }
      }
    }
  ]
}

覚えておくべき形は type と function で、その中に name、description、parameters がネストされます。すでに JSON schema 定義があるなら、parameters ブロックがそれを置く場所です。

モデルはどう返答するか

モデルがツールが必要だと判断すると、choices[0] の assistant メッセージは通常のテキストではありません。その content は通常空で、tool_calls 配列を運びます。各エントリは識別子、あなたの定義のいずれかと一致する関数名、そして JSON を含む arguments 文字列を持ちます。その arguments 文字列をパースしてください——それは文字列であってオブジェクトではなく、オブジェクトとして扱うことがよくあるエラーの原因です。

あなたのコードはその後その関数を実行し、後続のリクエストを送ります:元の会話、tool_calls 付きの assistant メッセージ、そして呼び出し識別子と結果を含む role が tool の新しいメッセージです。モデルはその結果を使って最終的な答えを生成します。tool_call_id は assistant メッセージの識別子と一致しなければなりません。それがなければ、後続のリクエストは曖昧になります。

実用的な防御策

  • パースした引数を、送信したのと同じ schema で検証してください。モデルは schema に導かれますが、拘束されるわけではありません。
  • 返された関数名は信頼できない入力として扱い、明示的な関数の許可リストにのみルーティングしてください。
  • 初回テストで stream とツールを同時に有効にしないでください。まず非ストリーミングのツール往復をエンドツーエンドで確認し、その後、ユースケースが両方を必要とするなら組み合わせてください。

本番前にレスポンスを検証する

ターミナルで動く1回の呼び出しは、検証済みの統合と同じではありません。このチェックリストを一通り実行し、その後スクリプトをスモークテストとして残してください。

トランスポート層を確認する

何かをパースする前に、HTTP ステータスが 200 であることを確認してください。先にパースするクライアントは、本当の問題が 401 のときに紛らわしい KeyError を出します。ステータスを明示的にアサートし、失敗時はレスポンスボディとともにログに記録してください——サーバーはたいてい何が悪かったかを示してくれます。

レスポンス構造を確認する

仮定せず、アサートしてください。成功した非ストリーミング呼び出しでは、3つのことを検証します:choices が存在して空でないこと、choices[0].message.content が空でない文字列であること、レスポンスでエコーバックされたモデルが送信したものと一致すること。最後のチェックは驚くほど多くの設定ミスを捕まえます——デフォルトモデルがリクエストしたモデルを上書きしているケースです。

エラーパスを意図的に演習する

障害が起きてからコードの振る舞いを知るのを待たないでください。3つの迅速なネガティブテストを実行します:

  • 認証ヘッダーを外して呼び出し、コードが無限リトライではなく明確な認証エラーを表面化することを確認する。
  • model フィールドを欠いたリクエストボディを送り、ハングではなくクライアントエラーが返ることを確認する。
  • 意図的に非常に長いプロンプトを送り、タイムアウトと切り捨ての処理が期待どおりに振る舞うことを確認する。

それぞれが、漠然とした「何か問題が発生しました」ではなく、具体的で記録された失敗を生むべきです。

強化機能を個別に検証する

ストリーミングを有効にしたなら、連結したデータブロックが一貫した答えを形成し、番兵がループを終了させることを確認してください。ツールを有効にしたなら、往復の完了を確認してください:ツール呼び出しがパースされ、関数が実行され、結果が一致する識別子を伴って返り、最終的なテキストの答えが生成されること。各検証をそれぞれ小さなスクリプトに分けておけば、失敗が特定の機能を指し示します。

チェックを再現可能にする

一連の流れ全体を1つのファイルに入れ、いずれかのアサートが失敗したら非ゼロコードで終了させ、デプロイのたびにステージング設定に対して実行してください。数秒で済むはずで、基本呼び出し、1回のストリーミング呼び出し、ツールを使うならさらに1回のツール往復をカバーします。これが通れば、本番での失敗は基盤のパイプラインではなく、あなたが送ったリクエストにあると信頼できます。

チェックが通ったら、もう一度 curl 呼び出しを実行してください。生の JSON がアプリの出力と一致すれば、統合は完了です。

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

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

APIドキュメントを読む