If you already call OpenAI's API with the official SDK, the migration to Stav is two lines of configuration. The Stav API speaks the OpenAI Chat Completions, Embeddings, and Models contracts verbatim — streaming, tool calling, structured output, the lot.
The change
Python
from openai import OpenAI
client = OpenAI(
base_url="https://api.stav.ai/v1", # ← was openai.com
api_key=os.environ["STAV_API_KEY"], # ← was OPENAI_API_KEY
)
Node / TypeScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.stav.ai/v1", // ← was openai.com
apiKey: process.env.STAV_API_KEY, // ← was OPENAI_API_KEY
});
Every other call — chat.completions.create, embeddings.create, models.list, streaming, tools, response_format, parallel_tool_calls — works identically.
Model identifiers
OpenAI's model names (gpt-4o, gpt-4o-mini, o1-preview, text-embedding-3-large) are catalogued on Stav under the openai/ prefix in the catalogue browser, but in the API you can refer to them by their original names too — Stav resolves both forms:
client.chat.completions.create(model="gpt-4o", messages=[...]) # works
client.chat.completions.create(model="openai/gpt-4o", messages=[...]) # also works
client.chat.completions.create(model="gpt-4o-mini:fast", messages=[...]) # tier-suffixed
To call sovereign-tier models instead of routed-commercial OpenAI, change the model identifier:
client.chat.completions.create(model="qwen3-32b", messages=[...]) # sovereign
client.chat.completions.create(model="auto", messages=[...]) # Smart Router
client.chat.completions.create(model="auto", messages=[...], # sovereign-only
extra_body={"sovereignty_required": True})
The catalogue at /v1/public/models lists every identifier with its sovereignty tier and pricing.
What's identical
What's different
A small set of Stav-specific extensions sit on top of the OpenAI contract. They're additive — your existing code keeps working — and you opt into each one explicitly.
Sovereignty tier on every response
Every response carries an X-Stav-Sovereignty-Tier header (sovereign / routed-commercial / byo). The SDK doesn't expose response headers directly, so to read it:
response = client.chat.completions.with_raw_response.create(
model="auto", messages=[{"role": "user", "content": "..."}],
)
tier = response.headers["X-Stav-Sovereignty-Tier"]
parsed = response.parse()
print(tier, parsed.choices[0].message.content)
For request-tracing, X-Stav-Selected-Model and X-Request-Id are also on every response.
model="auto" — Smart Router
Set the model to auto and Stav picks per request based on your team's routing policy. See Smart Router for the full mechanics. The response includes X-Stav-Selected-Model so you know what actually ran.
:fast / :precision tier suffix
Append :fast or :precision to any model identifier to lock the inference tier. See Tier suffix. Defaults to :precision for explicit model names, router-decided for auto.
Sovereign built-in tools
The tools array accepts stav.*-prefixed function names that execute server-side on Stav infrastructure. The model invocation, the tool execution, and the result all stay inside a single HTTP request from your side. See Built-in tools.
client.chat.completions.create(
model="auto",
messages=[...],
tools=[{"type": "function", "function": {"name": "stav.web_search"}}],
)
extra_body for Stav-specific knobs
The OpenAI SDK passes anything in extra_body straight to the API. Stav uses this for parameters that don't have a direct OpenAI counterpart:
client.chat.completions.create(
model="auto",
messages=[...],
extra_body={
"sovereignty_required": True, # hard-constrain to sovereign-tier
"stav_tools": ["web_search"], # shorthand for tools array
"max_tool_iterations": 3, # cap for in-flight tool loops
},
)
Migrating a real codebase — checklist
Known compatibility gaps
A handful of OpenAI-specific features don't translate. The honest list:
- Assistants API and Threads. Not supported. Use Built-in tools (
stav.file_searchis the file-search equivalent) plus your own conversation-state management. - Realtime API (voice). Roadmap, not shipped. Inference is text + vision today.
If your codebase uses any of these and you need a migration path, open a ticket — most teams find a sovereign-tools rewrite is cleaner than a feature-by-feature port.
Next steps
- Anthropic SDK migration — if you're on the Anthropic SDK instead.
- Smart Router — the biggest cost lever after the base-URL switch.
- API reference — every parameter Stav supports, annotated.