Anthropic /v1/messages

cc-router はローカルマシン上で HTTP プロキシを起動し、Anthropic Messages API(主入口)と OpenAI Responses API(v2.3+ 互換入口)の 2 種類のプロトコル入口を同時に公開します。本ページは Anthropic /v1/messages の完全リファレンスです——Claude Code および Anthropic Messages プロトコルを話す任意のクライアントの推奨入口です。

対応バージョン:cc-router v3.0.0 以上。

待受アドレスとポート

設定項目既定値説明
待受アドレス127.0.0.1設定で「すべてのインターフェースで待受」を有効化すると 0.0.0.0 に切替(UI に赤い警告)
HTTP ポート23456既に使用中の場合は +1 で最大 100 回まで自動探索
HTTPS ポート設定の https_port で制御プロキシモードによって有効化を判断
アドレス/ポートの変更アプリ再起動が必要プロキシはホットリロード非対応

クライアント側の最小構成

export ANTHROPIC_BASE_URL=http://127.0.0.1:23456
# 認証が無効(既定)であれば、この行は省略可
export ANTHROPIC_API_KEY=<cc-router 設定ページで提供される token>

# Claude Code の 3 つのモデルスロットを cc-router の仮想モデルへ向ける
export ANTHROPIC_DEFAULT_OPUS_MODEL=model-opus
export ANTHROPIC_DEFAULT_SONNET_MODEL=model-sonnet
export ANTHROPIC_DEFAULT_HAIKU_MODEL=model-haiku

認証

  • 既定で無効:任意のリクエストがそのまま通過、token 不要。
  • 有効化後、cc-router は以下のいずれかのヘッダから token を読み取ります(どちらか一方でよい):
    • x-api-key: <token>(Claude Code の ANTHROPIC_API_KEY がここに入る、優先
    • Authorization: Bearer <token>(Claude Code の ANTHROPIC_AUTH_TOKEN がここに入る)
  • 抽出した token は設定ページで構成した auth_token完全一致する必要があります。一致しなければ 401 を返します。
  • 許可リスト/v1/models/health、すべての OPTIONS プリフライトは常に通過します。認証有効時でもブロックしません。
    • 設計意図:クライアント起動時の list-models やブラウザでのデバッグを認証で阻害しないため。実際に token クォータを消費する /v1/messages/v1/responses は認証必須です。

ここで cc-router が受け取る token は cc-router 自身のためのもの であり、各上流プロバイダの本物の API Key とは無関係です——本物の Key は cc-router が仮想モデルのディスパッチ規則に従って上流リクエストへ差し替えます。

CORS は既定で有効:Access-Control-Allow-Origin: *、Method 許可 GET / POST / OPTIONS、すべてのヘッダ許可、プリフライトは 204 を返します。401 レスポンスにも CORS ヘッダが付くので、ブラウザの fetch でレスポンスボディを取得できます。


リクエスト

POST /v1/messages
Content-Type: application/json
ヘッダ必須説明
Content-Type: application/jsonはいリクエストボディは JSON 必須
x-api-key または Authorization: Bearer ...認証設定による認証有効時はいずれか必須
anthropic-version / anthropic-beta / …いいえcc-router は消費せず、そのまま上流へ転送

リクエストボディAnthropic Messages API の標準形式に準拠します。cc-router は 2 つのフィールドのみをディスパッチに使用 し、その他のフィールド(messages / system / tools / temperature / max_tokens / thinking / …)はそのまま上流へ透過転送します。

フィールド必須挙動
modelstringはい仮想モデルに解決される。下記マッピング参照。欠落時は 400
streambooleanいいえ(既定 falsetrue で SSE、false で非ストリーミング

cc-router はリクエストボディの model フィールドを書き換えます:

  • model-opus / model-sonnet / model-haiku にヒット → スロットにバインドされた実モデル名(例:glm-4.6qwen3-max)に書き換え
  • fallback にヒット → 書き換えなし、そのまま上流へ透過

非ストリーミングリクエストの例

curl http://127.0.0.1:23456/v1/messages \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "model-sonnet",
    "max_tokens": 256,
    "messages": [
      { "role": "user", "content": "cc-router を一文で説明して" }
    ]
  }' | jq

レスポンス(非ストリーミング)

  • 200 OKContent-Type: application/json
  • ボディは Anthropic 標準の message JSON
  • cc-router は message.model を仮想モデル名に逆書き換えします(fallback は書き換えなし)。クライアント側でキャッシュや統計を仮想モデル単位で集約しやすくするため
  • usage.*cache_creation_input_tokens / cache_read_input_tokens を含む)は透過。cc-router は同時に内部統計用にも抽出します
{
  "id": "msg_xxx",
  "type": "message",
  "role": "assistant",
  "model": "model-sonnet",
  "content": [
    { "type": "text", "text": "..." }
  ],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 42, "output_tokens": 128 }
}

レスポンス(ストリーミング SSE)

  • 200 OKContent-Type: text/event-stream
  • 上流の SSE フレームはほぼ全バイトそのまま透過します。以下 2 種のイベントのみ特別扱い:
イベントcc-router の挙動
message_startJSON をパースし、message.model を仮想モデル名へ書き換え(fallback は書き換えなし)、usage.* を抽出して計上、再シリアライズして送出
message_delta書き換えなしusage.output_tokens などを副次的に抽出して計上するのみ、バイトは透過
その他すべて(content_block_* / message_stop / ping など)バイトそのまま透過

ストリーミングリクエストの例

curl -N http://127.0.0.1:23456/v1/messages \
  -H 'Content-Type: application/json' \
  -d '{
    "model": "model-sonnet",
    "max_tokens": 256,
    "stream": true,
    "messages": [
      { "role": "user", "content": "ping" }
    ]
  }'

-N で curl のバッファを切り、SSE フレームをリアルタイム表示します。

先頭フレーム lookahead:上流が 200 を返したが先頭イベントが実は event: error の場合(典型例:GLM の 1302/1308 でクォータ枯渇が 200 に偽装される)、cc-router はそのフレームをクライアントへ転送せず次のサブスクリプションへ自動リトライします。クライアントから見えるのは「1 回の成功」または「1 回の最終失敗」のみです。

転送中の切断:上流接続が途中で切れた場合、cc-router は既送信フレームの後ろに event: error フレーム + data: [DONE] を追記し、クライアントが永久ハングではなく中断を検知できるようにします。


仮想モデルマッピング

cc-router はリクエストの model フィールドを 1 つの仮想モデルにマップし、その仮想モデルにバインドされたサブスクリプション一覧 + ディスパッチモード(順次 / ラウンドロビン)に従って順に上流を試します。

クライアントが送る modelヒットする仮想モデル
model-opusclaude-opus-4-7gpt-5.5anthropic/model-opusanthropic/claude-opus-4-7openai/gpt-5.5model-opus
model-sonnetclaude-sonnet-4-6gpt-5.4anthropic/model-sonnetanthropic/claude-sonnet-4-6openai/gpt-5.4model-sonnet
model-haikuclaude-haiku-4-5gpt-5.4-minianthropic/model-haikuanthropic/claude-haiku-4-5openai/gpt-5.4-minimodel-haiku
model-fallbackanthropic/model-fallbackFallback(明示)
その他任意の値(カスタムモデル名など)Fallback(暗黙、model はそのまま透過)
  • anthropic/ プレフィックスは LiteLLM 形式のベンダープレフィックス命名との互換性のためにサポートしています。
  • openai/ プレフィックスも同じ思想で、主に OpenAI /v1/responses 入口 のクライアント向けです。
  • gpt-5.5 / gpt-5.4 / gpt-5.4-mini は cc-router が意図的に用意した OpenAI 風のエイリアスで、Opus / Sonnet / Haiku の 3 スロットを再利用します(新しい仮想モデルは追加しません)。

エラーレスポンス

/v1/messages 入口のエラーはすべて Anthropic 形式 に従います:

{
  "type": "error",
  "error": {
    "type": "<kind>",
    "message": "<人間可読メッセージ>"
  }
}

cc-router 自身が生成するエラー:

HTTP Statuskind発生条件
400invalid_request_errorJSON パース失敗 / model フィールド欠落
401authentication_error認証有効時に token 不一致
500api_errorパイプライン内部エラー(全サブスクリプション失敗など)
503overloaded_errorfallback 仮想モデルのサブスクリプション一覧が空
4xx / 5xx上流次第全サブスクリプション失敗時、cc-router は最後の上流の status とエラーボディをそのまま返す

SSE ストリーム内の error フレーム:

  • 先頭イベントが event: error → cc-router が遮断して次のサブスクリプションへ自動リトライ、クライアントには見えない
  • ストリーム途中で現れる error フレーム → そのままクライアントへ透過、kind は固定で upstream_error

未実装の Anthropic エンドポイント

下記の公式 Anthropic エンドポイントは cc-router では未実装で、これは設計上の選択です:

  • POST /v1/messages/count_tokens
  • POST /v1/messages/batches および batches 関連すべて
  • POST /v1/files(Files API)
  • Workbench / Admin API

cc-router は Claude Code 風のリアルタイム対話プロキシ用途に設計されており、Claude Code は POST /v1/messagesGET /v1/models のみに依存するため、その他は実装していません。token 数を見積りたい場合は、クライアント側で tiktoken などのローカルライブラリを使うか、/v1/messages を 1 回叩いてレスポンスの usage.input_tokens を確認してください。

クライアントが OpenAI Responses プロトコル(Codex CLI など)を話すなら、OpenAI /v1/responses 入口 を使ってください。cc-router がリクエストを Anthropic Messages に翻訳し、同じディスパッチ pipeline で処理します。