Proxy Anthropic Requests
Configure APISIX to proxy OpenAI-compatible and native Anthropic Messages requests with the ai-proxy plugin, then verify and clean up the Routes.
Applies to:Apache APISIX 3.18.0
Deployments:DockerRoles:Platform engineerTime:20 minutesImpact:Changes live traffic
Goal
Create isolated APISIX Routes for an OpenAI Chat Completions-shaped client and a native Anthropic Messages client. Keep the Anthropic credential and model selection at the gateway, validate both response formats, then remove the Routes and shell secrets.
The validation requests call the live Anthropic API. They can incur provider charges and send the example prompts to Anthropic under your account's data controls. Use approved test credentials, models, and content.
Before you begin
- Complete Get APISIX with the Docker quickstart.
- Install cURL and jq.
- Create an Anthropic API key.
- Choose an active model available to your account. Model IDs and retirement dates change; consult Anthropic's model overview instead of copying a model name from an old example.
Set the endpoints, read secrets without echoing them, and protect the fixed Route IDs used by this guide:
export APISIX_ADMIN_URL="http://127.0.0.1:9180"
export GATEWAY_URL="http://127.0.0.1:9080"
read -rsp "Admin API key (press Enter for an unchanged quickstart): " APISIX_ADMIN_KEY && export APISIX_ADMIN_KEY && echo
read -rsp "Anthropic API key: " ANTHROPIC_API_KEY && export ANTHROPIC_API_KEY && echo
read -rp "Active Anthropic model: " ANTHROPIC_MODEL && export ANTHROPIC_MODEL
test -n "${ANTHROPIC_API_KEY}" && test -n "${ANTHROPIC_MODEL}"
for route_id in anthropic-guide-chat anthropic-guide-messages; do
test "$(curl -sS --connect-timeout 3 --max-time 10 -o /dev/null -w '%{http_code}' \
"${APISIX_ADMIN_URL}/apisix/admin/routes/${route_id}" \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}")" = 404 || \
{ echo "Stop: route ${route_id} already exists"; exit 1; }
doneSteps
Step 1: Create the OpenAI-compatible Chat Route
APISIX detects the messages array and sends an OpenAI Chat Completions-shaped request to Anthropic's compatible endpoint.
jq -n --arg key "${ANTHROPIC_API_KEY}" --arg model "${ANTHROPIC_MODEL}" '{
name:"anthropic-guide-chat",
uri:"/anthropic-guide/chat",
methods:["POST"],
plugins:{
"ai-proxy":{
provider:"anthropic",
auth:{header:{"x-api-key":$key}},
options:{model:$model}
}
}
}' | \
curl --fail-with-body -sS --connect-timeout 3 --max-time 15 \
"${APISIX_ADMIN_URL}/apisix/admin/routes/anthropic-guide-chat" -X PUT \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" -H 'Content-Type: application/json' \
--data-binary @- | \
jq -e --arg model "${ANTHROPIC_MODEL}" '
.value.id == "anthropic-guide-chat" and
.value.uri == "/anthropic-guide/chat" and
.value.plugins["ai-proxy"].provider == "anthropic" and
.value.plugins["ai-proxy"].options.model == $model'What changed: the custom client path now uses the gateway-managed key and model and returns an OpenAI Chat Completions-shaped response.
Step 2: Create the native Messages Route
The native path must end in /v1/messages. APISIX then passes the Anthropic Messages format through without protocol conversion, preserving provider-specific fields.
jq -n --arg key "${ANTHROPIC_API_KEY}" --arg model "${ANTHROPIC_MODEL}" '{
name:"anthropic-guide-messages",
uri:"/anthropic-guide/v1/messages",
methods:["POST"],
plugins:{
"ai-proxy":{
provider:"anthropic",
auth:{header:{"x-api-key":$key}},
options:{model:$model}
}
}
}' | \
curl --fail-with-body -sS --connect-timeout 3 --max-time 15 \
"${APISIX_ADMIN_URL}/apisix/admin/routes/anthropic-guide-messages" -X PUT \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" -H 'Content-Type: application/json' \
--data-binary @- | \
jq -e --arg model "${ANTHROPIC_MODEL}" '
.value.id == "anthropic-guide-messages" and
.value.uri == "/anthropic-guide/v1/messages" and
.value.plugins["ai-proxy"].provider == "anthropic" and
.value.plugins["ai-proxy"].options.model == $model'Do not commit credentials in ADC, Kubernetes manifests, or shell history. The Admin API configuration still contains the provider key and must be access-controlled. When data encryption with a keyring is enabled, APISIX encrypts configured ai-proxy authentication fields before storing them in etcd.
Validate
Send an OpenAI Chat Completions-shaped request and require a non-empty assistant message:
curl --fail-with-body -sS --connect-timeout 3 --max-time 90 \
"${GATEWAY_URL}/anthropic-guide/chat" -X POST \
-H 'Content-Type: application/json' \
-d '{"messages":[{"role":"user","content":"Reply with one short sentence defining an API gateway."}]}' | \
jq -e '.object == "chat.completion" and (.choices[0].message.content | type == "string" and length > 0)'Send a native Messages request. Anthropic requires the version header; 2023-06-01 remains its current stable API version.
curl --fail-with-body -sS --connect-timeout 3 --max-time 90 \
"${GATEWAY_URL}/anthropic-guide/v1/messages" -X POST \
-H 'Content-Type: application/json' \
-H 'anthropic-version: 2023-06-01' \
-d '{"max_tokens":128,"messages":[{"role":"user","content":"Reply with one short sentence defining an API gateway."}]}' | \
jq -e '.type == "message" and .role == "assistant" and any(.content[]?; .type == "text" and (.text | length > 0)) and (.stop_reason | type == "string")'Both commands must exit successfully. The native assertion follows Anthropic's documented Messages response shape without depending on exact prose or a particular stop reason.
Roll back / Clean up
Delete both Routes and remove secrets and the model name from the shell:
for route_id in anthropic-guide-chat anthropic-guide-messages; do
curl --fail-with-body -sS --connect-timeout 3 --max-time 15 -X DELETE \
"${APISIX_ADMIN_URL}/apisix/admin/routes/${route_id}" \
-H "X-API-KEY: ${APISIX_ADMIN_KEY}" | jq -e '.key | endswith("/" + $route_id)' --arg route_id "${route_id}"
done
unset APISIX_ADMIN_URL APISIX_ADMIN_KEY GATEWAY_URL ANTHROPIC_API_KEY ANTHROPIC_MODELExpected: both fixed Route IDs are deleted and the five shell variables are unset.
Troubleshoot
| Symptom | Cause | Fix |
|---|---|---|
| A native request returns an OpenAI-shaped response. | The Route URI does not end in /v1/messages. | Use the exact native URI configured in this guide. |
Anthropic returns 401. | The key is invalid, revoked, or unavailable to the selected workspace. | Create or select an approved workspace key, then recreate both Routes. |
| Anthropic returns a model error. | The chosen model is unavailable, deprecated, or retired. | Select an active model available to the account and recreate both Routes. |
APISIX returns 502 or times out. | APISIX cannot reach Anthropic, or the provider exceeded the bounded request time. | Check gateway egress, DNS, TLS trust, and provider status; do not remove timeouts while diagnosing. |
A validation assertion fails after HTTP 200. | The response format does not match the selected client protocol. | Read the response without the final jq only in an approved environment, then verify the Route suffix and request body. |
Related
- AI Proxy (opens in Plugin Hub docs) — Anthropic-compatible and native pass-through behavior.
- AI Proxy Protocol Reference (opens in Plugin Hub docs) — request detection, conversion, and limitations.
- Create a Message — official native request and response fields.
- API versioning — Anthropic version-header requirements.