ai-proxy
The ai-proxy plugin simplifies access to LLM and embedding models by transforming plugin configurations into the required request format. It supports OpenAI, DeepSeek, Anthropic, Gemini, Vertex AI, and other OpenAI-compatible APIs.
Before forwarding a request, the plugin identifies the client protocol from the request URI and body. Protocol conversion applies when the client uses Anthropic Messages but the selected provider supports OpenAI Chat Completions instead of native Anthropic Messages. The plugin converts the client request to OpenAI format and the backend response to Anthropic format. This conversion supports only a subset of Anthropic Messages. See Protocol Reference for detection rules, field mappings, release boundaries, and limitations.
The plugin can also record LLM request information in the access log, not the error log, including token usage, model, and time to first response. Logging plugins can consume these entries.
Examples
The examples below demonstrate how you can configure ai-proxy for different scenarios.
Proxy to OpenAI
The following example demonstrates how you can configure the API key, model, and other parameters in the ai-proxy plugin and configure the plugin on a route to proxy user prompts to OpenAI.
Obtain the OpenAI API key and optionally save it to an environment variable:
export OPENAI_API_KEY=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 # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options":{
"model": "gpt-4"
}
}
}
}
EOF
❶ Specify the provider to be openai.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the model.
Create a route with the ai-proxy plugin configured as such:
services:
- name: openai-service
routes:
- name: openai-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: openai
auth:
header:
Authorization: "Bearer ${OPENAI_API_KEY}"
options:
model: gpt-4
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be openai.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the model.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: openai
auth:
header:
Authorization: "Bearer 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"
options:
model: gpt-4
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: openai-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-ic.yaml
❶ Specify the provider to be openai.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the model.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: openai-route
spec:
ingressClassName: apisix
http:
- name: openai-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: openai
auth:
header:
Authorization: "Bearer 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"
options:
model: gpt-4
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-ic.yaml
❶ Specify the provider to be openai.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the model.
Send a POST request to the route with a system prompt and a sample user question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You should receive a response similar to the following:
{
...,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}
If the LLM upstream returns 429 or a 5xx response, the client receives the upstream status, response body, and Content-Type. This preserves any provider error details.
Proxy to DeepSeek
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to DeepSeek.
Obtain the DeepSeek API key and optionally save it to an environment variable:
export DEEPSEEK_API_KEY=sk-5e99f3e26abc40e75d80009a90e66 # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "deepseek",
"auth": {
"header": {
"Authorization": "Bearer $DEEPSEEK_API_KEY"
}
},
"options": {
"model": "deepseek-chat"
}
}
}
}
EOF
❶ Specify the provider to be deepseek, so that the plugin will proxy requests to https://api.deepseek.com/chat/completions.
❷ Attach DeepSeek API key in the Authorization header.
❸ Specify the name of the model.
Create a route with the ai-proxy plugin configured as such:
services:
- name: deepseek-service
routes:
- name: deepseek-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: deepseek
auth:
header:
Authorization: "Bearer ${DEEPSEEK_API_KEY}"
options:
model: deepseek-chat
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be deepseek, so that the plugin will proxy requests to https://api.deepseek.com/chat/completions.
❷ Attach DeepSeek API key in the Authorization header.
❸ Specify the name of the model.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: deepseek
auth:
header:
Authorization: "Bearer sk-5e99f3e26abc40e75d80009a90e66"
options:
model: deepseek-chat
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: deepseek-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f deepseek-ic.yaml
❶ Specify the provider to be deepseek, so that the plugin will proxy requests to https://api.deepseek.com/chat/completions.
❷ Attach DeepSeek API key in the Authorization header.
❸ Specify the name of the model.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: deepseek-route
spec:
ingressClassName: apisix
http:
- name: deepseek-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: deepseek
auth:
header:
Authorization: "Bearer sk-5e99f3e26abc40e75d80009a90e66"
options:
model: deepseek-chat
Apply the configuration to your cluster:
kubectl apply -f deepseek-ic.yaml
❶ Specify the provider to be deepseek, so that the plugin will proxy requests to https://api.deepseek.com/chat/completions.
❷ Attach DeepSeek API key in the Authorization header.
❸ Specify the name of the model.
Send a POST request to the route with a sample question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are an AI assistant that helps people find information."
},
{
"role": "user",
"content": "Write me a 50-word introduction for Apache APISIX."
}
]
}'
You should receive a response similar to the following:
{
...
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Apache APISIX is a dynamic, real-time, high-performance API gateway and cloud-native platform. It provides rich traffic management features like load balancing, dynamic upstream, canary release, circuit breaking, authentication, observability, and more. Designed for microservices and serverless architectures, APISIX ensures scalability, security, and seamless integration with modern DevOps workflows."
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}
Proxy to Azure OpenAI
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to other LLM services, such as Azure OpenAI.
Obtain the Azure OpenAI API key and optionally save it to an environment variable:
export AZ_OPENAI_API_KEY=57cha9ee8e8a89a12c0aha174f180f4 # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "azure-openai",
"auth": {
"header": {
"api-key": "$AZ_OPENAI_API_KEY"
}
},
"options":{
"model": "gpt-4"
},
"override": {
"endpoint": "https://api7-azure-openai.openai.azure.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-15-preview"
}
}
}
}
EOF
❶ Set the provider to azure-openai.
❷ Attach Azure OpenAI API key in the api-key header.
❸ Specify the name of the model.
❹ Specify the Azure OpenAI endpoint.
Create a route with the ai-proxy plugin configured as such:
services:
- name: azure-openai-service
routes:
- name: azure-openai-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: azure-openai
auth:
header:
api-key: "${AZ_OPENAI_API_KEY}"
options:
model: gpt-4
override:
endpoint: "https://api7-azure-openai.openai.azure.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-15-preview"
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Set the provider to azure-openai.
❷ Attach Azure OpenAI API key in the api-key header.
❸ Specify the name of the model.
❹ Specify the Azure OpenAI endpoint.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: azure-openai
auth:
header:
api-key: "57cha9ee8e8a89a12c0aha174f180f4"
options:
model: gpt-4
override:
endpoint: "https://api7-azure-openai.openai.azure.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-15-preview"
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: azure-openai-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f azure-openai-ic.yaml
❶ Set the provider to azure-openai.
❷ Attach Azure OpenAI API key in the api-key header.
❸ Specify the name of the model.
❹ Specify the Azure OpenAI endpoint.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: azure-openai-route
spec:
ingressClassName: apisix
http:
- name: azure-openai-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: azure-openai
auth:
header:
api-key: "57cha9ee8e8a89a12c0aha174f180f4"
options:
model: gpt-4
override:
endpoint: "https://api7-azure-openai.openai.azure.com/openai/deployments/gpt-4/chat/completions?api-version=2024-02-15-preview"
Apply the configuration to your cluster:
kubectl apply -f azure-openai-ic.yaml
❶ Set the provider to azure-openai.
❷ Attach Azure OpenAI API key in the api-key header.
❸ Specify the name of the model.
❹ Specify the Azure OpenAI endpoint.
Send a POST request to the route with a sample question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "system",
"content": "You are an AI assistant that helps people find information."
},
{
"role": "user",
"content": "Write me a 50-word introduction for Apache APISIX."
}
],
"max_tokens": 800,
"temperature": 0.7,
"frequency_penalty": 0,
"presence_penalty": 0,
"top_p": 0.95,
"stop": null
}'
You should receive a response similar to the following:
{
"choices": [
{
...,
"message": {
"content": "Apache APISIX is a modern, cloud-native API gateway built to handle high-performance and low-latency use cases. It offers a wide range of features, including load balancing, rate limiting, authentication, and dynamic routing, making it an ideal choice for microservices and cloud-native architectures.",
"role": "assistant"
}
}
],
...
}
Proxy to Gemini
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to Google's Gemini API for chat completion. This example applies to API7 Enterprise from version 3.9.2 and APISIX from version 3.17.0.
Obtain a Gemini API key and optionally save it to an environment variable:
export GEMINI_API_KEY=AIzaSyDUMZbZmHCmJ5BNNLl0KfQk # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-gemini-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "gemini",
"auth": {
"header": {
"Authorization": "Bearer $GEMINI_API_KEY"
}
},
"options": {
"model": "gemini-2.5-flash"
}
}
}
}
EOF
❶ Specify the provider to be gemini.
❷ Replace with your Gemini API key in the Authorization header.
❸ Specify the name of the Gemini model.
Create a route with the ai-proxy plugin configured as such:
services:
- name: gemini-service
routes:
- name: gemini-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: gemini
auth:
header:
Authorization: "Bearer ${GEMINI_API_KEY}"
options:
model: gemini-2.5-flash
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be gemini.
❷ Replace with your Gemini API key in the Authorization header.
❸ Specify the name of the Gemini model.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: gemini
auth:
header:
Authorization: "Bearer AIzaSyDUMZbZmHCmJ5BNNLl0KfQk"
options:
model: gemini-2.5-flash
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: gemini-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f gemini-ic.yaml
❶ Specify the provider to be gemini.
❷ Replace with your Gemini API key in the Authorization header.
❸ Specify the name of the Gemini model.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: gemini-route
spec:
ingressClassName: apisix
http:
- name: gemini-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: gemini
auth:
header:
Authorization: "Bearer AIzaSyDUMZbZmHCmJ5BNNLl0KfQk"
options:
model: gemini-2.5-flash
Apply the configuration to your cluster:
kubectl apply -f gemini-ic.yaml
❶ Specify the provider to be gemini.
❷ Replace with your Gemini API key in the Authorization header.
❸ Specify the name of the Gemini model.
The configuration above proxies requests to the chat completion endpoint at https://generativelanguage.googleapis.com/v1beta/openai/chat/completions. To proxy requests to an embeddings model, explicitly configure the embeddings model endpoint in the override field.
Send a POST request to the route with a system prompt and a sample user question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a helpful AI assistant" },
{ "role": "user", "content": "What is the capital of France?" }
]
}'
You should receive a response similar to the following:
{
"choices": [
{
"finish_reason": "stop",
"index": 0,
"message": {
"content": "The capital of France is **Paris**.",
"role": "assistant"
}
}
],
"model": "gemini-2.5-flash",
"object": "chat.completion",
"usage": {
"completion_tokens": 8,
"prompt_tokens": 15,
"total_tokens": 41
},
...
}
Proxy to Vertex AI Chat Completion
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to Google Cloud's Vertex AI platform using GCP service account authentication. This example applies to API7 Enterprise from version 3.9.2 and APISIX from version 3.17.0.
Before proceeding:
- Enable Vertex AI and billing for your GCP project.
- Follow the service account credentials section to create a service account in GCP, assign the account with the "Vertex AI User" role, and obtain the account credentials in JSON.
Your credentials file should look similar to the following:
{
"type": "service_account",
"project_id": "api7-vertex",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "api7-docs@api7-vertex.iam.gserviceaccount.com",
"client_id": "....",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
Optionally save the JSON to an environment variable:
export GCP_SA_JSON="$(cat credentials.json)"
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-vertex-ai-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "vertex-ai",
"auth": {
"gcp": {
"service_account_json": "$GCP_SA_JSON"
}
},
"provider_conf": {
"project_id": "api7-vertex",
"region": "us-central1"
},
"options": {
"model": "google/gemini-2.5-flash"
}
}
}
}
EOF
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Gemini model through Vertex AI in the <publisher>/<model> format.
Create a route with the ai-proxy plugin configured as such:
services:
- name: vertex-ai-service
routes:
- name: vertex-ai-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: vertex-ai
auth:
gcp:
service_account_json: "${GCP_SA_JSON}"
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: google/gemini-2.5-flash
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Gemini model through Vertex AI in the <publisher>/<model> format.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: vertex-ai
auth:
gcp:
service_account_json: '{"type":"service_account","project_id":"api7-vertex","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----","client_email":"api7-docs@api7-vertex.iam.gserviceaccount.com","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com","universe_domain":"googleapis.com"}'
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: google/gemini-2.5-flash
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: vertex-ai-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f vertex-ai-ic.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Gemini model through Vertex AI in the <publisher>/<model> format.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: vertex-ai-route
spec:
ingressClassName: apisix
http:
- name: vertex-ai-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: vertex-ai
auth:
gcp:
service_account_json: '{"type":"service_account","project_id":"api7-vertex","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----","client_email":"api7-docs@api7-vertex.iam.gserviceaccount.com","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com","universe_domain":"googleapis.com"}'
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: google/gemini-2.5-flash
Apply the configuration to your cluster:
kubectl apply -f vertex-ai-ic.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Gemini model through Vertex AI in the <publisher>/<model> format.
Send a POST request to the route with a system prompt and a sample user question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You should receive a response similar to the following:
{
"choices": [
{
"message": {
"role": "assistant",
"content": "1 + 1 = 2\n"
},
"index": 0,
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"completion_tokens": 8,
"extra_properties": {
"google": {
"traffic_type": "ON_DEMAND"
}
},
"total_tokens": 19,
"prompt_tokens": 11
},
"object": "chat.completion",
"model": "google/gemini-2.5-flash",
...
}
Proxy to Vertex AI Embedding Models
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to Vertex AI embedding models using GCP service account authentication. This example applies to API7 Enterprise from version 3.9.2 and APISIX from version 3.17.0.
Before proceeding:
- Enable Vertex AI and billing for your GCP project.
- Follow the service account credentials section to create a service account in GCP, assign the account with the "Vertex AI User" role, and obtain the account credentials in JSON.
Your credentials file should look similar to the following:
{
"type": "service_account",
"project_id": "api7-vertex",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "api7-docs@api7-vertex.iam.gserviceaccount.com",
"client_id": "....",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
Optionally save the JSON to an environment variable:
export GCP_SA_JSON="$(cat credentials.json)"
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-vertex-ai-embeddings-route",
"uri": "/embeddings",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "vertex-ai",
"auth": {
"gcp": {
"service_account_json": "$GCP_SA_JSON"
}
},
"provider_conf": {
"project_id": "api7-vertex",
"region": "us-central1"
},
"options": {
"model": "gemini-embedding-001"
}
}
}
}
EOF
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Vertex AI Gemini embedding model.
Create a route with the ai-proxy plugin configured as such:
services:
- name: vertex-ai-embeddings-service
routes:
- name: vertex-ai-embeddings-route
uris:
- /embeddings
methods:
- POST
plugins:
ai-proxy:
provider: vertex-ai
auth:
gcp:
service_account_json: "${GCP_SA_JSON}"
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: gemini-embedding-001
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Vertex AI Gemini embedding model.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: vertex-ai
auth:
gcp:
service_account_json: '{"type":"service_account","project_id":"api7-vertex","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----","client_email":"api7-docs@api7-vertex.iam.gserviceaccount.com","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com","universe_domain":"googleapis.com"}'
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: gemini-embedding-001
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: vertex-ai-embeddings-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /embeddings
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f vertex-ai-embeddings-ic.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Vertex AI Gemini embedding model.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: vertex-ai-embeddings-route
spec:
ingressClassName: apisix
http:
- name: vertex-ai-embeddings-route
match:
paths:
- /embeddings
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: vertex-ai
auth:
gcp:
service_account_json: '{"type":"service_account","project_id":"api7-vertex","private_key_id":"...","private_key":"-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----","client_email":"api7-docs@api7-vertex.iam.gserviceaccount.com","client_id":"...","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_x509_cert_url":"https://www.googleapis.com/robot/v1/metadata/x509/api7-docs%40api7-vertex.iam.gserviceaccount.com","universe_domain":"googleapis.com"}'
provider_conf:
project_id: api7-vertex
region: us-central1
options:
model: gemini-embedding-001
Apply the configuration to your cluster:
kubectl apply -f vertex-ai-embeddings-ic.yaml
❶ Specify the provider to be vertex-ai.
❷ Replace with your JSON credentials. Ensure that it is a JSON-escaped string.
❸ Replace with your Vertex AI project ID and region.
❹ Specify the name of the Vertex AI Gemini embedding model.
Send a POST request to the route with an input string:
curl "http://127.0.0.1:9080/embeddings" -X POST \
-H "Content-Type: application/json" \
-d '{
"input": "hello world"
}'
You should receive a response similar to the following:
{
"model": "gemini-embedding-001",
"usage": {
"total_tokens": 2,
"prompt_tokens": 2
},
"object": "list",
"data": [
{
"index": 0,
"object": "embedding",
"embedding": [
-0.0241838414222,
0.0098769934847951,
0.0074856607243419,
-0.067302219569683,
...
]
}
]
}
Proxy to OpenAI Embedding Models
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to embedding models. This example will use the OpenAI embedding model endpoint.
Obtain the OpenAI API key and optionally save it to an environment variable:
export OPENAI_API_KEY=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 # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-route",
"uri": "/embeddings",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "text-embedding-3-small",
"encoding_format": "float"
}
}
}
}
EOF
❶ Select the openai provider. When the request body contains input, the plugin detects an Embeddings request and sends it to https://api.openai.com/v1/embeddings.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the embedding model.
❹ Add an additional parameter encoding_format to configure returned embedding vector to be a list of floating point numbers.
Create a route with the ai-proxy plugin configured as such:
services:
- name: openai-embeddings-service
routes:
- name: openai-embeddings-route
uris:
- /embeddings
methods:
- POST
plugins:
ai-proxy:
provider: openai
auth:
header:
Authorization: "Bearer ${OPENAI_API_KEY}"
options:
model: text-embedding-3-small
encoding_format: float
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Select the openai provider. When the request body contains input, the plugin detects an Embeddings request and sends it to https://api.openai.com/v1/embeddings.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the embedding model.
❹ Add an additional parameter encoding_format to configure returned embedding vector to be a list of floating point numbers.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: openai
auth:
header:
Authorization: "Bearer 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"
options:
model: text-embedding-3-small
encoding_format: float
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: openai-embeddings-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /embeddings
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f openai-embeddings-ic.yaml
❶ Select the openai provider. When the request body contains input, the plugin detects an Embeddings request and sends it to https://api.openai.com/v1/embeddings.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the embedding model.
❹ Add an additional parameter encoding_format to configure returned embedding vector to be a list of floating point numbers.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: openai-embeddings-route
spec:
ingressClassName: apisix
http:
- name: openai-embeddings-route
match:
paths:
- /embeddings
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: openai
auth:
header:
Authorization: "Bearer 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"
options:
model: text-embedding-3-small
encoding_format: float
Apply the configuration to your cluster:
kubectl apply -f openai-embeddings-ic.yaml
❶ Select the openai provider. When the request body contains input, the plugin detects an Embeddings request and sends it to https://api.openai.com/v1/embeddings.
❷ Attach OpenAI API key in the Authorization header.
❸ Specify the name of the embedding model.
❹ Add an additional parameter encoding_format to configure returned embedding vector to be a list of floating point numbers.
Send a POST request to the route with an input string:
curl "http://127.0.0.1:9080/embeddings" -X POST \
-H "Content-Type: application/json" \
-d '{
"input": "hello world"
}'
You should receive a response similar to the following:
{
"object": "list",
"data": [
{
"object": "embedding",
"index": 0,
"embedding": [
-0.0067144386,
-0.039197803,
0.034177095,
0.028763203,
-0.024785956,
-0.04201061,
...
],
}
],
"model": "text-embedding-3-small",
"usage": {
"prompt_tokens": 2,
"total_tokens": 2
}
}
Proxy to Anthropic
The following example demonstrates how you can configure the ai-proxy plugin to proxy requests to the Anthropic Claude API for chat completion.
Obtain an Anthropic API key and optionally save it to an environment variable:
export ANTHROPIC_API_KEY=sk-ant-api03-XXXXXXXXXXXXXXXX # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-anthropic-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "anthropic",
"auth": {
"header": {
"x-api-key": "$ANTHROPIC_API_KEY"
}
},
"options": {
"model": "claude-sonnet-4-20250514"
}
}
}
}
EOF
❶ Specify the provider to be anthropic.
❷ Attach Anthropic API key in the x-api-key header.
❸ Specify the name of the Anthropic model.
Create a route with the ai-proxy plugin configured as such:
services:
- name: anthropic-service
routes:
- name: anthropic-route
uris:
- /anything
methods:
- POST
plugins:
ai-proxy:
provider: anthropic
auth:
header:
x-api-key: "${ANTHROPIC_API_KEY}"
options:
model: claude-sonnet-4-20250514
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Specify the provider to be anthropic.
❷ Attach Anthropic API key in the x-api-key header.
❸ Specify the name of the Anthropic model.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: anthropic
auth:
header:
x-api-key: "sk-ant-api03-XXXXXXXXXXXXXXXX"
options:
model: claude-sonnet-4-20250514
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: anthropic-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /anything
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f anthropic-ic.yaml
❶ Specify the provider to be anthropic.
❷ Attach Anthropic API key in the x-api-key header.
❸ Specify the name of the Anthropic model.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: anthropic-route
spec:
ingressClassName: apisix
http:
- name: anthropic-route
match:
paths:
- /anything
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: anthropic
auth:
header:
x-api-key: "sk-ant-api03-XXXXXXXXXXXXXXXX"
options:
model: claude-sonnet-4-20250514
Apply the configuration to your cluster:
kubectl apply -f anthropic-ic.yaml
❶ Specify the provider to be anthropic.
❷ Attach Anthropic API key in the x-api-key header.
❸ Specify the name of the Anthropic model.
Send a POST request to the route with a system prompt and a sample user question in the request body:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You should receive a response similar to the following:
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "1+1 equals 2."
}
],
"model": "claude-sonnet-4-20250514",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 19,
"output_tokens": 11
}
}
Convert Anthropic Requests to OpenAI-Compatible Backend
This example configures the ai-proxy plugin to accept Anthropic Messages requests, convert them to OpenAI Chat Completions, and forward them to an OpenAI-compatible backend. Use this configuration when client applications send Anthropic-formatted requests but the backend uses an OpenAI-compatible API.
The /v1/messages URI suffix identifies the request as Anthropic Messages. Because this example configures an OpenAI-compatible provider, the plugin converts requests to OpenAI Chat Completions and converts responses back to Anthropic format.
Obtain an API key for your chosen OpenAI-compatible backend service and save it to an environment variable. This example uses OpenAI:
export BACKEND_API_KEY=sk-xxx # replace with your API key
- Admin API
- ADC
- Ingress Controller
Create a route and configure the ai-proxy plugin as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-anthropic-convert-route",
"uri": "/v1/messages",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $BACKEND_API_KEY"
}
},
"options": {
"model": "gpt-4"
}
}
}
}
EOF
❶ Use a URI ending in /v1/messages to identify the request as Anthropic Messages.
❷ Configure a provider that supports OpenAI Chat Completions. The plugin converts the Anthropic request before forwarding it.
❸ Specify the model name of the backend provider.
Create a route with the ai-proxy plugin configured as such:
services:
- name: anthropic-convert-service
routes:
- name: anthropic-convert-route
uris:
- /v1/messages
methods:
- POST
plugins:
ai-proxy:
provider: openai
auth:
header:
Authorization: "Bearer ${BACKEND_API_KEY}"
options:
model: gpt-4
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Use a URI ending in /v1/messages to identify the request as Anthropic Messages.
❷ Configure a provider that supports OpenAI Chat Completions. The plugin converts the Anthropic request before forwarding it.
❸ Specify the model name of the backend provider.
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: openai
auth:
header:
Authorization: "Bearer sk-xxx"
options:
model: gpt-4
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: anthropic-convert-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /v1/messages
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-plugin-config
Apply the configuration to your cluster:
kubectl apply -f anthropic-convert-ic.yaml
❶ Use a URI ending in /v1/messages to identify the request as Anthropic Messages.
❷ Configure a provider that supports OpenAI Chat Completions. The plugin converts the Anthropic request before forwarding it.
❸ Specify the model name of the backend provider.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: anthropic-convert-route
spec:
ingressClassName: apisix
http:
- name: anthropic-convert-route
match:
paths:
- /v1/messages
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: openai
auth:
header:
Authorization: "Bearer sk-xxx"
options:
model: gpt-4
Apply the configuration to your cluster:
kubectl apply -f anthropic-convert-ic.yaml
❶ Use a URI ending in /v1/messages to identify the request as Anthropic Messages.
❷ Configure a provider that supports OpenAI Chat Completions. The plugin converts the Anthropic request before forwarding it.
❸ Specify the model name of the backend provider.
Send a POST request to the route in Anthropic Messages API format:
curl "http://127.0.0.1:9080/v1/messages" -X POST \
-H "Content-Type: application/json" \
-H "x-api-key: ${BACKEND_API_KEY}" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "gpt-4",
"max_tokens": 1024,
"messages": [
{ "role": "user", "content": "What is 1+1?" }
]
}'
Although the request is sent in Anthropic format, it will be automatically converted to OpenAI format and forwarded to the backend. The response is converted back to Anthropic format:
{
"id": "msg_01XFDUDYJgAACzvnptvVoYEL",
"type": "message",
"role": "assistant",
"content": [
{
"type": "text",
"text": "1+1 equals 2."
}
],
"model": "gpt-4",
"stop_reason": "end_turn",
"usage": {
"input_tokens": 12,
"output_tokens": 8
}
}
This conversion covers common Anthropic Messages workflows: text messages, system prompts, streaming (SSE), and custom function tools. It converts the response back to Anthropic format.
The conversion supports a subset of the Anthropic Messages API, not an equivalent implementation. Some fields are approximated, and the plugin can drop unsupported fields without returning an error. See Protocol Reference for the field-level mapping, the release boundaries, and the known limitations.
If your client and backend both support the Anthropic Messages API natively, use Native Anthropic Messages API Pass-Through instead. That mode skips the conversion and preserves Anthropic-specific fields.
Native Anthropic Messages API Pass-Through
This example applies to API7 Enterprise version 3.9.8 and later and APISIX version 3.17.0 and later.
The following example demonstrates how to use the ai-proxy plugin to pass requests directly to an Anthropic backend using the native Anthropic Messages API format, without any protocol conversion. This is useful when both the client and backend use the Anthropic SDK natively.
The conversion example translates Anthropic client requests to OpenAI format and backend responses to Anthropic format. Native pass-through performs neither protocol transformation, so it preserves all Anthropic-specific fields including cache token usage (cache_creation_input_tokens, cache_read_input_tokens).
Obtain an Anthropic API key and save it to an environment variable:
export ANTHROPIC_API_KEY=sk-ant-your-api-key
Create a route with the ai-proxy plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-anthropic-native",
"uri": "/v1/messages",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "anthropic",
"auth": {
"header": {
"x-api-key": "$ANTHROPIC_API_KEY"
}
},
"options": {
"model": "claude-sonnet-4-20250514"
}
}
}
}
EOF
services:
- name: ai-proxy-anthropic-native-service
routes:
- name: ai-proxy-anthropic-native-route
uris:
- /v1/messages
methods:
- POST
plugins:
ai-proxy:
provider: anthropic
auth:
header:
x-api-key: ${ANTHROPIC_API_KEY}
options:
model: claude-sonnet-4-20250514
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-anthropic-native-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: anthropic
auth:
header:
x-api-key: sk-ant-your-api-key
options:
model: claude-sonnet-4-20250514
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ai-proxy-anthropic-native-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /v1/messages
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-anthropic-native-plugin-config
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-anthropic-native-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ai-proxy-anthropic-native-route
spec:
ingressClassName: apisix
http:
- name: ai-proxy-anthropic-native-route
match:
paths:
- /v1/messages
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: anthropic
auth:
header:
x-api-key: sk-ant-your-api-key
options:
model: claude-sonnet-4-20250514
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-anthropic-native-ic.yaml
Send a request using the Anthropic Messages API format:
curl -i "http://127.0.0.1:9080/v1/messages" -X POST \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{
"model": "claude-sonnet-4-20250514",
"messages": [
{"role": "user", "content": "Hello, Claude!"}
],
"max_tokens": 1024
}'
The request is forwarded directly to the Anthropic API without format conversion. The response is returned in native Anthropic format, preserving all provider-specific fields.
Proxy OpenAI Responses API
This example applies to API7 Enterprise version 3.9.8 and later and APISIX version 3.17.0 and later.
The following example demonstrates how to use the ai-proxy plugin to proxy OpenAI Responses API requests (POST /v1/responses). The Responses API is OpenAI's newer API format that supports built-in tools, web search, file search, and computer use.
Obtain an OpenAI API key and save it to an environment variable:
export OPENAI_API_KEY=sk-your-openai-api-key
Responses and Embeddings requests both contain input. Keep the /v1/responses URI suffix so that the plugin identifies this request as Responses instead of Embeddings. See Request Protocol Detection.
Create a route with the ai-proxy plugin:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-responses-api",
"uri": "/v1/responses",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4.1"
}
}
}
}
EOF
services:
- name: ai-proxy-responses-api-service
routes:
- name: ai-proxy-responses-api-route
uris:
- /v1/responses
methods:
- POST
plugins:
ai-proxy:
provider: openai
auth:
header:
Authorization: "Bearer ${OPENAI_API_KEY}"
options:
model: gpt-4.1
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-responses-api-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: openai
auth:
header:
Authorization: "Bearer sk-your-openai-api-key"
options:
model: gpt-4.1
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ai-proxy-responses-api-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /v1/responses
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-responses-api-plugin-config
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-responses-api-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ai-proxy-responses-api-route
spec:
ingressClassName: apisix
http:
- name: ai-proxy-responses-api-route
match:
paths:
- /v1/responses
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: openai
auth:
header:
Authorization: "Bearer sk-your-openai-api-key"
options:
model: gpt-4.1
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-responses-api-ic.yaml
Send a request using the OpenAI Responses API format:
curl -i "http://127.0.0.1:9080/v1/responses" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4.1",
"input": "Explain API gateways in one sentence."
}'
Send a streaming request:
curl "http://127.0.0.1:9080/v1/responses" -X POST \
--no-buffer \
-H "Content-Type: application/json" \
-d '{
"stream": true,
"input": "Count from one to five."
}'
❶ Disable cURL output buffering so that it displays each server-sent event as it arrives.
❷ Request a streaming response from OpenAI.
The stream contains typed events such as response.output_text.delta and ends with a response.completed event.
Plugins that explicitly support the Responses request structure can be used on the same route. These include ai-prompt-decorator, ai-prompt-guard, ai-rag, and ai-aliyun-content-moderation.
Each plugin handles instructions and input differently. Check its plugin page before adding it to a Responses route; plugins designed for Chat Completions do not automatically support the Responses format.
Proxy to AWS Bedrock
This example applies to API7 Enterprise version 3.9.12 and later and APISIX version 3.17.0 and later.
The following example demonstrates how to use the ai-proxy plugin to proxy requests to AWS Bedrock using the Converse API. Bedrock uses AWS SigV4 signing for authentication, so you need to provide IAM credentials instead of an API key header.
Obtain your AWS IAM credentials and save them to environment variables:
export AWS_ACCESS_KEY_ID=<your-aws-access-key-id>
export AWS_SECRET_ACCESS_KEY=<your-aws-secret-access-key>
Create a route with the ai-proxy plugin configured for Bedrock:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-bedrock",
"uri": "/bedrock/converse",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "bedrock",
"auth": {
"aws": {
"access_key_id": "$AWS_ACCESS_KEY_ID",
"secret_access_key": "$AWS_SECRET_ACCESS_KEY"
}
},
"provider_conf": {
"region": "us-east-1"
},
"options": {
"model": "anthropic.claude-3-haiku-20240307-v1:0"
}
}
}
}
EOF
services:
- name: ai-proxy-bedrock-service
routes:
- name: ai-proxy-bedrock-route
uris:
- /bedrock/converse
methods:
- POST
plugins:
ai-proxy:
provider: bedrock
auth:
aws:
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
provider_conf:
region: us-east-1
options:
model: anthropic.claude-3-haiku-20240307-v1:0
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: ai-proxy-bedrock-plugin-config
spec:
plugins:
- name: ai-proxy
config:
provider: bedrock
auth:
aws:
access_key_id: your-aws-access-key-id
secret_access_key: your-aws-secret-access-key
provider_conf:
region: us-east-1
options:
model: anthropic.claude-3-haiku-20240307-v1:0
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: ai-proxy-bedrock-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: Exact
value: /bedrock/converse
method: POST
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: ai-proxy-bedrock-plugin-config
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-bedrock-ic.yaml
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: ai-proxy-bedrock-route
spec:
ingressClassName: apisix
http:
- name: ai-proxy-bedrock-route
match:
paths:
- /bedrock/converse
methods:
- POST
plugins:
- name: ai-proxy
enable: true
config:
provider: bedrock
auth:
aws:
access_key_id: your-aws-access-key-id
secret_access_key: your-aws-secret-access-key
provider_conf:
region: us-east-1
options:
model: anthropic.claude-3-haiku-20240307-v1:0
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-bedrock-ic.yaml
The plugin uses the configured AWS credentials for SigV4 request signing.
Send a POST request to the route in Bedrock Converse format. The request URI must end with /converse:
curl "http://127.0.0.1:9080/bedrock/converse" -X POST \
-H "Content-Type: application/json" \
-d '{
"messages": [
{
"role": "user",
"content": [
{ "text": "Explain API gateways in one sentence." }
]
}
],
"inferenceConfig": {
"maxTokens": 256
}
}'
The plugin forwards the request to the configured Bedrock model and applies SigV4 signing automatically.
To use streaming, add "stream": true to the request body:
curl "http://127.0.0.1:9080/bedrock/converse" -X POST \
-H "Content-Type: application/json" \
-d '{
"stream": true,
"messages": [
{
"role": "user",
"content": [
{ "text": "Hello" }
]
}
]
}'
Streaming requests are routed to the /converse-stream endpoint and the binary AWS EventStream response is parsed and forwarded to the client.
Proxy to Selected Model using Request Body Parameter
The following example demonstrates how you can proxy requests to different models on the same URI, based on the user-specified model in the user requests. You will be using the post_arg.* variable to fetch the value of the request body parameter.
The example will use OpenAI and DeepSeek as the example LLM services. Obtain the OpenAI and DeepSeek API keys and save them to environment variables:
# replace with your API key
export OPENAI_API_KEY=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
export DEEPSEEK_API_KEY=sk-5e99f3e26abc40e75d80009a90e66
- Admin API
- ADC
- Ingress Controller
Create a route to the OpenAI API with the ai-proxy plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-openai-route",
"uri": "/anything",
"methods": ["POST"],
"vars": [[ "post_arg.model", "==", "openai" ]],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4"
}
}
}
}
EOF
❶ Set the route URI to be /anything.
❷ Match the route to requests where the body parameter model is set to openai.
Create another route /anything to the DeepSeek API with the ai-proxy plugin:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-deepseek-route",
"uri": "/anything",
"methods": ["POST"],
"vars": [[ "post_arg.model", "==", "deepseek" ]],
"plugins": {
"ai-proxy": {
"provider": "deepseek",
"auth": {
"header": {
"Authorization": "Bearer $DEEPSEEK_API_KEY"
}
},
"options": {
"model": "deepseek-chat"
}
}
}
}
EOF
❶ Set the route URI to be /anything, same as the previous route.
❷ Match the route to requests where the body parameter model is set to deepseek.
Create two routes with the ai-proxy plugin configured for different providers:
services:
- name: multi-model-service
routes:
- name: openai-route
uris:
- /anything
methods:
- POST
vars:
- - post_arg.model
- ==
- openai
plugins:
ai-proxy:
provider: openai
auth:
header:
Authorization: "Bearer ${OPENAI_API_KEY}"
options:
model: gpt-4
- name: deepseek-route
uris:
- /anything
methods:
- POST
vars:
- - post_arg.model
- ==
- deepseek
plugins:
ai-proxy:
provider: deepseek
auth:
header:
Authorization: "Bearer ${DEEPSEEK_API_KEY}"
options:
model: deepseek-chat
Synchronize the configuration to the gateway:
adc sync -f adc.yaml
❶ Set the route URI to be /anything.
❷ Match the route to requests where the body parameter model is set to openai.
❸ Set the route URI to be /anything, same as the previous route.
❹ Match the route to requests where the body parameter model is set to deepseek.
- Gateway API
- APISIX CRD
Body parameter matching is not supported in HTTPRoute. The supported matching mechanisms are path, method, headers, and queryParams. This example cannot be completed with Gateway API.
Create an ApisixRoute that matches requests based on the JSON request body field model:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: body-match-route
spec:
ingressClassName: apisix
http:
- name: openai
match:
paths:
- /anything
exprs:
- subject:
scope: Body
name: model
op: Equal
value: openai
upstreams:
- name: httpbin-external-domain
- name: deepseek
match:
paths:
- /anything
exprs:
- subject:
scope: Body
name: model
op: Equal
value: deepseek
upstreams:
- name: httpbin-external-domain
Apply the configuration to your cluster:
kubectl apply -f ai-proxy-body-match.yaml
Send a POST request to the route with model set to openai:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "openai",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You should receive a response similar to the following:
{
...,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}
Send a POST request to the route with model set to deepseek:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You should receive a response similar to the following:
{
...,
"model": "deepseek-chat",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The sum of 1 and 1 is 2. This is a basic arithmetic operation where you combine two units to get a total of two units."
},
"logprobs": null,
"finish_reason": "stop"
}
],
...
}
You can also configure post_arg.* to fetch nested request body parameter. For instance, if the request format is:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": {
"name": "openai"
},
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
You can configure the vars on the route to be [[ "post_arg.model.name", "==", "openai" ]].
For more information on the expressions, see APISIX Expressions.
Include LLM Information in Access Log
The following example demonstrates how you can log LLM request related information in the gateway's access log to improve analytics and audit. In addition to NGINX variables, the following variables are also available:
apisix_upstream_response_time: Time taken for the gateway to send the request to the upstream service and receive the full response, in milliseconds. Error responses returned by the LLM upstream are also recorded in milliseconds. Available from API7 Enterprise 3.8.8.request_type: Type of request, where the value could betraditional_http,ai_chat, orai_stream.llm_time_to_first_token: Duration from request sending to the first token received from the LLM service, in milliseconds. For an upstream error response, this is the duration until the error response was received. It remains0if the gateway could not reach the upstream.llm_model: LLM model name forwarded to the upstream LLM service.request_llm_model: LLM model name specified in the request.llm_prompt_tokens: Number of tokens in the prompt.llm_completion_tokens: Number of completion tokens in the response.llm_content_risk_level: Content risk level reported by an AI content moderation plugin. Available in APISIX from version 3.17.0.
The gateway's AI HTTP transport also populates the standard upstream variables upstream_addr, upstream_status, apisix_upstream_response_time, upstream_scheme, upstream_host, upstream_uri, and upstream_response_length.
These variables apply to streaming and non-streaming AI responses in API7 Enterprise from version 3.10.0 and APISIX from version 3.17.0. They are also populated for APISIX requests sent through the FFI client.
The following additional variables are available in API7 Enterprise from version 3.9.14 and APISIX from version 3.18.0:
llm_total_tokens: Total number of tokens used, including prompt and completion tokens.llm_stream: Whether the request was a streaming request, eithertrueorfalse.llm_has_tool_calls: Whether the LLM response contains tool calls, eithertrueorfalse.llm_tool_count: Number of tools provided in the request.llm_end_user_id: End-user identifier extracted from the request body, such asuser,safety_identifier, ormetadata.user_id.llm_cache_read_input_tokens: Number of prompt tokens served from the provider's prompt cache.llm_cache_creation_input_tokens: Number of prompt tokens written to the provider's prompt cache.llm_reasoning_tokens: Number of reasoning tokens used by reasoning models.
These variables are demonstrated in the access log format but are also available for use in logging plugins. In API7 Enterprise 3.9.18 and 3.10.5, and in APISIX 3.18.0, enabling logging.summaries adds them to the llm_summary object without the llm_ prefix. Values that were not produced for a request are omitted.
To record these values in access logs, add the LLM variables to the gateway access log format:
- Host or Docker
- Kubernetes (Helm)
Add or update this section in the gateway configuration file:
nginx_config:
http:
access_log_format: "$remote_addr - $remote_user [$time_local] $http_host \"$request_line\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $apisix_upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\" \"$apisix_request_id\" \"$request_type\" \"$llm_time_to_first_token\" \"$llm_model\" \"$request_llm_model\" \"$llm_prompt_tokens\" \"$llm_completion_tokens\" \"$llm_total_tokens\" \"$llm_stream\" \"$llm_has_tool_calls\" \"$llm_tool_count\" \"$llm_end_user_id\" \"$llm_cache_read_input_tokens\" \"$llm_cache_creation_input_tokens\" \"$llm_reasoning_tokens\""
Reload the gateway for configuration changes to take effect.
For the APISIX Helm chart, set the following values:
apisix:
nginx:
logs:
accessLogFormat: "$remote_addr - $remote_user [$time_local] $http_host \"$request_line\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $apisix_upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\" \"$apisix_request_id\" \"$request_type\" \"$llm_time_to_first_token\" \"$llm_model\" \"$request_llm_model\" \"$llm_prompt_tokens\" \"$llm_completion_tokens\" \"$llm_total_tokens\" \"$llm_stream\" \"$llm_has_tool_calls\" \"$llm_tool_count\" \"$llm_end_user_id\" \"$llm_cache_read_input_tokens\" \"$llm_cache_creation_input_tokens\" \"$llm_reasoning_tokens\""
For the API7 Gateway Helm chart, set the following values:
logs:
accessLogFormat: "$remote_addr - $remote_user [$time_local] $http_host \"$request_line\" $status $body_bytes_sent $request_time \"$http_referer\" \"$http_user_agent\" $upstream_addr $upstream_status $apisix_upstream_response_time \"$upstream_scheme://$upstream_host$upstream_uri\" \"$apisix_request_id\" \"$request_type\" \"$llm_time_to_first_token\" \"$llm_model\" \"$request_llm_model\" \"$llm_prompt_tokens\" \"$llm_completion_tokens\" \"$llm_total_tokens\" \"$llm_stream\" \"$llm_has_tool_calls\" \"$llm_tool_count\" \"$llm_end_user_id\" \"$llm_cache_read_input_tokens\" \"$llm_cache_creation_input_tokens\" \"$llm_reasoning_tokens\""
Then apply the values file with the chart used for this gateway release:
helm upgrade <release-name> <chart-name> -n <namespace> -f values.yaml
Now if you create a route following the Proxy to OpenAI example. Send a request like this:
curl "http://127.0.0.1:9080/anything" -X POST \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-3.5",
"messages": [
{ "role": "system", "content": "You are a mathematician" },
{ "role": "user", "content": "What is 1+1?" }
]
}'
Since the model in ai-proxy is gpt-4, the request will be forwarded to GPT-4 model and you will receive a response similar to the following:
{
...,
"model": "gpt-4-0613",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "1+1 equals 2.",
"refusal": null,
"annotations": []
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 23,
"completion_tokens": 8,
"total_tokens": 31,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
...
},
"service_tier": "default",
"system_fingerprint": null
}
In the gateway's access log, you should see a log entry similar to the following:
192.168.215.1 - - [29/Aug/2025:09:54:16 +0000] 127.0.0.1:9080 "POST /anything HTTP/1.1" 200 808 2.670 "-" "curl/8.6.0" - - 2670 "http://127.0.0.1:9080" "6526bf5c961b6e6bb8cfcb66486f02dc" "ai_chat" "2670" "gpt-4" "gpt-3.5" "23" "8" "31" "false" "false" "0" "" "0" "0" "0"
The access log entry shows an upstream response time and time to first token of 2670 milliseconds. The request uses the ai_chat type, requests gpt-3.5, and is forwarded to gpt-4. It uses 23 prompt tokens, 8 completion tokens, and 31 total tokens.
The remaining values show a non-streaming request with no tool calls, provided tools, end-user identifier, prompt-cache tokens, or reasoning tokens.
Send Request Log to Logger
The following example demonstrates how you can log request and request information, including LLM model, token, and payload, and push them to a logger. Before proceeding, you should first set up a logger, such as Kafka. See kafka-logger for more information.
- Admin API
- ADC
- Ingress Controller
Create a route to your LLM service and configure logging details as such:
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
--data-binary @- <<EOF
{
"id": "ai-proxy-openai-route",
"uri": "/anything",
"methods": ["POST"],
"plugins": {
"ai-proxy": {
"provider": "openai",
"auth": {
"header": {
"Authorization": "Bearer $OPENAI_API_KEY"
}
},
"options": {
"model": "gpt-4"
},
"logging": {
"summaries": true,
"payloads": true
}
},
"kafka-logger": {
"brokers": [
{
"host": "127.0.0.1",
"port": 9092
}
],
"kafka_topic": "test2",
"key": "key1",
"batch_max_size": 1
}
}
}
}
EOF
❶ Log request LLM model, duration, request and response tokens.
❷ Log request and response payload.
❸ Update with your Kafka address.
❹ Update with your Kafka topic.
❺ Update with your Kafka key.