Skip to content

HTTP エンドポイント

shunt が Claude Code LLM ゲートウェイとして提供するエンドポイント。

Updated View as Markdown
メソッド パス 目的
HEAD / Liveness プローブ
GET / 人間可読なランディング(バージョン + エンドポイント一覧)
GET /health ヘルスチェック — {"status":"ok","version":"x.y.z"}
GET /v1/models Model discovery — あなたの [[models]] エントリを返す
GET /routes shunt ネイティブのルート discovery — 設定された [[routes]] テーブルをそのまま返す(model → provider/upstream_model/effort のマッピング、claude プレフィックスの discovery エイリアスを含む)。/v1/models とは別物で、後者はより狭い Anthropic プロトコルの discovery レスポンス(id、display_name、およびアップストリームのモデルメタデータ)を提供する。[models.router] テーブルを設定した [[models]] エントリが 1 つでもあれば routers 配列が加わり、各ルーターの model id、algorithm(設定された type)、ルーティングしうるすべての targets id を示す。ジャッジを設定したルーターは、尋ねるだけで提供はしない id を judges としても示す(ない場合は省略)。ステージルーターと auto のエントリはさらに、2 つのティアのターゲットと、シグナルが何も決めなかったときに picker が戻るティアも示す
POST /v1/messages 推論 — リクエストの model id に従ってルーティング
POST /v1/messages/count_tokens トークンカウント
GET /managed/settings ゲートウェイ JWT ごとの Claude Code managed settings。ETag、If-None-Match、304 Not Modified に対応
GET /user/bootstrap ゲートウェイ JWT 向けの Claude Desktop bootstrap 構成。ETag、If-None-Match、304 Not Modified をサポート
GET /v1/organizations/spend_limits 保存された支出上限を方向付きカーソルページネーションで一覧表示
POST /v1/organizations/spend_limits 1 つの (scope, period) に対する支出上限を作成または置換
GET /v1/organizations/spend_limits/{id} 保存された支出上限を 1 件取得
DELETE /v1/organizations/spend_limits/{id} 保存された支出上限を 1 件削除
GET /v1/organizations/spend_limits/effective プリンシパル・期間ごとの適用上限と期間累計の支出
POST /v1/metrics 管理された Claude Code クライアントからのインバウンド OTLP/HTTP メトリクス — opt-in したゲートウェイテレメトリー宛先へ verbatim 中継
POST /v1/logs インバウンド OTLP/HTTP log record — logs = true の宛先にのみ中継
POST /v1/traces インバウンド OTLP/HTTP span — traces = true の宛先にのみ中継
GET /admin、/admin/ 管理ダッシュボード — バンドルの他の部分と同じく認証なしで配信される SPA シェルです。GET /admin/api/session が 401 を返すと、バンドル自身が /admin/login へ遷移させます。ワイルドカードのセグメントは空文字列に一致しないため /admin/ はどのルートにも一致せず、マウントルートは 2 つの綴りを両方とも登録しています。--features ui なしでビルドしたバイナリでは、どちらのパスもその機能名を含む本文とともに 404 を返します
GET, POST /admin/login 管理トークンのログインフォームとブラウザーセッションの作成
POST /admin/api/logout ブラウザーセッションの破棄
GET /admin/api/session 管理 SPA がレンダリング前に必要とするセッション固有の値: セッションの csrf トークン、expiry_buffer_ms(claude::auth::EXPIRY_BUFFER のミリ秒値で、setup token が使用不可になる境界)、そして access — このセッションが認証する階層で read または write であり、ダッシュボードはこの値から書き込み操作を出すかどうかを決める。また [server.admin].hide_observed の真偽値である hide_observed も含み、ダッシュボードはこの値から /admin/api/observed をそもそも要求するかどうかを決める。ヘッダー資格情報の呼び出し元は CSRF 免除のため空の csrf を受け取る。このサーフェスには CORS レイヤーがないため、クロスオリジンのページはリクエストを送れても応答を読めない。したがって GET でトークンを返しても安全
GET /admin/api/accounts Claude アカウントストアのメタデータ: 名前、種類、有効期限、UUID。トークン本体は決して返さない
GET /admin/api/accounts/codex Codex アカウントストアのメタデータ: 名前、有効期限、ChatGPT アカウント ID。トークン本体は決して返さない
GET /admin/api/accounts/antigravity Antigravity アカウントストアのメタデータ: 名前、有効期限、メールアドレス(Google が返した場合)。トークン本体は決して返さない
GET /admin/api/accounts/xai xAI アカウントストアのメタデータ: 名前、xAI ユーザー ID。トークン本体は決して返さない
GET /admin/api/observed ローカルの Claude Code、Codex、Gemini、Kimi、Grok、Cursor のアイデンティティとプロバイダー固有の使用量を読み取り専用で返す。トークン本体は決して返さず、元の認証情報をリフレッシュすることもない。[server.admin].hide_observed が true の場合は、これらのソースを一切読まずに { "accounts": [] } を返す
GET /admin/api/pool claude_oauth / chatgpt_oauth / kimi_oauth / xai_oauth / antigravity_oauth provider ごとのプール状態。各 account オブジェクトには任意の plan 文字列が含まれることがあり、ファイルから読んだ値は後の profile 照会でより精密な値に補正されることがあり、Codex の行には報告された 5h/7d 使用量が含まれる(7d_oi に対応する Codex の項目はない)。各 account には真偽値 needs_relogin も含まれる。クレデンシャルが終端的に拒否された(invalid_grant)か、リフレッシュトークンをそもそも持たないか、ローテーションされたトークン対を保存できずに失った場合で、どのリトライでも回復せず、オペレーターの再ログインだけが解決策となる。クールダウンのフィールドとは独立に報告される — クールダウンは自然に失効するが、この印は残る — ダッシュボードの二つの表はいずれもクォータ一時停止の cooling ではなく needs re-login と表示する。メモリ上のみで保持されるため、再起動でクリアされ、そのアカウントの次の終端的な失敗で再び立つ。どの provider テーブルも一度も選択したことのないアカウントについても — has_state: false と並んで — 報告される。admin の refresh プローブが判定をストア名で記録するためである。各 account には真偽値 paused も含まれる。これはオペレーターが shunt.toml に触れずに切り替えられるランタイム限定の除外フラグである(下の PATCH .../accounts/{account_ref} を参照)。レスポンス最上位の sort_by_reset は [server.pool] sort_by_reset またはそのランタイムオーバーライドを反映し(下のボディなしの PATCH を参照)、provider ごとではなくプロセス全体に適用される。 各 account には不透明な account_ref も含まれ、provider ごとのプール識別子から導出される。ミューテーションは表示名 name ではなくこの値を使うため、同名の別アカウントも安全に個別操作できる。各 account には真偽値 credential_override も含まれる。プールのエントリが明示的な credentials ファイルまたは token_env を指定し、アカウント名と同じストアファイルを読まない場合に true となる。credential_override が true の xai_oauth 行は、ダッシュボードがストアの同名ログインと照合しないため、別ユーザーの Grok CLI の観測がその行に統合されない。各 account には、このプロセスの起動以降のリクエストカウンターも含まれる: requests_attempted は shunt がその account へ送ったプロキシリクエストの数(トークンのリフレッシュやスロットルの待機の後に同じ account へ再送したものも改めて数える。使用量のポーリング、モデルの探索、カタログの照会、トークンのリフレッシュは数えない)で、常に次の三つの合計に等しい: requests_succeeded は 2xx で応答されたもの、requests_failed はそれ以外のステータスで応答されたもの、またはレスポンスヘッダーの到着前に失敗したもの(トランスポートエラーまたは初回バイトまでのタイムアウト)、requests_cancelled はクライアントの切断や期限によって結果が出る前に打ち切られたもの。mean_latency_ms はヘッダーを受け取ったリクエストについての送信からレスポンスヘッダーまでの平均時間で、まだ一つもなければ null。Codex WebSocket トランスポート経由のリクエストは、成功か失敗かを問わず数えない。WebSocket の試行が失敗した後の HTTP フォールバックは数える。同じアカウント識別子に解決される行は、一組のカウンターを共有する。カウンターは設定のリロードをまたいで保持され、再起動でリセットされ、admin API で account を削除すると消える。各アカウントは解決済みのハードキャップ max_utilization_5h、max_utilization_7d、max_utilization_fable も [0.0, 1.0] の割合で持つ(アカウントのウィンドウ → アカウント → プールのウィンドウ → プールのデフォルトの順に解決し、そのウィンドウに適用されるキャップがなければ null)。has_state が false でも設定から報告され、ダッシュボードは使用量バーとプール表に表示する。max_utilization_fable は Fable 専用の 7d_oi ウィンドウにのみ適用されるため、Fable モデルへのリクエストにのみ影響する。chatgpt_oauth アカウントには 7d_oi ウィンドウがないため常に null で、antigravity_oauth アカウントはクォータがキャップに反映されないため 3 つとも null になる。
PATCH /admin/api/pool/{provider}/accounts/{account_ref} write 権限限定。ボディ {"paused": true|false} で指定したアカウントのランタイム一時停止を切り替える。disabled と同様に選択から除外されるが、メモリ上のみで(再起動でクリアされる)、shunt.toml とは独立している。不明な provider または account には 404 {account_ref} は GET /admin/api/pool の対応する account オブジェクトから取得する。表示名はミューテーションの対象指定には使わない。
PATCH /admin/api/pool write 権限限定。ボディ {"sort_by_reset": true|false} でプール全体のリセット優先ソートをランタイムに切り替える([server.pool] は provider ごとではなくプロセス全体であるため)。利用可能なアカウントはバーンレートのヘッドルームではなくクォータのリセットが最も早い順に並ぶ。{"sort_by_reset": null} は以前に設定したオーバーライドを明示的に解除し、設定ファイル自身の値に戻す(フィールドの省略は何もしない — 解除ではない)。オーバーライドはメモリ上のみで、再起動でも戻る。[server.pool] 自体が存在しない場合 — そのレガシー選択パスはこの値を一切参照しないため — オーバーライドの有無にかかわらず効果はなく、GET /admin/api/pool も sort_by_reset: false を報告する
GET /admin/api/routes 管理者資格情報で保護された解決済みのルーティング表で、ダッシュボードから利用できます — 上の GET /routes が返すものと同じボディで、同じスナップショットから構築されるため、運用者が見る表とクライアントが実際に解決する表が食い違うことはありません。リダイレクトではなく個別に登録しているのは、管理面が自前の認証を保つためです。公開の /routes は意図的に認証を持たないので、こちらをそちらへ向けると両者の認証が結び付いてしまいます。ここで管理者資格情報を要求するため、/routes を開放していても当該資格情報が守る範囲は広がりません
POST /admin/api/accounts/claude {name, mode} で Claude のブラウザープロビジョニングを開始。mode は oauth または setup_token で、省略時は setup_token。{authorize_url} を返す
POST /admin/api/accounts/claude/{name}/complete <code>#<state> を含む {code} で Claude プロビジョニングを完了。アカウントを保存し、有効(live)かどうかを報告
POST /admin/api/accounts/claude/{name}/refresh imported な Claude アカウントの refresh グラントをその場で実行し、ログインがまだ生きているかを報告。プロバイダのトークンエンドポイントを叩くためレート制限があり、必ず共有クレデンシャルストア経由なのでプロキシ側のリフレッシュと競合しない。新しい expires_at のみを返し、トークン本体は一切返さない。あわせて、プローブ自身のクリア後にプールから読み直した needs_relogin を返す — プールがなお死んでいると見なすアカウントでもグラント自体は成功しうるため、/admin/api/pool と矛盾する回復を主張せずそのまま報告する。setup_token アカウント(refresh グラントを持たない)やあらゆる終端判定には 400、一時的な失敗には 502
DELETE /admin/api/accounts/claude/{name} 指定した Claude アカウントのストアファイルを削除
POST /admin/api/accounts/codex {name} で ChatGPT OAuth を開始し、{authorize_url} を返す
POST /admin/api/accounts/codex/{name}/complete localhost の redirect URL 全体または <code>#<state> を含む {code} で Codex プロビジョニングを完了
DELETE /admin/api/accounts/codex/{name} 指定した Codex アカウントのストアファイルを削除
POST /admin/api/accounts/antigravity {name} で Antigravity OAuth を開始し、{authorize_url} を返す
POST /admin/api/accounts/antigravity/{name}/complete localhost の redirect URL 全体または <code>#<state> を含む {code} で Antigravity プロビジョニングを完了
POST /admin/api/accounts/antigravity/{name}/refresh Antigravity アカウントの refresh グラントをその場で実行し、ログインがまだ生きているかを報告。上記 Claude の refresh ルートと同じプローブ
DELETE /admin/api/accounts/antigravity/{name} 指定した Antigravity アカウントのストアファイルを削除
GET /admin/assets/{*path} 埋め込まれた管理 SPA バンドルのファイル。拡張子に応じた Content-Type と X-Content-Type-Options: nosniff を付けて返します。--features ui でビルドしたバイナリにのみ存在
GET /admin/{*path} /admin マウント配下でどのルートにも一致しないパスに対する SPA シェル。クライアント側のディープリンクがリロード後も維持されます。--features ui でビルドしたバイナリにのみ存在
GET, POST /backend-api/codex/responses Inbound Codex CLI パススルー — 実際の ChatGPT バックエンドパスをミラー
GET, POST /responses Inbound Codex CLI パススルー — bare base_url 形式
GET, POST /v1/responses Inbound Codex CLI パススルー — /v1 サフィックスの base_url 形式
POST /backend-api/codex/alpha/search Codex CLI Web 検索(web.run)の中継 — ChatGPT 形式のベースパス
POST /alpha/search Codex CLI Web 検索の中継 — bare base_url 形式
POST /v1/alpha/search Codex CLI Web 検索の中継 — /v1 サフィックスの base_url 形式
GET /models Codex CLI モデルカタログのフォールバック — {"models":[]} を返す
GET /backend-api/codex/models Codex CLI モデルカタログのフォールバック — ChatGPT 形式のベースパス
POST /backend-api/codex/analytics-events/events Codex CLI analytics sink — 受理して破棄し、サニタイズ済みイベント名のカウンターのみ記録
POST /codex/analytics-events/events Codex CLI analytics sink — ルート形式の chatgpt_base_url
GET /usage クライアント向けのサニタイズ済みプール使用量 — 共有アカウントプールのウィンドウごとの残り余裕とリセットに加え、プールされるプロバイダーごとの同じ集計。アカウントの身元や容量は返さない

/admin* ルートは [server.admin] が設定されている場合にのみ存在します。そのテーブルがなければ、いずれも登録されません。管理認証情報は設定されたヘッダーまたは x-api-key で受け付け、read_keys の認証情報は上記のすべての GET を通過しますが、すべての変更操作では 403 で拒否されます。サインインは可能です: POST /admin/login はこれを受け入れて read 階層のセッションを発行し、そのセッションの変更操作も同じ 403 で拒否されます。 このログイン POST には same-origin ガードがあります: クロスサイトのフォーム送信は認証情報を検査する前に 403 で拒否されるため、どの認証情報の保持者も、サインイン済みの運用者のセッション Cookie を自分のものへ差し替えることはできません。スクリプトからのログインは影響を受けません — Sec-Fetch-Site と Origin のどちらも無い場合、このチェックは通過します。ただし SPA シェルとバンドルファイルは例外で、GET /admin(2 つの綴りとも)、GET /admin/{*path}、GET /admin/assets/{*path} は管理認証なしで配信されます。これらは運用者のデータを含まず、SPA が読み取る値はすべて、リクエストごとに認証する /admin/api/* の背後にあるため安全です。ワイルドカードの 2 つのルートは、[server.admin] が設定され、かつ --features ui でビルドしたバイナリでのみ存在します。GET /admin/api/observed は、ゲートウェイホスト上のサポート対象の Claude Code、Codex CLI、Gemini CLI、Kimi Code、Grok CLI、Cursor.app の認証情報を自動検出します。これらのソースをリフレッシュしたり書き込んだりすることはありません。その検出を省くには [server.admin].hide_observed を設定します: ルートは引き続き認証したうえで { "accounts": [] } を返し、GET /admin/api/session は hide_observed: true を報告し、ダッシュボードはそのリクエストを省いて管理対象のプールアカウントのみを一覧表示します。

管理 SPA バンドル(--features ui)

/admin/assets/{*path} と /admin/{*path} の SPA フォールバックは、 --features ui でビルドしたバイナリにのみ存在します。このビルドは ui/ パッケージから生成したバンドルをバイナリに埋め込みます。既定の cargo build は Node ツールチェーンを必要とせず、バンドルも持たず、どちらのルートも登録しません。 配布されているリリースバイナリはこの機能を有効にしてビルドされています。

フォールバックは /admin マウント配下に限定されます。

  • /admin/ 配下でどのルートにも一致しないパスは、200 と text/html で SPA シェルを返すため、クライアント側のディープリンクがリロード後も維持されます。
  • /admin/api/ 配下で一致しないパスは、Anthropic のエラー形状で 404 を返します。 この名前空間は UI ではなく JSON であり、HTML を返すとクライアントのエラー処理が 壊れるためです。
  • マウントの外側のパスは影響を受けず、これまでどおり 404 を返します。

GET /admin もシェルで、GET /admin/ も同様です。ワイルドカードのセグメントは空文字列に一致しないため、/admin/ は完全一致のルートにもフォールバックにも一致せず、ダッシュボード自身のルートで本文のない 404 を返してしまいます。そのため、マウントルートは 2 つの綴りをそれぞれ登録しています。

この 2 つは、両方のビルドに登録されていながら応答が機能フラグ次第で変わる管理パスで、有効ならシェル、無効なら本文に --features ui を挙げた 404 を返します。どちらでも登録しておくのは、その 404 にこの案内文を持たせるためです — ルートごと外すと axum の本文なし 404 になり、運用者は [server.admin] 未設定と見分けられません。

管理パスの移行

破壊的変更です。 すべての管理 JSON ルートと変更系ルートが /admin/* から /admin/api/* へ 移動しました。古いパスはエイリアスを残さず削除され、どのリクエストも admin ハンドラーには 到達しなくなりました。

古いパスで何が返るかはビルドによって異なるため、そこでの 200 を成功と見なさないでください:

  • デフォルトビルド — パスがどこにも登録されておらず、404 を返します。
  • --features ui(ビルド済みリリースバイナリはこちら)— GET はマウント配下の他のディープ リンクと同様に /admin/{*path} の SPA フォールバックへ落ち、200 text/html のシェルを返します。 HEAD も同じです。それ以外のメソッドは Allow: GET,HEAD を伴う 405 を返します — フォールバックが any ではなく get で登録されているためです。

そのため古い GET URL のままのスクリプトは、移行を示すシグナルではなく HTML を受け取ります。 /admin/api/* へ移してください。レスポンスの Content-Type が確実な判別基準です。

/admin はダッシュボードのシェルとして残り、/admin/login と /admin/oidc/callback もそのままです — これらは API ルートではなく、サーバー側でレンダリングされるページだからです。それ以外はすべて 移動しました。ダッシュボードが /admin/* をブラウズ可能なディープリンクとして使えるようにするため です。一つのパスが JSON エンドポイントであると同時にクライアント側のルートであることはできないため、 互換用のエイリアスは残していません。

スクリプトから呼び出している箇所は、機械的に一度だけ書き換えてください。パスは /admin の後ろに /api セグメントが一つ増えるだけです:

変更前 変更後
GET /admin/accounts GET /admin/api/accounts
GET /admin/accounts/codex GET /admin/api/accounts/codex
GET /admin/observed GET /admin/api/observed
GET /admin/pool GET /admin/api/pool
GET /admin/status GET /admin/api/status
POST /admin/accounts/claude POST /admin/api/accounts/claude
POST /admin/accounts/claude/{name}/complete POST /admin/api/accounts/claude/{name}/complete
POST /admin/accounts/claude/{name}/refresh POST /admin/api/accounts/claude/{name}/refresh
DELETE /admin/accounts/claude/{name} DELETE /admin/api/accounts/claude/{name}
POST /admin/accounts/codex POST /admin/api/accounts/codex
POST /admin/accounts/codex/{name}/complete POST /admin/api/accounts/codex/{name}/complete
DELETE /admin/accounts/codex/{name} DELETE /admin/api/accounts/codex/{name}
POST /admin/oidc/start POST /admin/api/oidc/start
POST /admin/logout POST /admin/api/logout

認証は変わりません。同じ管理認証情報を同じヘッダーまたは x-api-key で送り、読み取り/書き込みの等級も同じです。

spend-limit ルートは、起動時に [server.spend] が設定されていた場合にのみ存在します。[server.admin] の認証情報で認証するため、[server.gateway] とは無関係です。その認証情報は設定された管理ヘッダー(デフォルトは x-shunt-admin-token)または x-api-key で送信します — どちらのスロットも受け付けます。write の認証情報(write_keys エントリー、または tokens_env/tokens_file のペア)はすべての操作を使用でき、read_keys の認証情報は GET のみ使用でき、変更操作では 403 を受け取ります。POST は user と organization の scope、daily/weekly/monthly の period、user scope では 1~256 バイトの user_id、1~19 桁の USD セント非負整数文字列または null の amount を受け付け、(scope, period) 単位で upsert します。一覧では limit(1~1000、デフォルト 20)、after_id、before_id、scope_type を使用でき、2 つのカーソルは同時に指定できません。すべてのレスポンスに request-id が含まれ、エラーは Anthropic のエラー形式です。上限と変更監査レコードは、設定したバージョン付き JSON 状態ファイルに一緒に保存され、各変更は admin-key:<id> または admin-token:<name> に帰属します — 両方のスロットが同じティアの異なる認証情報を保持している場合は、設定された管理ヘッダー側が帰属先になります。GET /v1/organizations/spend_limits/effective(read または write 認証情報)は、プリンシパルと期間ごとに 1 行、適用される上限(amount、source、spend_limit_id)と米国セント単位の period_to_date_spend を返します。limit(1–1000、デフォルト 20、プリンシパル数で計数)、period[]、user_ids[](最大 100 件、ページネーションなし)、q、sort=spend_desc(period[] がちょうど 1 つのとき)、page を受け付け、不正な入力には 400 invalid_request_error を返します。period_to_date_spend はメーターが読み取れたカウンターだけを反映します。保存されたカウンターレコードの復元に失敗したプリンシパルは、unavailable フラグが解除されるまで支出が 0 または一部だけに見えることがあり、ログの復元警告にそのプリンシパルが記録されます。上限は /v1/messages と、受信 Codex エンドポイントの Responses ルートおよび /alpha/search エイリアスに適用されます(上限を超えた Codex ターンは 429 usage_limit_reached を受けます。受信 Codex エンドポイントを参照)。passthrough または type = "noop" ルートのみのチェーンには適用されません。/audit は公開されません。

/user/bootstrap ルートは、起動時に [server.gateway] が有効だった場合にのみ存在し、有効なゲートウェイ bearer JWT を要求します。static な [server.auth] トークンでは認証できません。[server.gateway.desktop_bootstrap] のテンプレートを application/json で返し、文字列値の中の ${user.email}、${user.sub}、${user.name} は置換されます。エラーと 304 を含むすべてのレスポンスに Cache-Control: no-store が付き、ルートはリダイレクトしません。

ステータス エラータイプ 意味
200 なし テンプレート本文と、引用符付きの ETag("sha256:<body-hash>")
304 なし If-None-Match が現在の ETag に一致。本文は空
401 authentication_error ゲートウェイ bearer がない、無効、または期限切れ
403 permission_error bearer は有効だが、[[server.gateway.policies]] の対象ではない
404 not_found_error desktop_bootstrap が未設定
500 api_error テンプレートが読み取れなくなった、または JSON オブジェクトではなくなった

policy がなければサインイン済みの全ユーザーが対象で、policy があれば、policy の match.emails に含まれるか、catch-all policy(match なし)がある場合に対象になります。デバイスコードのエンドポイントは、client_id のないリクエスト(Claude Desktop は送りません)と client_id=claude-code のリクエストを受け付け、それ以外の値は拒否します。client_id のないリクエストで拒否された refresh トークンは 400 {"error":"invalid_grant"} を返し、claude-code のリクエストは 401 のままです。Claude Desktop の接続を参照してください。

GET /managed/settings と POST /v1/{metrics,logs,traces} のテレメトリー受信ルートは、起動時に [server.gateway] が有効だった場合にのみ存在し、どちらも同じゲートウェイのベアラー JWT を要求します。受信ルートは、管理された Claude Code クライアントが export する OTLP/HTTP ペイロードを受け取り([server.gateway.telemetry] がそれらの exporter をゲートウェイへ向けます)、リクエストのバイト列をその signal に opt-in したすべての宛先へそのまま中継します。インバウンドの content-type と content-encoding は保持され、宛先に設定された headers がその上に適用されます(設定されたキーは転送値を置き換え、ヘッダーを重複させません)。クライアントの Authorization ヘッダーが転送されることはなく、中継はリダイレクトに従いません。宛先は signal ごとに opt-in し(metrics はデフォルト on、logs/traces は off)、どの宛先も opt-in していない signal は受理後に破棄されます。中継はデタッチされているため、宛先の状態にかかわらずレスポンスは常に即座の 200 で、成功ボディは OTLP/HTTP に従いリクエストのプロトコルをミラーします(application/json には {}、それ以外には空の application/x-protobuf ボディ)。32 MiB の受信上限を超えるボディは 413 を返します。

Inbound Codex Responses、Web 検索、モデルカタログ、analytics のルートは [server.codex_endpoint] が設定されている場合にのみ存在します。Responses ルートは OpenAI Responses のリクエストとレスポンスを HTTP/SSE(POST)または WebSocket アップグレード(GET)でそのまま中継し、[[server.codex_endpoint.routes]] によってモデルごとに別の Responses 互換アップストリームへルーティングすることもできます。Codex 専用の 2 つのモデルパスは {"models":[]} を返し、共有の /v1/models はクエリに client_version がある場合だけその形式を返し、それ以外では Anthropic 契約を保ちます。すべてのカタログ変形は通常のモデル検出認証ゲートを使います。2 つの analytics ルートは同じ inbound auth ポリシーを適用し、クライアント payload を転送または保持せず、認証後は不正な JSON やサイズ超過の body にも 200 {} を返します。サニタイズ済みイベント名だけを shunt.codex_client_events に記録し、metric sink がなければ純粋な破棄 sink として動作します。3 つの Web 検索パスは、Codex CLI の組み込み Web 検索を Responses パスと同じアカウントプールと inbound auth ポリシーでバックエンドの /codex/alpha/search へそのまま中継します。POST のみを受け付け、[[server.codex_endpoint.routes]] のエントリには従いません。

/usage ルートは [server.usage] を設定した場合にのみ存在し、同じく [server.auth] または [server.gateway] の設定を必要とします。GET /v1/messages と同じクライアントトークン、または Authorization: Bearer で送られたゲートウェイログインのアクセストークン(shunt gateway claude で起動したセッションが送るもの)で認証します。有効なゲートウェイログインは [server.auth] を参照せずに受け付けるため、[[server.auth.jwt]] の鍵セットに到達できなくても締め出されません。共有アカウントプールのウィンドウごとの残り余裕(そのウィンドウを報告した無効化されていないアカウントの mean(clamp(cap - utilization, 0, 1))。cap はそのウィンドウについてのアカウントの解決済み max_utilization ハードキャップで、該当するものがなければ 1.0、つまりキャップによってアカウントが除外されるまでにプール全体の容量のうちまだ使える割合。キャップがそのウィンドウのリクエストからすでに除外しているアカウントは 0 として数えられ、5h または 7d のキャップは Fable リクエストからもそのアカウントを除外します)、それらのアカウントが報告した最も早いリセット時刻(キャップで 0 として数えられているアカウントは、そのキャップが解除される時刻を含む)、ok/degraded/exhausted/capped ステータスを返します。アカウントの身元、件数、優先度、disabled、しきい値、アカウント単位の数値は公開しません。無効化されていないアカウントがそのウィンドウを報告していない場合だけ null になります。Codex の x-codex-* レスポンスヘッダーとオプションの wham/usage ポーリングは、5 時間と共有週次ウィンドウを埋めます。WebSocket トランスポートでは、ストリーム内の codex.rate_limits イベントが再利用接続を含むすべてのターンで同じウィンドウを埋めます。Codex には Fable スコープ(7d_oi)のシグナルがありませんが、混在プロバイダーのプールでは別のプロバイダーが集約 Fable 値を提供できます。pool はプールされるすべてのプロバイダーを通じた集計で、providers は同じサニタイズ済み集計をプールされるプロバイダーごとに、設定されたプロバイダー名をキーとして持ちます。そのため特定のプロバイダーにルーティングするクライアントは、プール全体の平均ではなく、そのプロバイダーの余裕とステータスを読み取れます。プールされない認証モードのプロバイダーは省略されます。完全なレスポンス形は英語版エンドポイントリファレンスを参照してください。 Claude Code のクライアントであれば curl なしで読めます。このリポジトリのプラグインマーケットプレイスにある shunt モッド が /shunt:usage をこのエンドポイントから答え、ウィンドウごとの余裕とリセット時刻を表示します。関数フック(CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1)が必要で、まだアーリーアクセスです。

プール状態 capped は、利用可能なアカウントがなく、有効(disabled でない)かつ一時停止されていないアカウントのうち 1 つ以上が max_utilization* のハードキャップで除外されていることを意味し([server.pool] を参照)、exhausted とは区別されます。

GET / と GET /health は、[server.auth] が有効なときも開いたままです(ヘルスチェックツールは通常トークンを付けられません)。機密情報は何も公開しません — ステータス、バージョン、およびすでに公開されているエンドポイント一覧のみです。 [[server.auth.jwt]] エントリを設定すると、Authorization: Bearer の検証済み外部 JWT がクライアントトークンと同じゲート対象ルートを認証します。どのエントリでも検証できなかったトークンは 401、検証できたエントリがなく、トークンの issuer に一致するエントリのうちキャッシュ済みの key set がなく取得にも失敗したものがある場合は 503 です。

ゲートウェイプロトコル

shunt は公式の Claude Code LLM ゲートウェイプロトコルを実装します: 正しいヘッダーとボディフィールドの転送、機能のパススルー、システムプロンプトのアトリビューション処理。ゲートウェイ所有のエラーは Anthropic のエラー形で返され、上流のコンテキストオーバーフローエラーは Anthropic の prompt is too long の文言へ書き換えられて Claude Code のコンパクト&リトライが発火し、ストリーミングレスポンスはバッファリングなしで中継されます(オプションでキープアライブ ping 付き)。

Navigation

Type to search…

↑↓ navigate↵ selectEsc close