BBramaDocs
Browse documentation

Claude Code (subscription) claude-code

The Anthropic API spoken with a Claude subscription from the shared pool instead of the deployment's API key. Routes are claude-code/<model> over anthropic-messages; who may spend the account is the entitlement decision, and the account itself is a subscription. This page is how we sign in, what the grant looks like, and how a request presents it.

How we sign in

Claude offers no headless path to a subscription credential: the grant comes out of a real OAuth sign-in — the claude.ai login, in a browser, through SSO and a consent screen. On this fleet that browser is Weles's, on Weles's own host, never the operator's: Weles exposes the sign-in as POST /reauth on its worker API, drives its stored sign-in row for the account, and writes the minted grant into the Skarbiec vault at the coordinate provider:claude-code:<subscription>. The proof a sign-in worked is never the login's own exit status — it is the vault bundle standing at a higher revision than before, and a refresh that now answers refreshed.

Four callers drive that sign-in: brama subscription login claude-code --by weles --reason "<why>" on the host Weles runs on (cli), --by hand through a person's own browser and a pasted code (cli), the renewal loop that watches the pool for authentication refusals and signs the mapped account in without a human, and Brama Desktop. A grant can also arrive without any sign-in on this fleet at all: a signed donation through POST /v1/subscription-pool banks a credential minted elsewhere (donation).

The grant on disk

The vault item is the same document the Claude Code CLI writes for itself — one JSON object with a claudeAiOauth block:

{"claudeAiOauth": {
  "accessToken":  "<short-lived bearer>",
  "refreshToken": "<rotating refresh token>",
  "expiresAt":    1756150000000
}}

accessToken is what a request presents; refreshToken is what mints the next one; expiresAt is epoch milliseconds, written back on every refresh from the token endpoint's own expires_in. The gateway reads expiry from the blob's own keys (expiresAt, expires_at, expires, expiry) and, when the blob states none, from the access token's JWT exp claim (src/gateway/oauth_refresh.rs). The item carries the discovery tags (brama:subscription, brama:agent:<agent>, brama:provider:claude-code, brama:id:<id>); the agent tag only records who banked the account. Losing the brama:subscription mark makes the account unroutable, and /readyz reports it under unroutable_accounts.

How a request presents it

At final use the gateway redeems the vault item through the local entitlements router, reduces the document to the access token, and sends it as Authorization: Bearer <accessToken> with anthropic-version: 2023-06-01, in the shape the Claude Agent SDK harness sends on the operator's account: its claude-cli/<version> (external, local-agent, agent-sdk/<sdk version>) user agent, its own anthropic-beta list in its own order, the Stainless client headers that SDK sends in its order (its client deadline header, x-stainless-timeout, included as captured: it states the SDK's own wait, none Brama holds), and a system prompt that opens with the harness's billing attestation (x-anthropic-billing-header: cc_version=<version>.<fingerprint>; cc_entrypoint=local-agent; cch=<checksum>;) and the sentence You are a Claude agent, built on Anthropic's Claude Agent SDK., followed by the caller's own system prompt. The exact release, beta list, header values and fingerprint and checksum parameters are one capture, the CLAUDE_CODE constant in src/providers/adapter/call/credential/claude_code.rs, which names the Claude Code release they were read from, so they change together; this page names their shape, not their values, so it cannot fall behind a release. The checksum is the low twenty bits of xxHash64 over the body it travels in; the fingerprint salts the version with three characters of the first user message. Anthropic honours a subscription grant for its newest models only in this shape: the same grant is answered 429 with the one-word body Error when presented with the OAuth beta header alone, while the harness the grant was taken from is being answered on the same account in the same minute. No copy of the token outlives the request.

Refresh

Once a token expires the gateway posts grant_type=refresh_token with the stored refreshToken and the public client id 9d1c250a-e61b-44d9-88ed-5944d1962f5e to https://claude.ai/v1/oauth/token, as JSON. The answer is read whole. Completion and response handling follow the core request contract. Each brama maintain pass refreshes every active credential whose stated expiry has passed, single-flighted per subscription; a token is used until that instant. Anthropic rotates the refresh token on issue — the moment a new grant is minted, the previous refresh token is invalid — which is why a refreshed grant that cannot be written back to the vault is a failed refresh, and why brama subscription refresh claude-code demands a --reason and journals it. Refreshing costs no plan quota.

When the provider disowns the grant

A refused refresh is definitive only on the provider's own evidence — a body naming invalid_grant, invalid_token, revoked, unauthorized_client, or a 401/403 with no stated reason. That records credential.state: needs_reauthorization with the provider's sentence as cause, blocks the account for 30 minutes, and leaves it alone: the sweep will not resurrect it, the pool lists it burnt, and the one repair is the sign-in above. Everything else is transient and simply waits for the next sweep. The full state machine is in subscription, the repair sequence in the runbook.

Plan usage

Claude publishes a free usage report at https://api.anthropic.com/api/oauth/usage, issued to exactly the OAuth bearer the chat route already presents — reading it costs no quota and provisions nothing new. The ledger records each window with its instant and source (subscription).

Endpoints

Chathttps://api.anthropic.com/v1/messages
Model discoveryhttps://api.anthropic.com/v1/models, widening the pinned rows claude-haiku-4-5, claude-opus-4-6, claude-sonnet-4-6
Token endpointhttps://claude.ai/v1/oauth/token (JSON wire)
Usage reporthttps://api.anthropic.com/api/oauth/usage
Trusted hostapi.anthropic.com
Base URL overrideBRAMA_PROVIDER_CLAUDE_CODE_BASE_URL, validated with the refusals in provider