見積もりとプロトコル互換
支払う前にリクエストの正確な価格を確かめてその価格のまま送信する方法、応答を受け取れなかったときの復旧方法、そしてテキストと動画の互換 API がどう課金されるかを説明します。
特定のリクエストを見積もる
見積もりは、1 つの具体的なリクエストの価格を、支払う前に教えてくれるものです。見積もりは無料で、タスクは作成されず、資金も仮押さえされません。そのあと見積もりを付けて同じリクエストを送信すると、そのリクエストは表示された価格でしか受理されません。
以下のコマンドは macOS または Linux のターミナル向けで、クイックスタートの説明どおりに SPICY_API_KEY が設定されていることを前提にしています。MODEL_ID_FROM_CATALOG は仮の値です。ライブカタログ(GET /api/v1/models)にある model の値を使い、input のフィールドはすべてそのモデルのスキーマに従って書いてください。
送るつもりのリクエストを保存する
request.json という名前のファイルを作り、実際に送信する model、input、(使う場合は)callBackUrl を、送信するときとまったく同じ内容で書きます。
{
"model": "MODEL_ID_FROM_CATALOG",
"input": { "prompt": "A cinematic night portrait" }
}価格を問い合わせる
curl https://api.spicyapi.ai/api/v1/jobs/quote \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
--data-binary @request.json{
"code": 200,
"msg": "success",
"data": {
"quoteId": "QUOTE_ID_FROM_RESPONSE",
"model": "MODEL_ID_FROM_CATALOG",
"estimatedCost": "0.008",
"maxCharge": "0.008",
"currency": "USD",
"quantity": "1",
"unit": "per_image",
"expiresAt": "2026-09-17T10:05:00Z"
},
"request_id": "req_01k3m8x9q2z4v7n5p6r8s0t1w2"
}金額は米ドル建ての十進数の文字列です。maxCharge はこのリクエストにかかりうる最大額で、現在は常に estimatedCost と同じ値です。quantity と unit は、何を数えているか(たとえば動画の秒数)を表します。支出を承認する人には、金額と expiresAt を見せてください。
見積もりは実際の送信と同じチェックを行うので、この段階ですでに失敗することがあります。返るのは、400(入力がモデルのスキーマに合わない)、40201(残高不足)、40202(キーの利用上限、またはプラットフォームの割り当てに到達)、403(このキーではこのモデルを使えない)です。
見積もりを付けて同じリクエストを送信する
5 分以内に、何も変えていないリクエストを createTask に送ります。このとき、2 つのフィールドを追加します。見積もりで返ってきた quoteId と、見積もりの estimatedCost と同じ値を入れた expectedCost です。このステップではお金がかかります。
{
"model": "MODEL_ID_FROM_CATALOG",
"input": { "prompt": "A cinematic night portrait" },
"quoteId": "QUOTE_ID_FROM_RESPONSE",
"expectedCost": "0.008"
}SPICY_IDEMPOTENCY_KEY="$(uuidgen)" # 新しいタスクごとに 1 回だけ作る。再利用するのは、このリクエストをそのまま送り直すときだけ
curl https://api.spicyapi.ai/api/v1/jobs/createTask \
-H "Authorization: Bearer $SPICY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $SPICY_IDEMPOTENCY_KEY" \
--data-binary @submit.json応答は、クイックスタートで説明している通常の 202 Accepted のタスク応答です。見積もりは Idempotency-Key の代わりにはなりません。両方を送ってください。
| 見積もりが結び付いているもの | 見積もりが使えなくなるとき |
|---|---|
| あなたのアカウントと、見積もりを取得した API キー | 別のキーで送信したとき |
まったく同じ model、input、callBackUrl | どれか 1 つでも変わったとき。プロンプトが 1 文字違うだけでも同じです。フィールドの順序や空白は関係ありません |
| その時点の価格 | 5 分が過ぎたとき、または価格が変わったとき |
40901 は、見積もりがもうそのリクエストに当てはまらないという意味です
入力の変更、別の API キー、期限切れの見積もり、価格の変更、見積もりと異なる expectedCost。これらはすべて同じ形で表に出ます。受理が 40901 で失敗し、何も課金されません。見積もりを取り直して、もう一度確認してください。quoteId と expectedCost を外して、価格の確認なしにリクエストを押し通すことはしないでください。
ネイティブのテキストストリームである POST /api/v1/jobs/stream も、同じ方法で見積もりを受け付けます。テキストとストリーミングを参照してください。
応答を受け取れなかったときの復旧
送信がタイムアウトしたり接続が切れたりすると、リクエストが受理されたかどうかがわかりません。createTask、retry、POST /v1/videos の場合は、次のようにしてください。
- 元のリクエストを、元の
Idempotency-Keyを付けて、同じ API キーで送り直します。元のタスクが現在の状態で返ってきて、二重に課金されることはありません。 - 新しいキーで別のタスクを作らないでください。新しいキーは、新しい生成と新しい課金を意味します。
- すでに受理されたリクエストの再送は、見積もりの期限が切れたあとも有効です。期限が制限するのは受理であって、受理によって作られたタスクではありません。
409は「作成されなかった」という意味ではありません。リクエストが変わった(新しいキーが必要な、別の作業です)か、同じアカウントの別の API キーで送られた(元のキーで送り直してください)かのどちらかです。冪等性を参照してください。- 最終的な課金額は、
recordInfoのcostとsettledで確認します。
テキストとストリーミングのリクエストは、この方法では復旧できません
テキストのリクエスト(/api/v1/jobs/stream と、/v1 および /v1beta 配下のテキストエンドポイント)の返答は、生成されたそばから送られ、保存されません。すでに受理されたキーで送り直すと、返答ではなくエラーが返ります。本文が同じなら 400、違えば 409 です。追加の課金はありませんが、受け取れなかった返答を取得することはできません。もう一度返答を得るには、新しいキーでリクエストを送り、その分を支払ってください。どのエンドポイントがヘッダーを読むかを参照してください。
見積額は精算ではありません
estimatedCost は、課金される見込みの金額です。ストリームのテキスト終了マーカーは、バイトが届かなくなったことを示すだけです。どちらも、課金が確定したことの証明にはなりません。タスクの場合は、recordInfo で cost と一緒に settled: true が返っていれば確定です。テキストの呼び出しではタスク ID が返りません。課金を確かめるには、同じ API キーでタスクを一覧表示する(GET /api/v1/jobs)か、コンソール → ログを開き、settled が true になった時点で cost を確定額として扱ってください。
公式ツールでの見積もり
CLI と MCP サーバーは、課金されるすべての呼び出しの前に見積もりを取り、人に確認を求めます。そのため、このステップを自分で作る必要はありません。
- CLI:
spicyapi tasks quoteはリクエストの価格を計算します。spicyapi tasks createはもう一度見積もりを取り、金額を表示して、作成する前に確認を求めます。費用・確認・安全性を参照してください。 - MCP: アシスタントは自由に見積もりを取れますが、タスクを作成するときは、AI クライアントを通じて価格とともにあなたに確認を求めます。費用・確認・安全性を参照してください。
- SDK:
quoteTaskは見積もりを返します。そのquoteIdとestimatedCostをcreateTaskかrunに渡してください。
エージェントがユーザーの代わりに確認してはいけません
確認は、人が判断するためにあります。エージェントが自分で答えたり、クライアントを自動承認に設定したりすると、その経路で支出を止める唯一の歯止めがなくなります。
テキストと動画の互換 API
SpicyAPI は、テキストモデル向けに OpenAI・Anthropic・Google Gemini の形式を、動画向けに OpenAI Videos の形式も受け付けます。エンドポイントの一覧は API リファレンスに、プロトコルごとのリクエスト・ストリーム・エラーはテキストとストリーミングにまとめています。
ベース URL。 OpenAI 形式では https://api.spicyapi.ai/v1 を使います。Anthropic と Google GenAI の SDK は /v1 や /v1beta を自分で付け足すので、これらのベース URL は https://api.spicyapi.ai にします。
認証情報。 どの形式でも 1 つの API キーを使い、Authorization: Bearer ヘッダーに入れて送ります。Anthropic SDK が使う x-api-key ヘッダーと、Google GenAI SDK が使う x-goog-api-key ヘッダーも受け付けます。URL に付けた ?key= は、どの場合も受け付けません。
モデル。 ライブカタログから正確なモデルを選びます。ツール、画像を含むメッセージ、生成オプションが使えるかどうかは、選んだプロトコルではなく、そのモデルのスキーマで決まります。
応答の形。 各プロトコルは、プラットフォーム共通の {code, msg, data, request_id} という外枠ではなく、それぞれ独自の外枠で応答を返します。
推論フィールド
推論テキストを出力するチャットモデルは、message.reasoning_content(ストリーミング時は delta.reasoning_content)に、省略されることもある文字列を返す場合があります。ツール呼び出しのあとで会話を続けるときは、ライブのモデルスキーマが対応していれば、対応するアシスタントメッセージにこの値を残しておけます。
usage.completion_tokens_details.reasoning_tokens は、completion_tokens にすでに含まれている推論部分の量を表します。もう一度足さないでください。推論テキストやこれらのトークン内訳を返さないモデルもあります。
組み込む前に知っておきたい 2 つの形式
- Responses では、会話全体を
inputに入れる必要があります。previous_response_idには対応していません。 - Videos は、
model、prompt、input_reference、seconds、sizeを含む JSON を受け付け、これらをモデル自身のフィールドに対応付けます。返ってくる動画のidはタスク ID でもあり、recordInfoにそのまま渡せます。コンテンツ取得用のエンドポイントは、HTTP302で、有効期間の短い署名付き URL にリダイレクトします。
互換 API は受理時の価格で課金します
quoteId と expectedCost が使えるのは jobs/createTask と jobs/stream だけです。/v1 と /v1beta はリクエストが受理された時点の価格を使い、この 2 つのフィールドを拒否します。そのため、この経路には呼び出しごとの価格確認がありません。ワークフローで課金額の上限を確認しなければならない場合は、ネイティブのタスク API を使ってください。キーが使える金額全体に上限を設けるには、認証の説明に従って、キーの日次・月次・累計の上限を設定してください。
公式の OpenAI・Anthropic・Google クライアントでチャットをストリーミングする例は、公式 SDK を使うを参照してください。CLI と MCP サーバーはネイティブのタスクを送信して追跡するもので、チャットのトークンをストリーミングすることはありません。

