バッチAPIとは?AIへの大量の依頼を半額で処理する仕組み

バッチAPIとは?AIへの大量の依頼を半額で処理する仕組み

AI の API には、1 件ずつ送って答えを待つ使い方のほかに、大量の依頼をまとめて預けて、あとで結果を受け取る使い方があります。

Anthropic・OpenAI・Google の 3 社は、名前は少しずつ違いますが、どれもこの仕組みをバッチ API として用意しています。

料金は 3 社とも通常の半額で、引き換えに手放すのは「すぐに答えが返ること」です。

依頼から結果までの流れと 3 社の上限の違い、向く仕事と向かない仕事が分かると、評価の一括実行や大量の分類にかかる費用を半分にできるかを自分で見極められます。

バッチAPIとは

バッチ API は、たくさんのリクエストを 1 つのジョブにまとめて送り、提供側で非同期に処理してもらい、終わったら結果をまとめて受け取るための API です。

ふだんの API 呼び出しは同期型で、接続を開いたまま 1 件の答えが返るのを待ちます。

バッチ API では、送った時点で返ってくるのはジョブの ID や処理の状態で、答えそのものはまだ入っていません。

処理は提供側で非同期に進み、利用者はあとから状態を確かめて結果を取りに行きます。

3 社の公式ドキュメントは、どれも 24 時間を結果が返るまでの目安にしています。

待つことを受け入れる代わりに、3 社とも次の 2 つを用意しています。

  • 料金が通常の API の 50%
  • 通常の API とは別枠のレート制限

公式ドキュメントが挙げる用途は、大規模な評価、ユーザー投稿のモデレーション、大量のデータの分類や要約、埋め込みの作成などです。

すぐに答えが要らない仕事を、半額と引き換えに後回しにしてもらう仕組みと考えると分かりやすいでしょう。

依頼から結果までの流れ

どの会社のバッチ API も、使い方は 4 つの段階に分かれます。

  1. 依頼を 1 件ずつ ID を付けて並べる
  2. ジョブを作って送る
  3. 状態を確かめながら終わるのを待つ
  4. 結果を受け取り、ID で依頼と突き合わせる

依頼にIDを付けて並べる

1 件ずつの依頼には、利用者が決めた ID を付けます。

Anthropic と OpenAI では custom_id、Google では key と呼ばれる値です。

Anthropic の Message Batches API では、ふだんの Messages API に渡す中身を params に入れ、custom_id と組にして requests の配列に並べます。

次は公式ドキュメントの例をもとに、1 件分に縮めて中身を差し替えた書式です。

手元では実行していません。

{
  "requests": [
    {
      "custom_id": "review-001",
      "params": {
        "model": "claude-opus-5-5",
        "max_tokens": 1024,
        "messages": [{"role": "user", "content": "このレビューは肯定的か否定的か: 配送が早くて助かった"}]
      }
    }
    // 2 件目以降も同じ形で続く(省略)
  ]
}

custom_id は 1〜64 文字で、使えるのは英数字とハイフン、アンダースコアだけです。

OpenAI の Batch API は、依頼を 1 行 1 件の JSONL ファイルに書き、Files API でアップロードしてからジョブを作る方式です。

各行には custom_id と送り先のエンドポイント(/v1/responses や /v1/chat/completions など)、本文を書きます。

1 つの入力ファイルに入れられるのは、1 つのモデルへの依頼だけです。

Google の Gemini Batch API は、20 MB 未満なら依頼を作成リクエストに直接並べる方式、大きいときは JSONL ファイルを File API で上げる方式を選べます。

参考: Claude 公式ドキュメント「Batch processing」

Batch processing

状態を確かめて待つ

ジョブを作ると、ジョブの ID と処理の状態が返ってきます。

Anthropic では、processing_status が in_progress から ended に変わるまで、ID を指定して状態を取り直します。

公式の例は、60 秒ごとに状態を確かめるループです。

OpenAI のジョブは、入力ファイルを検査する validating から始まり、in_progress と結果を用意する finalizing を経て completed になります。

Gemini の状態は JOB_STATE_PENDING・JOB_STATE_RUNNING・JOB_STATE_SUCCEEDED などです。

Gemini では、状態を繰り返し確かめる代わりに、Webhook で完了の通知を受け取ることもできます。

結果をIDで突き合わせる

Anthropic と OpenAI では、処理が終わると結果を 1 行 1 件の JSONL として受け取れます。

Gemini は、入力ファイルで送ったときは JSONL のファイル、直接並べたときは応答の一覧として結果を返します。

ここで大事なのは、結果の並び順は依頼を送った順と一致するとは限らないことです。

Anthropic も OpenAI も、結果は custom_id で依頼と突き合わせるよう公式ドキュメントで明記しています。

Anthropic の結果は、1 件ごとに次の 4 種類のどれかになります。

種類意味課金
succeeded成功して答えが入っているバッチの料金で課金
errored依頼の誤りやサーバー側のエラーで答えが作られなかったなし
canceledジョブを取り消したため、モデルに送られる前に止まったなし
expired24 時間の期限までにモデルに送られなかったなし

この形に合わせて手で作った 4 行の結果ファイル(並び順は review-003・001・004・002)を、ID で突き合わせるコードで読みました。

Windows の Python 3.12.10 で、python -X utf8 match_results.py として実行しています。

import json

sent = ["review-001", "review-002", "review-003", "review-004"]  # 送った順の custom_id
answers, fix, retry = {}, [], []

for line in open("results.jsonl", encoding="utf-8"):  # 1 行が 1 件(送った順とは限らない)
    r = json.loads(line)
    cid, res = r["custom_id"], r["result"]
    if res["type"] == "succeeded":
        answers[cid] = res["message"]["content"][0]["text"]
    elif res["type"] == "errored" and res["error"]["error"]["type"] == "invalid_request_error":
        fix.append(cid)    # 依頼の中身を直してから送り直す
    else:
        retry.append(cid)  # サーバー側の失敗・期限切れ・取り消し

for cid in sent:
    print(cid, answers.get(cid, "-"))
print("直して再送:", fix, "/ そのまま再送:", retry)

出力は次のとおりで、結果ファイルの並びに関係なく、送った順に答えを並べ直せています。

review-001 肯定的
review-002 -
review-003 否定的
review-004 -
直して再送: ['review-004'] / そのまま再送: ['review-002']

依頼の誤り(invalid_request_error)は中身を直してから送り、それ以外のエラーはそのまま送り直す、という分け方は公式ドキュメントのコード例に合わせました。

期限切れと取り消しはモデルに送られていない依頼なので、このコードでは再送の候補に入れています。

OpenAI では、成功した依頼は出力ファイルに、失敗した依頼はエラーファイルに分かれて書き出されます。

3社のバッチAPIを比べる

基本の考え方は同じでも、上限や期限の数字は会社ごとに違います。

次の表は、2026年10月20日に各社の公式ドキュメントで確かめた値です。

項目AnthropicOpenAIGoogle(Gemini)
料金通常の 50%通常の 50%通常の 50%
処理時間の目安多くは 1 時間以内・24 時間で期限切れ24 時間以内(指定できる期限は 24h だけ)目標は 24 時間・48 時間を超えると期限切れ
1 回に送れる量10 万件か 256 MB の早いほう5 万件・入力ファイルは 200 MB まで直接並べるなら 20 MB 未満・入力ファイルは 2 GB まで
依頼の渡し方リクエスト本文に配列で入れるJSONL を Files API で上げる直接並べるか JSONL ファイル
結果の保存期間作成から 29 日完了から 30 日で出力ファイルを自動削除既定で 6 週間

レート制限も通常の API とは別枠で数えられます。

Anthropic には処理待ちにできる依頼の件数の上限があり、OpenAI と Google ではモデルごとに処理待ちにできるトークン数の上限があります。

OpenAI は、バッチを作れるのは 1 時間に 2,000 回までと定めています。

参考: OpenAI 公式ドキュメント「Batch API」

Batch API | OpenAI API

参考: Gemini API 公式ドキュメント「Batch API」

Batch API  |  Gemini API  |  Google AI for Developers

向いている仕事と向かない仕事

バッチ API が向くのは、件数が多く、結果を数時間後に受け取っても困らない仕事です。

  • 評価用のテストケースを数千件流して、モデルやプロンプトを比べる
  • 溜まった問い合わせやレビューを分類・要約する
  • 文書を埋め込みに変換して検索用のデータを作る(OpenAI と Google)
  • 商品説明などの文章をまとめて作る

反対に、人が画面の前で答えを待っている仕事には向きません。

チャットのように数秒で返す必要があるものは、通常の API で呼び出します。

Anthropic のバッチでは、ストリーミング(stream: true)と Fast mode の speed は使えず、指定すると検証エラーで返されます。

前の答えを見て次の依頼を決める処理も、1 つのバッチの中では組めません。

バッチの中の依頼はそれぞれ独立に処理されるので、前の結果を受けて次を送るには、結果を受け取ってから次のバッチを作ることになります。

一方で、1 件の依頼の中で完結するツールの往復なら、バッチでも問題ありません。

Anthropic では、ウェブ検索やコード実行などのサーバーツールがバッチの中でも使え、同期の API と同じループが API 側で回ります。

1 件の中で往復が終わらなかったときは stop_reason が pause_turn で返るので、続きは別の依頼として送ります。

費用を下げる手段には、質問の難しさで使うモデルを振り分ける LLM ルーティングもあり、バッチとは別の軸として組み合わせられます。

LLMルーティングとは?質問ごとにモデルを選ぶ仕組み

プロンプトキャッシュと重ねる

同じ長い前置き(システムプロンプトや資料)を多くの依頼で共有するなら、プロンプトキャッシュと組み合わせられます。

Anthropic の料金ページには、キャッシュの倍率とバッチの割引は重ねて適用されると書かれています。

キャッシュの読み出しは、標準では通常の入力料金の 0.1 倍で、一部のモデルはさらに低く設定されています。

参考: Claude 公式ドキュメント「Pricing」

Pricing

ただし、バッチの依頼は並行して順不同で処理されるため、キャッシュに当たるかどうかはベストエフォートです。

公式ドキュメントによると、利用者のキャッシュのヒット率は、依頼の流れ方によって 30〜98% の幅があります。

バッチの処理は 5 分から 1 時間ほどかかることが多く、5 分のキャッシュでは途中で切れやすくなります。

そのためプロンプトキャッシュの公式ドキュメントの FAQ では、1 時間のキャッシュを使う次の手順が勧められています。

  • 共通の前置きを持つ依頼を集める
  • 前置きに 1 時間のキャッシュを付けた依頼を 1 件だけバッチで送り、キャッシュを書き込む
  • その 1 件が終わったら、残りの依頼をまとめて送る

キャッシュを先に温めるための max_tokens: 0 の依頼は、バッチの中では使えません。

参考: Claude 公式ドキュメント「Prompt caching」

Prompt caching

Gemini でも、依頼ごとに cached_content を指定すれば、バッチの中でコンテキストキャッシュを使えます。

キャッシュの書き込みと読み出しの損益分岐は、プロンプトキャッシュの記事で計算しています。

プロンプトキャッシュとは?API料金を下げる仕組みを整理

つまずきやすいところ

最後に、使い始めてから気づきやすい点を 5 つ挙げます。

依頼の誤りは処理が終わるまで分からない

Anthropic のバッチでは、1 件ずつの params の検証が非同期に行われ、誤りはバッチ全体の処理が終わってから返ってきます。

数万件を送ってから形の誤りに気づくと、待った時間がそのまま無駄になります。

公式ドキュメントのおすすめは、先に同じ形の依頼を通常の Messages API で 1 件送り、通ることを確かめる方法です。

OpenAI では、最初の validating で入力ファイルが検査され、通らなければジョブが failed になります。

作り直すとジョブが2つになる

送ったバッチは、あとから中身を変えられません。

Anthropic では、直すときは取り消してから送り直すよう案内されていて、取り消しはすぐには効かないことがあります。

OpenAI の取り消しも、処理中の依頼が終わるまで最大 10 分は cancelling のままです。

Gemini は、ジョブの作成が冪等ではないと明記していて、同じ作成リクエストを 2 回送ると別々のジョブが 2 つできます。

通信が途切れて作成を再試行するときは、一覧でジョブが既にできていないかを確かめてから送るのが確実です。

期限切れの扱いが会社ごとに違う

Anthropic では、24 時間の期限までにモデルに送られなかった依頼は expired になり、その分は課金されません。

混み具合や依頼の量によっては処理が遅くなり、期限切れが増えることもあると書かれています。

OpenAI では、期限切れになると未処理の依頼は取り消され、終わっていた依頼の結果は出力ファイルに残ります。

終わっていた分のトークンは課金され、期限切れの依頼は batch_expired としてエラーファイルに書かれます。

Gemini は、48 時間を超えて待機か処理中のままだったジョブを期限切れにし、その場合は取り出せる結果がありません。

使用額の上限を少し超えることがある

Anthropic では、ワークスペースに使用額の上限を設定していても、バッチは並行して大量に処理されるため、上限をわずかに超えることがあると明記されています。

上限ぎりぎりまで使っている月に大きなバッチを流すときは、余裕を見ておく必要があります。

結果には保存期間がある

結果は、取りに行かないまま置いておくと消えます。

Anthropic のバッチは、依頼と応答のデータを作成から最大 29 日保存し、処理が終わったバッチは API でいつでも削除できます。

29 日は処理の終了ではなく作成の時刻から数えるので、結果は早めに取り出しておくと安心です。

最後に

バッチ API は、急がない大量の依頼を 24 時間以内を目安に処理してもらう代わりに、料金を半分にする仕組みです。

依頼に ID を付けて送り、結果を ID で突き合わせるという型を押さえれば、3 社のどれでも同じ考え方で使えます。

まずは評価や分類のように、件数が多くて結果を待てる仕事を通常の API から切り分けるところから始められます。

以上です。

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

CAPTCHA