Skip to content

Account types

All types share one pool, so a request can fail over from an API key to Bedrock.

type Auth Streaming Extra
anthropic_api x-api-key native SSE
bedrock SigV4 binary event-stream, decoded to SSE pip install "tokenbiryani[bedrock]"
vertex bearer token native SSE pip install "tokenbiryani[vertex]"
oauth subscription session native SSE login from the console — see below

Subscription sessions

type: oauth is backed by a Claude subscription session rather than an API key. Add one from the console: Accounts → Add account → Claude subscription. The login is OAuth 2.0 + PKCE and the gateway refreshes the session for you.

It ships disabled: oauth.client_id, oauth.authorize_url and oauth.token_url are empty by default, because Anthropic does not publish the endpoints its first-party clients use and a guess would look like a working feature. docs/oauth.md covers how to fill them in.

Understand the trade before you do. A subscription session sends no anthropic-ratelimit-{requests,input-tokens,output-tokens}-* triples. It sends anthropic-ratelimit-unified-{5h,7d}-utilization instead — a share of a rolling window rather than a remaining count — and the mirror reads those, so such an account keeps failover, prompt-cache affinity and headroom-aware routing. What it loses is everything that needs an absolute token count: binding leases, admission control and the capacity horizon.

observable_limits is forced false for these accounts rather than left to you. It means "no per-window budgets", not "no limits": left true, windows that never populate read as permanently full, and the account would win every routing comparison and starve every API-key account in the pool. Its unified utilisation is read either way.

There is also a terms question, and it is not the same question for one account as for several. docs/oauth.md covers both.

The one place bodies are rewritten

Bedrock and Vertex serve the same Messages API but address the model in the URL and stamp their own anthropic_version. That is exactly two edits, in providers/translate.py, and nowhere else. Everything else the caller sent — including parameters this gateway has never heard of — travels through untouched.

Model mapping

Callers use one model name; each platform has its own ids.

accounts:
  - id: acct-bedrock
    type: bedrock
    cost_tier: 1.2
    options:
      region: us-east-1
      profile: default        # omit for the ambient AWS credential chain
      model_map:
        claude-test-1: anthropic.claude-3-5-sonnet-20241022-v2:0

  - id: acct-vertex
    type: vertex
    options:
      project: my-project
      region: us-central1
      model_map:
        claude-test-1: claude-3-5-sonnet-v2@20241022

Mapping is exact match, then trailing wildcard, then the name as given — which is right when the caller already knows the platform's id.

base_url is an override

Leave it unset and each adapter uses its own default. Setting it globally would point a Bedrock account at api.anthropic.com, which is a mistake the type system cannot catch for you. Set it only for a private endpoint:

    base_url: https://vpce-xxxx.bedrock-runtime.us-east-1.vpce.amazonaws.com

Bedrock streaming

Bedrock frames its stream in AWS event-stream binary, not SSE. The adapter decodes each frame and re-emits the Anthropic event, so the commit boundary and usage accounting keep reading ordinary streaming. Frames split across TCP chunks are handled; that case is tested.