Skip to main content
Version: Dev

Anthropic-Style Messages API

Anthropic-style proxy routes fit applications that already send Anthropic Messages requests and need AISIX to manage gateway-side authentication, model aliases, routing, and policy.

The client keeps the Anthropic-style request and response format. AISIX becomes the endpoint the client calls, and the upstream provider can be Anthropic or another supported provider family.

This guide describes the proxy API behavior. For a runnable client integration, see Anthropic SDK.

What the Client Sends

The client sends three AISIX-owned values:

  • The base URL is the AISIX gateway origin, without a trailing slash or endpoint path.
  • The API key is an AISIX caller API key.
  • The model value is an AISIX model alias, such as claude-prod.

The request body keeps the Anthropic Messages format, including messages, max_tokens, tools, and stream. The caller uses the AISIX caller API key, not the upstream Anthropic provider key.

AISIX also accepts a system role inside messages[] for clients that send that shape. When the upstream path needs Anthropic's native format, AISIX maps leading system messages to Anthropic's top-level system field.

Anthropic SDKs send the caller API key as x-api-key. AISIX also accepts bearer tokens for direct HTTP clients.

Export the gateway connection and request values used below:

# AISIX_PROXY has no trailing slash or endpoint path such as /v1.
# The local quickstarts use http://127.0.0.1:3000.
export AISIX_PROXY="YOUR_AISIX_GATEWAY_URL"
export AISIX_API_KEY="YOUR_CALLER_API_KEY"
export AISIX_MODEL="claude-prod"

Messages Request

Send a Messages request through AISIX:

curl -sS -X POST "${AISIX_PROXY}/v1/messages" \
-H "x-api-key: ${AISIX_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"model": "'"${AISIX_MODEL}"'",
"max_tokens": 128,
"messages": [
{
"role": "user",
"content": "Say hello from AISIX."
}
]
}'

A successful response uses the Anthropic Messages format. The model value in the request is the AISIX model alias, not necessarily the upstream provider model ID.

Choose an Upstream Path

Like other AISIX proxy APIs, /v1/messages lets the client request format stay stable while the upstream provider changes. For Anthropic-style requests, the upstream choice matters because a native Anthropic-protocol route preserves more Anthropic-specific behavior than a translated upstream.

Upstream pathWhat it gives youUse it when
Native Anthropic-protocol routeNative Anthropic request and response behavior, with AISIX handling the caller key, provider key, and model alias. This includes provider keys that use the anthropic adapter and keys that declare apis.messages.The application depends on Anthropic-specific behavior such as thinking blocks, image blocks, cache control, or exact tool-use semantics.
Translated upstreamAn Anthropic-style client edge with a non-Anthropic upstream behind AISIX.The application needs to keep an Anthropic-style client while AISIX routes traffic to another supported provider family.

The translated path supports text, vision, and tool-calling flows end to end. text, image (base64 and URL), and document blocks translate to multimodal content parts on the upstream wire. Assistant tool_use history becomes upstream tool calls, and tool_result blocks become the tool-response turns the upstream expects, so multi-turn tool loops keep their history across providers.

thinking and redacted_thinking history blocks are dropped on translation because another vendor cannot replay Anthropic's signed reasoning blocks. Prefer a native Anthropic-protocol route when the application depends on those reasoning blocks or other provider-specific request fields.

Anthropic Attribution Line

Anthropic's own clients, Claude Code among them, prepend an attribution line to the system prompt. It begins with x-anthropic-billing-header: and carries billing and telemetry metadata that only Anthropic's API reads. Whenever the resolved target is not Anthropic's own API, AISIX removes that line before it builds the upstream request.

The line sits at the very start of the system prompt, and in some deployments its value changes from one request to the next. Forwarding it to another provider therefore changes the prefix of every prompt and defeats that provider's prompt cache for the whole conversation: a conversation that should report a growing cache hit reports zero cached tokens on every turn instead. The line means nothing to that provider, so AISIX drops it.

The client sends:

{
"system": [
{ "type": "text", "text": "x-anthropic-billing-header: cc_entrypoint=cli; cch=7f3a91" },
{ "type": "text", "text": "You are a helpful assistant.", "cache_control": { "type": "ephemeral" } }
]
}

AISIX builds the upstream request from what is left:

{
"system": [
{ "type": "text", "text": "You are a helpful assistant.", "cache_control": { "type": "ephemeral" } }
]
}

An Anthropic-protocol upstream receives that system field as it stands. On the translated path AISIX then converts it into the system field or system message the upstream family uses, the same way it converts any other request.

  • Only the line is removed, not its container. Text that follows it in the same block is kept, along with that block's cache_control marker. A block left with nothing is dropped, and a system left with no content is omitted from the upstream request. The plain-string form of system is treated the same way.
  • The match is on the leading x-anthropic-billing-header: marker, ignoring leading whitespace and letter case.
  • messages are never touched. A caller that quotes the line inside conversation content still sends it upstream, because removing it there would change what the model is asked about.
  • The exemption is narrow. A target keeps the line only when its model's provider is anthropic and its provider key reaches the Anthropic API natively. Everything else is covered: the translated path, third-party Anthropic-compatible providers reached through byo with the anthropic adapter or through a provider key that declares apis.messages, and the Bedrock, Vertex AI, and Azure OpenAI platform adapters — a platform key still loses the line even under provider: anthropic. A byo key pointed at Anthropic's own API is not exempt either, because the exemption reads the model's provider value.
  • POST /v1/messages/count_tokens applies the same removal, so the count it returns is the count for the body /v1/messages would send.

There is no configuration for this behavior.

Request Fields on the Translated Path

When the provider key does not select a native Anthropic-protocol route, AISIX rewrites the Anthropic request fields into the shape the upstream family expects instead of forwarding them verbatim:

Anthropic fieldTranslated behavior
tools, tool_choiceTranslated to the OpenAI tool-calling shape.
stop_sequencesSent as stop.
metadata.user_idSent as user.
thinking, output_config.effortMapped to reasoning_effort. See Reasoning Effort for the resolution order and the tiers AISIX forwards.
output_format, output_config.formatA json_schema block is sent as response_format in the OpenAI json_schema form with strict mode enabled, carrying the schema as the caller wrote it. Any other shape is dropped. When a request carries both fields, output_format wins. An OpenAI-compatible upstream closes the strict schema at its own edge: additionalProperties: false plus every declared property listed in required, at every object level. A non-OpenAI upstream applies its own mapping instead — see Structured Output for the reverse direction, an OpenAI response_format reaching an Anthropic, Gemini, or Bedrock upstream.
context_management, top_k, mcp_servers, container, service_tier, betas, and other Anthropic-only fieldsDropped. Forwarding them would fail OpenAI-compatible upstreams with unknown-parameter errors, so requests from newer Anthropic SDKs keep working as new fields appear.

Native Anthropic-protocol routes do not go through this translation, so every Anthropic field keeps its native behavior on that path. AISIX still rewrites the model alias to the upstream model ID, removes the attribution line described in Anthropic Attribution Line unless the target is Anthropic's own API, applies any reasoning-effort mapping the model configures, and applies the request overrides the provider key configures. Every other field goes upstream as the client sent it.

Reasoning Effort

An Anthropic request can carry the reasoning depth in two places. output_config.effort is the current control, and the only one that Claude Opus 4.7 and later models accept. thinking.budget_tokens is the older one, deprecated on Claude Opus 4.6. An OpenAI-compatible upstream has a single reasoning_effort field for both, so AISIX resolves them in this order:

  1. thinking.type: disabled sends reasoning_effort: none. An explicit opt-out is a stronger instruction than a depth tier, so an output_config.effort alongside it does not override it.
  2. output_config.effort is sent as reasoning_effort, with the tier unchanged.
  3. thinking.type: enabled maps budget_tokens to a tier: 0-1023 minimal, 1024-2047 low, 2048-4095 medium, 4096 and above high.
  4. thinking.type: adaptive with no output_config.effort sends reasoning_effort: high, the tier Anthropic itself applies when a request omits an effort.

AISIX forwards the tier the request asked for and does not check it against the upstream model. Anthropic models accept tiers such as max and xhigh that many OpenAI-compatible models do not, and an upstream that does not accept a tier rejects the request. That rejection is deliberate. Substituting a tier the upstream happens to accept would quietly change the reasoning depth the application asked for, and that is far harder to notice than an error. Pick a tier the upstream model supports, and check the provider's own documentation for its range.

Upstream models with no reasoning support at all reject reasoning_effort itself, so send thinking and effort fields only to reasoning-capable models.

Streaming and non-streaming requests take the same translation.

Route Behavior

/v1/messages can use direct and routing model aliases. Non-streaming requests can fail over to the next target on retryable upstream failures.

Streaming requests can fail over before AISIX sends response bytes to the client. AISIX does not switch targets after the client-visible stream starts. For general streaming behavior, see Streaming.

POST /v1/messages/count_tokens uses the same AISIX caller API key and accepts the Anthropic token-counting request format. This route only uses targets whose provider key uses the anthropic adapter or declares apis.messages. A declaration covers both Messages routes, so confirm that the upstream also implements /v1/messages/count_tokens; otherwise, use a translated model for /v1/messages or a passthrough route for the provider's native Messages API. If no native Anthropic-protocol target is available, AISIX rejects the request.

Handle Errors

Messages routes return errors in an Anthropic-style envelope. The error type follows Anthropic SDK-compatible status mappings, so Anthropic clients can parse gateway-generated errors with the same error-handling path they use for provider errors.

Native Anthropic upstream errors can include request_id. AISIX does not add that field to gateway-generated Anthropic-style errors.

When an output guardrail holds a stream back, a buffered frame that AISIX cannot parse is dropped rather than released unscanned. A response left with nothing to return ends with a terminal SSE error event. That event uses the Anthropic envelope like every other error on this route. It therefore carries an Anthropic-legal error.type and no code field, rather than the content_filter an OpenAI-style route would return. The reason is named in the message instead. See Frames AISIX Cannot Scan and Guardrail Refusals.

For the full error and header reference, see Headers and Error Codes. For provider-defined error types, see Anthropic's Errors documentation.

Next Steps

You have now seen how Anthropic-style clients call AISIX. Continue with Streaming, Tool Calling, or Proxy Errors and Retries when your application depends on those behaviors.