GET /protocol, covering that gateway’s sign-in, inference, managed settings, model discovery, and telemetry endpoints. It is a separate document from this guide.
- To roll out an existing or third-party gateway for your organization, see Roll out an LLM gateway
- If you’re an individual developer authenticating Claude Code to a gateway with a credential you were given, see Connect Claude Code to an LLM gateway
- API formats and the endpoints to serve for each
- Client behavior by connection method: how model IDs,
anthropic-betavalues, request fields, and defaults differ between the formats and a Claude apps gateway sign-in - Request headers: which must reach the upstream and which your gateway can consume
- Response headers: what to return so stall detection, retries, and usage limit display work
- The system prompt attribution block and how it interacts with prompt caching
- Feature pass-through: what breaks when headers or body fields are stripped
- Model discovery
- Forward unchanged: pass it to the upstream byte-for-byte
- Consume: the gateway may read it for routing, attribution, or tracing and need not forward it
API formats
A gateway must expose at least one of the following API formats to Claude Code clients. A client picks a format and points Claude Code at your gateway with the variables in the Selected by column of the table below. Google Cloud’s Agent Platform is Google Cloud’s Claude endpoint, formerly Vertex AI; its variable names keep theVERTEX spelling.
Foundry and Claude Platform on AWS
Microsoft Foundry and the Claude Platform on AWS implement the Anthropic Messages format. Claude Code routes to them through their own variables,ANTHROPIC_FOUNDRY_BASE_URL and ANTHROPIC_AWS_BASE_URL, but a gateway fronting either implements the Anthropic Messages row above. A gateway fronting the Claude Platform on AWS must also forward the anthropic-workspace-id header, which that platform requires on every request.
Optional endpoints and startup traffic
Token-counting endpoints are the only optional ones: when they’re absent, Claude Code falls back to a character-based estimate of context usage. Match on the path, not the full URL:- Inference requests post to
/v1/messages?beta=true - The Google Cloud’s Agent Platform method suffixes attach to the publisher model path, as in
/projects/{project}/locations/{location}/publishers/anthropic/models/{model}:streamRawPredict
HEAD /api/hello connection-warming probe, which Claude Code skips when an HTTP proxy or client certificate is configured. An Amazon Bedrock-format gateway receives a GET /inference-profiles?type=SYSTEM_DEFINED request and, when the configured model is an inference profile, GET /inference-profiles/{profile} lookups.
Sessions that go through a gateway aren’t eligible for the HIPAA configuration. Check how developers sign in and connect lists which sign-in and connection methods are. See The HIPAA configuration behind a gateway.
The fast mode availability check never appears in gateway logs: it calls api.anthropic.com directly rather than following ANTHROPIC_BASE_URL, so on a network that blocks direct egress to api.anthropic.com, fast mode can report a connectivity error while inference through the gateway keeps working. The WebFetch domain safety check also calls api.anthropic.com directly. Use fast mode behind proxies and LLM gateways covers the variables that restore it.
Streaming
Claude Code reads each streaming inference response event by event as it arrives, so the way your gateway relays the stream affects what the user sees:- If your gateway buffers a response until it is complete, Claude Code stalls.
- Claude Code expects each response’s full event sequence, in order, through the final
message_deltaandmessage_stopevents. If the body ends cleanly after a content block has started but before that finalmessage_delta, Claude Code treats the response as a dropped connection. The response above may be incomplete describes what the user sees then, and Automatic retries says when Claude Code re-issues the request instead. - When an Amazon Bedrock guardrail blocks a reply, the events Bedrock sends can reference a content block whose
content_block_stopalready arrived, and Claude Code relies on receiving them as sent. AWS Guardrails describes how that reply ends. - Claude Code aborts a streaming response once no bytes reach it for longer than its streaming idle timeout. During a long thinking pause, the upstream’s SSE
pingevents can be the only bytes on the stream, so a gateway that strips or buffers them can trip that timeout partway through a response. A gateway that translates from an upstream without pings, such as Amazon Bedrock’s binary event stream, has the same gap unless it emits its ownpingevents. - On the Amazon Bedrock InvokeModel format, Claude Code reads the
/model/{model}/invoke-with-response-streamresponse as the binaryapplication/vnd.amazon.eventstreambody Bedrock returns, and can’t parse it once a gateway converts it to server-sent events or rewrites thatContent-Typeheader. Streaming errors behind a gateway or proxy describes what the user sees then.
Format mismatch with the upstream
Which format the client speaks determines what your gateway receives. The common failure mode is a mismatch between the format the client sends to your gateway and the format the upstream provider behind it accepts.- When the client speaks the Amazon Bedrock or Google Cloud’s Agent Platform format, Claude Code sends only the subset of its full capability set that those providers accept
- When the client speaks the Anthropic Messages format, Claude Code sends the full set, even if your gateway forwards to an Amazon Bedrock or Google Cloud’s Agent Platform upstream
How the connection method changes client behavior
The way a developer connects to your gateway determines which model IDs,anthropic-beta values, and request fields Claude Code sends, and which defaults it applies. Your gateway sees one of three client behaviors:
- Amazon Bedrock or Agent Platform format: the developer sets
CLAUDE_CODE_USE_BEDROCK=1withANTHROPIC_BEDROCK_BASE_URL, orCLAUDE_CODE_USE_VERTEX=1withANTHROPIC_VERTEX_BASE_URL, pointing at your gateway. Claude Code uses that provider’s model IDs, request fields, and defaults. - Anthropic Messages format: the developer sets
ANTHROPIC_BASE_URLto your gateway. Claude Code treats the gateway as the Claude API and can’t tell which upstream you forward to. - Claude apps gateway sign-in: the developer signs in to a Claude apps gateway. That gateway speaks the Anthropic Messages format but can route to any upstream, so Claude Code sends only the
anthropic-betavalues and model-capability assumptions that Amazon Bedrock and Agent Platform also accept.
Requests and defaults by connection method
The table below compares the three connection methods, one behavior per row. It leaves out Microsoft Foundry and Claude Platform on AWS, which also use the Anthropic Messages format but which Claude Code reaches through their own variables. For those, see the Microsoft Foundry and Claude Platform on AWS pages.
For the features each connection supports and the telemetry it sends to Anthropic by default, see Feature availability and Default behaviors by API provider.
Settings for unrecognized model IDs
Two client-side settings change what Claude Code assumes for a model ID it doesn’t recognize, whichever connection method the developer uses:- Context window: Claude Code assumes 200K, or 1M when the ID carries
[1m]. To declare the real window, see Correct the window for a gateway or custom model ID - Capabilities: to give a gateway alias the capabilities of the model behind it, map that model’s Anthropic ID to your alias with a
modelOverridesentry in the settings you distribute. For where theANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIESvariables apply, see feature pass-through
Request headers
Claude Code includes these headers on API requests. Header names are case-insensitive on the wire. Forwardanthropic-version and anthropic-beta unchanged, plus anthropic-workspace-id when the upstream is the Claude Platform on AWS; the rest the gateway may consume for routing, attribution, and tracing, and need not forward.
Subagent IDs are generated fresh each time Claude Code spawns a subagent. Teammate agents, the named members of an agent team, reuse a stable name-based ID across reconnections. In both cases the ID identifies an agent, not a person or a device, so don’t treat the agent ID header as a user identifier.
If your developers set
ANTHROPIC_CUSTOM_HEADERS, those headers appear on requests as well.
Gateway hint headers
Claude Code can also send routing hints: per-request facts a gateway or router can use to schedule, cache, or attribute a request. Requires Claude Code v2.1.273 or later. Whether a request carries them depends on where Claude Code sends it:- Direct connection to the Anthropic API: sent by default
- Custom base URL: off by default, because a proxy that rejects unknown headers would fail the request. To receive them, set
CLAUDE_CODE_GATEWAY_HINT_HEADERS=1for your developers, for example in theenvblock of managed settings - Any other backend, including Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, and Claude Platform on AWS: sent only when
CLAUDE_CODE_GATEWAY_HINT_HEADERS=1is set
CLAUDE_CODE_GATEWAY_HINT_HEADERS to 0 stops the headers on every connection.
The headers carry only what the rows below list: fixed vocabularies, tool names, durations, and a random prompt identifier, never prompt text or file contents. Every value is printable ASCII.
Before parsing
x-claude-code-prev-tool-durations, check how Claude Code builds the value and what it leaves out:
- Entries: one per tool call that ran, in the order its result was collected, in whole milliseconds
- Cap: Claude Code sends at most 32 entries and 4 KB, keeping the first entries
- Encoding: tool names are percent-encoded, covering
%,;,=, comma, space, and any character outside printable ASCII - Parsing: split on
;, then on=, and decode each name - Absence: compaction calls, side requests, and the first request of a new prompt never carry it. Don’t read a missing header as a turn that ran no tools
- Times: each one excludes permission prompts and hooks, and parallel tool calls each report their own time, so the entries don’t add up to the gap between requests
Forward as open lists
Treat the headers and body fields as open lists, not closed ones. Claude Code gains capabilities over releases, and they arrive as newanthropic-beta values, new request body fields, and occasionally new anthropic-* or x-claude-code-* headers.
When forwarding to an Anthropic-format upstream, pass anthropic-* request headers and request body fields through unchanged rather than allowlisting the ones you see today. A gateway pinned to an observed list strips the next capability’s header or field and breaks it on the release that introduces it.
The exception is a non-Anthropic upstream such as Amazon Bedrock or Google Cloud’s Agent Platform, where bridging the schema difference is the gateway’s job; see feature pass-through.
Response headers
Claude Code reads these response headers to detect stalled streams, to decide whether and when to retry, and to show usage limits. The table lists what to return for each. Also forward error response bodies unmodified, so Claude Code’s capability-rejection recovery can match the upstream’s error wording.System prompt attribution block
Claude Code prepends a short attribution block to the system prompt containing the client version and a fingerprint derived from the conversation. Theapi.anthropic.com endpoint strips the block before processing when it arrives unchanged as the first system block, so it doesn’t affect first-party prompt caching. Any other upstream receives it as part of the prompt.
The strip is positional, so it only works when the gateway forwards the system array unchanged. To keep the block out of the prompt without losing other system content:
- Forward the
systemarray exactly as received, keeping the block first: prepending another system block, reordering the array, or converting it to a single string defeats the strip, and the block then reaches the model and the prompt cache key. - Keep the block in its own array entry: the endpoint treats a merged block that starts with the attribution header as attribution in its entirety and drops everything merged into it, including the rest of the system prompt.
- If your gateway must reshape system content, set
CLAUDE_CODE_ATTRIBUTION_HEADER=0so Claude Code omits the block. Anthropic and the cloud providers’ Claude endpoints read the block for attribution, so omit it at the client rather than stripping or moving it in the gateway.
0:
- The requests go to
api.anthropic.com, withANTHROPIC_BASE_URLunset or naming that host and no third-party provider selected. - The active credential isn’t an Anthropic profile or federation credential.
0 removes the block from classifier requests too. Before v2.1.229, this exception didn’t exist: setting 0 removed the block from those classifier requests, and when the API declined the unidentified requests, auto mode failed on every action it sent to the classifier.
From Claude Code v2.1.181, the block is stable for the lifetime of a conversation when requests route through a custom base URL, so a gateway-side prompt cache keyed on the full request body works without disabling it, and any provider your gateway forwards to receives a stable prompt prefix. Before v2.1.181 the block included a per-request token that changed the start of the system prompt on every request. On those versions, set CLAUDE_CODE_ATTRIBUTION_HEADER=0 when your gateway does either of these:
- Implements a prompt cache keyed on the request body.
- Forwards requests to a third-party provider such as Amazon Bedrock, Microsoft Foundry, or Google Cloud’s Agent Platform, in the Anthropic Messages format or the provider’s own, where the changing prefix reduces prompt-cache reuse on that provider.
Feature pass-through
Claude Code treats anANTHROPIC_BASE_URL gateway as an Anthropic-format endpoint and sends it the beta headers and request body fields it sends to api.anthropic.com, except a small set of diagnostics and defaults reserved for direct connections, such as the fine-grained tool streaming default covered below. That set varies by release, so don’t depend on its contents.
Fine-grained tool streaming is one of the direct-connection defaults: it is off by default whenever requests route through a custom base URL, and a gateway receives it when developers set CLAUDE_CODE_ENABLE_FINE_GRAINED_TOOL_STREAMING=1.
Beta header and body field pairs
Capabilities that add body fields pair them with a beta header, and the pair travels together. A gateway that strips the header while passing the body, or forwards an Anthropic-format body to an upstream with a different schema, produces400 errors. When both halves are absent together, the feature turns off quietly.
A gateway that rewrites or redacts request bodies for content inspection breaks the pairing the same way stripping does, so inspect without modifying. The table notes where a feature deviates from the pairing.
The
ANTHROPIC_DEFAULT_*_MODEL_SUPPORTED_CAPABILITIES variables declare model capabilities only in the provider configurations: CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, CLAUDE_CODE_USE_FOUNDRY, and CLAUDE_CODE_USE_MANTLE. They have no effect behind an ANTHROPIC_BASE_URL gateway.
Automatic retry and error forwarding
When the upstream rejects one of these capabilities, Claude Code can retry the request on its own with the rejected part removed or changed:- When a
400says thethinking.typevalueenabledoradaptiveisn’t supported, Claude Code retries once with the other type and keeps thethinkingfield. Later requests to that model keep the switched type until Claude Code exits. Before v2.1.121, Claude Code didn’t retry, sothinking.type.enabled is not supportedreached the developer - When the upstream rejects a
role: "system"entry insidemessages, Claude Code retries once without those mid-conversation system messages and carries their text in user messages instead. Later requests in the conversation keep that shape until the developer runs/clearor the conversation compacts - When the upstream rejects only the
cache_controlmarker on a mid-conversation system message, Claude Code keeps the system messages and retries once with the marker moved. The marker goes on the last entry inmessagesthat isn’t a system message, in that retry and in later requests until Claude Code exits - When the upstream rejects a thinking signature, including with a
400whose message says the block isbound to a different conversation, Claude Code removes earlier thinking blocks from the request, retries, and keeps them out of every later request. New responses still include thinking - When the gateway or its upstream rejects the advisor tool entry in
toolsas an unrecognized tool type, Claude Code retries once without that entry and itsanthropic-betavalue. Later requests omit them. Claude Code recognizes this rejection by a400or422response whose message names the tool type afterInput tag, such asInput tag 'advisor_20260301'. Before v2.1.280, Claude Code didn’t retry this rejection - When the upstream rejects
output_config.effortor itsanthropic-betavalue, the gateway sees the request once more without them. Later requests omit them. Your gateway needs no change if it forwards the upstream’s400unmodified and the message:- Names
output_config.effortalongsideExtra inputs are not permitted - Says the model doesn’t support the effort parameter
- Starts with
Unexpected value(s)and listseffort-2025-11-24for theanthropic-betaheader. Requires v2.1.310 or later. Developers whoseANTHROPIC_BETASlists the value keep sending it and getting the400, so have them remove that entry
- Names
- When the upstream rejects the
context_managementfield or itsanthropic-betavalue, the gateway sees the request once more without them. Later requests omit them. Claude Code recognizes this rejection by its message, for example one containingcontext_management: Extra inputs are not permitted. Before v2.1.304, Claude Code didn’t retry this rejection - When a
400rejects anotheranthropic-betavalue by name, the gateway sees the request once more without it if the retry covers that value - When the upstream rejects a beta tool field other than
defer_loading, such asstrict, the400reaches the developer. Before it does, the gateway can see the request again without the tool search fields. To stop sending such fields, have developers setCLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1
bound to a different conversation rejection comes from the API’s preserved thinking check, which fails when system, tools, or earlier messages content differs from the request that produced the thinking. A gateway that rewrites any of that content can cause the rejection itself; Libraries, proxies, and gateways covers what to pass through unchanged.
Most of this retry logic matches on the upstream’s error wording, so forward error response bodies unmodified. A gateway that wraps upstream errors in its own envelope breaks the recovery path, even when it preserves the status code, unless the envelope’s message carries a stable capability_rejected: token. Claude apps gateway substitutes those tokens for cloud providers’ error wording, for example capability_rejected: prompt_too_long.
Retry without a rejected beta value
When a400 rejects by name an anthropic-beta value that this retry covers, the gateway sees the request once more without it. Later requests omit the value. Most values it covers require v2.1.314 or later.
Your gateway needs no change if the message of the 400 it returns carries the value in either of these forms:
- The API’s sentence: the
Unexpected value(s)sentence that lists the value for theanthropic-betaheader - A
beta_header:token:capability_rejected: beta_header:followed by the value, acapability_rejected:token
- A value with its own retry, such as advisor or tool search: the gateway sees that capability’s own retry instead
- A value Claude Code doesn’t recognize: a value that a developer set through
ANTHROPIC_BETASstays on each request, so the developer’s requests keep failing with the400. Have the developer remove the entry - A bare
invalid beta flag: Claude Code guesses which value the upstream rejected. If the request carried a value it guesses at, the gateway sees the request again without that value. If the400still reaches the developer, have your gateway name the rejected value in one of those forms
How long a rejected beta value stays out
Retry without tool search
On v2.1.305 or later, Claude Code resends a request withoutdefer_loading fields and tool_reference blocks after a 400 or 422 that names tool search or whose cause it doesn’t recognize. After a successful retry, later requests in that conversation omit them too.
The developer’s requests keep working without any change on the gateway, with their MCP tools loaded upfront. When Claude Code tries tool search again, the gateway can see another rejected request followed by its retry. For tool search itself, Claude Code expects the gateway to forward the defer_loading fields and tool_reference blocks with their anthropic-beta value.
Disable pre-release capabilities
When your gateway or its upstream rejects pre-releaseanthropic-beta values or the body fields that pair with them, and you can’t forward both halves, have developers set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1. With the variable set, Claude Code stops sending pre-release capabilities and the anthropic-beta values that pair with them, including:
- Context management and its
context_managementbody field - The beta tool schema fields, such as
strictanddefer_loading. The standardname,description,input_schema, andcache_controltool fields stay - The structured-output
output_config.formatfield. Requires Claude Code v2.1.287 or later - The
output_config.task_budgetfield - MCP tool search, so every MCP tool loads upfront unless your organization keeps it on through managed settings
anthropic-beta value. What it leaves in place includes:
- The
anthropic-betavalues for extended context, interleaved thinking, and effort, which cloud providers also accept - The top-level
output_config.effortfield. Automatic retry and error forwarding covers an upstream that rejects it - The adaptive reasoning
thinkingfield, which has no beta header - The
role: "system"entries that carry mid-conversation system messages - The OAuth
anthropic-betavalue that subscription authentication requires - Header values and body fields developers add themselves through
ANTHROPIC_BETASorCLAUDE_CODE_EXTRA_BODY
CLAUDE_CODE_PROVIDER_MANAGED_BY_HOST, CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS doesn’t stop auto mode sessions on Amazon Bedrock, Google Cloud’s Agent Platform, Microsoft Foundry, or a Claude apps gateway from asking the server for classifier review. That review adds an anthropic-beta value and a safeguards request field. Set CLAUDE_CODE_AUTO_MODE_SERVER=0 to stop it there.
On Claude Code v2.1.227 or later, your organization can keep MCP tool search on under this variable through managed settings. What Claude Code sends with that override in place depends on how you connect:
- On a direct connection without the HIPAA configuration, or through a gateway set with
ANTHROPIC_BASE_URL, Claude Code keeps sending the tool-search beta header,defer_loadingtool fields, andtool_referenceblocks - On a cloud provider, or signed in through a Claude apps gateway, the override has no effect
- In a session that gets the HIPAA configuration, the override has no effect and tool search stays off
Model discovery
WhenANTHROPIC_BASE_URL points at a gateway that exposes the Anthropic Messages format, Claude Code can query the gateway’s /v1/models endpoint at startup and add the returned models to the /model picker. If you or your administrator set replaceBuiltInOptions in a modelPicker lineup, Claude Code hides the discovered models from the picker.
Developers enable it by setting CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1, in their own environment or through managed settings. Discovery is off by default so that gateways backed by a shared API key don’t surface every model the key can access to every user.
When discovery runs
Discovery applies only to the Anthropic Messages format. It doesn’t run when:- Any
CLAUDE_CODE_USE_*provider variable is set, even ifANTHROPIC_BASE_URLis also set ANTHROPIC_BASE_URLis unset or points atapi.anthropic.com
Request and response
The request isGET /v1/models?limit=1000 with a timeout of 3 seconds by default, and any redirect is treated as failure so the credential can’t leak to a redirect target. A gateway that responds slower than the timeout, or one that redirects /v1/models, even http to https, fails discovery silently; serve the endpoint directly at the configured base URL.
To give a slow gateway longer, set CLAUDE_CODE_GATEWAY_MODEL_DISCOVERY_TIMEOUT_MS. The variable requires Claude Code v2.1.269 or later.
Claude Code sends the discovery request with both credential headers below and omits a header whose value doesn’t resolve. Sending both headers requires Claude Code v2.1.248 or later. Earlier versions send only Authorization when ANTHROPIC_AUTH_TOKEN is set and only x-api-key otherwise.
Authorization:ANTHROPIC_AUTH_TOKENas a bearer token, otherwise theapiKeyHelpervalue as a bearer token.x-api-key: the API key Claude Code resolved, such asANTHROPIC_API_KEY. When a helper value is the only credential, this header carries it too, so the value arrives in both headers.
ANTHROPIC_CUSTOM_HEADERS. When a custom header has a non-empty value, Claude Code sends it in place of a built-in header of the same name, matching names case-insensitively.
When neither credential header’s value resolves, Claude Code skips discovery and writes a [gatewayDiscovery] skipped line to the debug log of a claude --debug session. If you supply a credential only through ANTHROPIC_CUSTOM_HEADERS, Claude Code still skips discovery.
Claude Code reads id, the optional display_name, and the optional description from each entry in the response’s data array:
id contains claude or anthropic anywhere in the string, matched case-insensitively, and ignores the rest. Provider-prefixed IDs such as vertex_ai/claude-sonnet-4-6 or bedrock/anthropic.claude-sonnet-4-5 pass the filter; an ID that contains neither substring doesn’t. Before v2.1.223, Claude Code kept an entry only when its id began with claude or anthropic, which hid provider-prefixed IDs.
Picker entries and caching
The picker is the interactive model list that opens when a developer runs/model in Claude Code. Each discovered entry uses display_name as its name when the gateway sends one that differs from the id. Otherwise the entry shows the model’s name when Claude Code recognizes the id, and the id when it doesn’t. For example, an entry with the id my-gateway-claude-sonnet-4-6 and no display_name appears as Sonnet 4.6.
Discovery adds only models that the availableModels managed setting allows.
Each entry also shows the model’s description, collapsed to one line. An entry without a description reads “From gateway” instead. Before v2.1.257, every discovered entry read “From gateway”.
A discovered ID doesn’t get its own row when it matches a row already in the picker:
- Same ID: the discovered ID exactly matches an existing row’s ID, or the two IDs are spellings of the same Fable version.
- Same model as a built-in alias: when a discovered explicit ID names the model that a built-in alias currently resolves to, the picker shows only the alias row. For example, while
sonnetresolves toclaude-sonnet-5-5, a discoveredclaude-sonnet-5-5collapses into thesonnetrow, and a discoveredclaude-sonnet-5still gets its own row.
~/.claude/cache/gateway-models.json, or %USERPROFILE%\.claude\cache\gateway-models.json on Windows, and refreshed on each startup. If you set CLAUDE_CONFIG_DIR, the cache lives under that directory instead. If the request fails or the gateway doesn’t implement /v1/models, the picker falls back to the cached list from the previous startup or to the built-in model list. If your gateway serves Claude models under aliases that don’t match the discovery filter, developers can add those aliases manually with the model configuration variables.
Related resources
For the rest of the gateway documentation set and the underlying API references:- Gateway overview: what a gateway is and how to choose between Claude apps gateway and another product
- Other LLM gateways: how to roll out a gateway your organization runs and how it interacts with claude.ai subscriptions
- Roll out an LLM gateway for your organization: the admin checklist that uses this guide
- Connect Claude Code to an LLM gateway: per-developer configuration and the troubleshooting table
- Beta headers reference: the current set of
anthropic-betavalues - Messages API: the API format an Anthropic-format gateway implements