OpenAI-Compatible Gateway
Route your existing OpenAI SDK calls through AxonFlow by changing a single line of code. AxonFlow enforces policies, records audit logs, and tracks token usage — then forwards the request to your upstream provider.
Your app → POST /v1/chat/completions (AxonFlow) → Policy check → OpenAI API → Audit → Response
Quick Start
Python
import os
from openai import OpenAI
client = OpenAI(
api_key="any-value", # AxonFlow auth (community mode: any value)
base_url="http://localhost:8080/v1", # Point at AxonFlow instead of OpenAI
default_headers={
"X-Provider-Key": os.environ["OPENAI_API_KEY"] # Your real OpenAI key
}
)
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "What is 2+2?"}],
max_tokens=100
)
print(response.choices[0].message.content) # "4"
print(response.usage.total_tokens) # e.g., 21
TypeScript
import OpenAI from 'openai';
const client = new OpenAI({
apiKey: 'any-value',
baseURL: 'http://localhost:8080/v1',
defaultHeaders: {
'X-Provider-Key': process.env.OPENAI_API_KEY!
}
});
const response = await client.chat.completions.create({
model: 'gpt-4o-mini',
messages: [{ role: 'user', content: 'What is 2+2?' }],
max_tokens: 100
});
console.log(response.choices[0].message.content); // "4"
console.log(response.usage?.total_tokens); // e.g., 21
curl
curl -X POST http://localhost:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "X-Provider-Key: $OPENAI_API_KEY" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role": "user", "content": "What is 2+2?"}],
"max_tokens": 100
}'
What Happens Behind the Scenes
When your request hits /v1/chat/completions, AxonFlow:
- Authenticates the request (same auth as all AxonFlow endpoints)
- Evaluates policies against the message content — PII detection, SQL injection blocking, dangerous query prevention, compliance rules
- Blocks the request if any policy triggers a deny (returns an OpenAI-compatible error)
- Forwards the request to the upstream provider using your
X-Provider-Key - Records audit — model, provider, token usage, cost estimate, latency, policy decision
- Returns the provider's response unchanged, plus AxonFlow headers
The response you receive is identical to what OpenAI would return directly, with two additional headers:
| Header | Description |
|---|---|
X-AxonFlow-Decision-Id | UUID for this request in audit logs |
X-AxonFlow-Trace-Id | W3C-compatible 32-hex trace ID for observability |
Provider Key
Pass your upstream provider API key in the X-Provider-Key header. AxonFlow does not store this key — it is forwarded to the upstream provider for the duration of the request only.
# Python: set via default_headers
client = OpenAI(
base_url="http://localhost:8080/v1",
default_headers={"X-Provider-Key": os.environ["OPENAI_API_KEY"]}
)
# Or per-request via extra_headers
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[...],
extra_headers={"X-Provider-Key": os.environ["OPENAI_API_KEY"]}
)
If the header is missing, AxonFlow returns a clear error:
{
"error": {
"message": "X-Provider-Key header is required. Pass your upstream provider API key in this header.",
"type": "invalid_request_error",
"code": "missing_provider_key"
}
}
Policy Enforcement
AxonFlow evaluates the same policy categories as Gateway Mode and Decision Mode:
- PII detection — SSN, credit cards, Aadhaar, PAN, email, phone numbers
- SQL injection — UNION-based injection, tautology attacks, stacked queries
- Dangerous queries — attempts to access system tables, credentials, admin functions
- Compliance — RBI, SEBI, EU AI Act, MAS FEAT framework rules
When a policy denies a request, AxonFlow returns an OpenAI-compatible error that the SDK parses correctly:
from openai import BadRequestError
try:
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "My SSN is 123-45-6789"}]
)
except BadRequestError as e:
print(e.status_code) # 400
print(e.body)
# {'error': {'message': 'Request blocked by policy: Social Security Number detected',
# 'type': 'policy_violation', 'code': 'policy_denied'}}
The error envelope shape ({error: {message, type, code}}) matches OpenAI's, so the OpenAI SDK parses it as BadRequestError and your existing error handling works unchanged. The type and code values (policy_violation, policy_denied) are AxonFlow-specific — check for them explicitly to branch on policy denials.
Authentication
The endpoint uses the same authentication as all AxonFlow endpoints:
| Mode | Authentication |
|---|---|
| Community (self-hosted) | No auth required — api_key can be any value |
| Enterprise (self-hosted) | Basic Auth with client_id:client_secret |
| Community SaaS (try.getaxonflow.com) | Registration credentials |
In enterprise mode, set your AxonFlow credentials as the api_key:
client = OpenAI(
api_key="your-axonflow-client-id:your-axonflow-client-secret",
base_url="https://your-axonflow-host/v1",
default_headers={"X-Provider-Key": os.environ["OPENAI_API_KEY"]}
)
Audit and Cost Tracking
Every request is recorded in the llm_call_audits table with:
| Field | Description |
|---|---|
provider | Upstream provider (e.g., openai) |
model | Model used (e.g., gpt-4o-mini) |
prompt_tokens | Input tokens |
completion_tokens | Output tokens |
total_tokens | Total tokens |
estimated_cost_usd | Estimated cost based on published pricing |
latency_ms | Provider response time |
metadata.verdict | Policy decision (allow or deny) |
metadata.decision_id | Correlation ID (matches X-AxonFlow-Decision-Id header) |
Denied requests are also audited with verdict: "deny" and zero token counts (the request never reached the provider).
Comparison with Other Modes
| Feature | OpenAI-Compatible Gateway | Proxy Mode | Gateway Mode | Decision Mode |
|---|---|---|---|---|
| SDK change | baseURL only | AxonFlow SDK | AxonFlow SDK | Custom PEP |
| Request format | OpenAI native | AxonFlow format | AxonFlow format | AxonFlow format |
| Provider call | AxonFlow forwards | AxonFlow forwards | Your code calls | Your code calls |
| Policy enforcement | Pre-request | Pre-request | Pre-check | Pre-request |
| Audit | Automatic | Automatic | Two-step (pre-check + audit) | Per-decision |
| Streaming | Not yet supported | Supported | N/A | N/A |
| Custom policies | System policies | System + tenant | System policies | System policies |
Choose OpenAI-Compatible Gateway when you already use the OpenAI SDK and need policy enforcement + audit without changing your request format. No new SDK to learn.
Choose Proxy Mode when you need tenant-specific custom policies or your workflow requires AxonFlow's multi-step execution model.
Limitations
This is the first release of the OpenAI-Compatible Gateway:
- Non-streaming only. Requests with
stream: truereturn HTTP 400 with a clear error message. Streaming support is planned for a future release. - Caller-supplied provider key. You pass your API key in the
X-Provider-Keyheader. Server-side provider key management is planned. - OpenAI routing only. This release routes every request to OpenAI regardless of the
modelvalue. Model prefixes (gpt-,o1,o3,o4,chatgpt-) all map toapi.openai.com. Anthropic, Gemini, and Bedrock routing are planned. - No upstream header passthrough. AxonFlow forwards only the request body. Provider-specific headers in your request (
OpenAI-Beta,OpenAI-Organization,OpenAI-Project) are not forwarded — pass equivalent configuration in the request body where the provider supports it. - System policies only. Custom tenant policies created in the Portal UI require Proxy Mode.
- Chat Completions only. The
/v1/chat/completionsendpoint is supported. Other OpenAI endpoints (embeddings, images, audio) are not proxied.
Troubleshooting
"X-Provider-Key header is required"
Pass your upstream provider API key in the X-Provider-Key header. See the Provider Key section.
"Streaming is not supported in this release"
Remove stream: true from your request. Streaming support is planned for a future release.
Upstream provider returns an error
If your provider key is invalid or the model doesn't exist, the upstream error is forwarded to your SDK as-is. Check the error message — it comes directly from the provider.
Policy denials
If your request is blocked, the error body contains the policy violation reason. Adjust your prompt to avoid the detected pattern, or configure your AxonFlow deployment's policy actions (PII_ACTION, SQLI_ACTION) if the detection is too strict for your use case.
