Skip to content
GitHubOpen source
Product
Docs
Solutions
IndustriesAll industries
CompareCompare all AI data-leak tools
Benchmarks
GitHubApache-2.0

Gateway mode

In gateway mode, Shadow acts as an explicit reverse proxy. You change the base URL of your SDK or tool, and nothing else:

http://127.0.0.1:8877/gw/<route>/<path> → <route base>/<path>

For example, http://127.0.0.1:8877/gw/openai/v1/chat/completions is forwarded to https://api.openai.com/v1/chat/completions. Query strings are kept. Your API key travels in the usual header and is passed through to the provider.

No certificate is involved: the hop from your app to Shadow is plain HTTP on loopback, and Shadow connects to the provider over TLS.

RouteUpstream baseBase URL for OpenAI-style SDKs
openaihttps://api.openai.comhttp://127.0.0.1:8877/gw/openai/v1
anthropichttps://api.anthropic.comhttp://127.0.0.1:8877/gw/anthropic (Anthropic SDK)
openrouterhttps://openrouter.ai/apihttp://127.0.0.1:8877/gw/openrouter/v1
gemini, googlehttps://generativelanguage.googleapis.comhttp://127.0.0.1:8877/gw/gemini
mistralhttps://api.mistral.aihttp://127.0.0.1:8877/gw/mistral/v1
groqhttps://api.groq.com/openaihttp://127.0.0.1:8877/gw/groq/v1
togetherhttps://api.together.xyzhttp://127.0.0.1:8877/gw/together/v1
deepseekhttps://api.deepseek.comhttp://127.0.0.1:8877/gw/deepseek/v1
xaihttps://api.x.aihttp://127.0.0.1:8877/gw/xai/v1
coherehttps://api.cohere.comhttp://127.0.0.1:8877/gw/cohere
perplexityhttps://api.perplexity.aihttp://127.0.0.1:8877/gw/perplexity
fireworkshttps://api.fireworks.ai/inferencehttp://127.0.0.1:8877/gw/fireworks/v1
cerebrashttps://api.cerebras.aihttp://127.0.0.1:8877/gw/cerebras/v1

shadow hosts prints the routes in effect, including your own.

Add routes for Azure OpenAI, AWS Bedrock (API-key auth), a self-hosted model server or an internal LLM gateway under [proxy.routes]. A custom route with the same name as a built-in overrides it.

[proxy.routes]
azure = "https://my-resource.openai.azure.com"
bedrock = "https://bedrock-runtime.eu-central-1.amazonaws.com"
llm = "https://llm.internal.example.com"

http://127.0.0.1:8877/gw/azure/openai/deployments/gpt-4o/chat/completions?api-version=2024-10-21 then goes to your Azure resource.

from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8877/gw/openai/v1") # api_key from OPENAI_API_KEY
reply = client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Summarise this ticket from jane@acme.com: card declined twice"}],
)
print(reply.choices[0].message.content) # mentions jane@acme.com, the provider never saw it

The Anthropic SDKs append /v1/messages themselves, so the base URL stops at the route.

import anthropic
client = anthropic.Anthropic(base_url="http://127.0.0.1:8877/gw/anthropic")
msg = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=512,
messages=[{"role": "user", "content": "Write a short note to Jane Doe about Project Falcon"}],
)
print(msg.content[0].text)

OpenRouter speaks the OpenAI protocol, so use the OpenAI SDK with the openrouter route:

from openai import OpenAI
import os
client = OpenAI(
base_url="http://127.0.0.1:8877/gw/openrouter/v1",
api_key=os.environ["OPENROUTER_API_KEY"],
)
Terminal window
curl "http://127.0.0.1:8877/gw/gemini/v1beta/models/gemini-2.5-flash:generateContent" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contents":[{"parts":[{"text":"Write to jane@acme.com about the Acme GmbH renewal"}]}]}'

With the Google Gen AI SDK, set the base URL through its HTTP options (http_options={"base_url": "http://127.0.0.1:8877/gw/gemini"} in Python).

Besides /gw/..., the same port serves:

PathReturns
/ or /shadow/statusJSON status: version, persona region/country/company/hostname, vault stats, routes, CA fingerprint
/healthzok
/proxy.pacPAC file for proxy mode
/shadow/ca.pemThe local CA certificate

Errors from Shadow itself, such as an unknown route, are returned as OpenAI-style JSON ({"error": {"message": ..., "type": "shadow_error"}}), so SDKs surface them cleanly.

Frequently asked questions

Does gateway mode need a certificate?

No. The hop from your app to Shadow is plain HTTP on loopback, and Shadow connects to the provider over TLS.

What happens to my API key?

It travels in the usual header and is passed through to the provider unchanged. Shadow masks the content of the request, not your credentials.

Does streaming work through the gateway?

Yes. Streamed responses are restored as they arrive, including fakes split across events and tool-call arguments.

Why do I get a 404 from Anthropic through the gateway?

The Anthropic SDKs append /v1/messages themselves, so their base URL must stop at the route: http://127.0.0.1:8877/gw/anthropic. OpenAI-style SDKs use /gw/openai/v1.