The Stav API speaks both OpenAI and Anthropic contracts. Pick the SDK you already use, point it at https://api.stav.ai/v1, and you're done.
What you'll need
- A Stav API key. If you don't have one, follow Authentication & API keys first — it takes about two minutes.
- Python 3.9+ or Node 18+ or
curl. Pick whichever you're most comfortable in.
Your first completion
curl
curl https://api.stav.ai/v1/chat/completions \
-H "Authorization: Bearer $STAV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen3-32b",
"messages": [
{"role": "user", "content": "In one sentence, what is EU sovereignty for AI?"}
]
}'
You should get a JSON response back with choices[0].message.content containing the answer. The response also carries an X-Stav-Sovereignty-Tier header — for qwen3-32b it will read sovereign, meaning the request ran end-to-end on Stav-hosted infrastructure in the EU.
Python — OpenAI SDK
from openai import OpenAI
client = OpenAI(
base_url="https://api.stav.ai/v1",
api_key="hm_live_...", # or read from STAV_API_KEY env var
)
response = client.chat.completions.create(
model="qwen3-32b",
messages=[
{"role": "user", "content": "In one sentence, what is EU sovereignty for AI?"}
],
)
print(response.choices[0].message.content)
If you've been using openai.com already, the only thing that changes is the base_url. Every other call — streaming, tools, structured output, embeddings — works the same way.
TypeScript — Anthropic SDK
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://api.stav.ai/v1",
apiKey: process.env.STAV_API_KEY,
});
const message = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [
{ role: "user", content: "In one sentence, what is EU sovereignty for AI?" },
],
});
console.log(message.content);
For claude-* models, Stav proxies your request verbatim to Anthropic — all features including cache_control, extended thinking, and beta flags work as-is. For every other catalogue model, Stav translates the Anthropic Messages contract to the OpenAI Chat Completions contract under the hood — same call from your side, different upstream.
Streaming
Pass stream: true (OpenAI) or stream: true (Anthropic). Stav forwards the server-sent events from the upstream in the exact format your SDK expects.
stream = client.chat.completions.create(
model="qwen3-32b",
messages=[{"role": "user", "content": "Tell me a short story about Rjukan."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="", flush=True)
Smart Router
Set model="auto" and Stav picks the right model for each request based on prompt classification (complexity, domain, sensitivity) and your team's routing policy. The response includes a routing_metadata field showing what was picked and why.
response = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Refactor this Python function..."}],
)
print(response.routing_metadata.selected_model) # e.g. "llama-4-maverick:precision"
print(response.routing_metadata.reason)
# "complexity=high, code=true, sensitive=false → llama-4-maverick:precision"
Next steps
- Authentication & API keys — scopes, rotation, the IP allowlist.
- Sovereignty — what the three tiers (
sovereign,routed-commercial, ) actually guarantee.