Quickstart
Get access, create a key, and send your first request with the OpenAI SDK or curl.
Stav is an OpenAI- and Anthropic-compatible inference gateway. You keep the SDK you already use and change two things: the base URL and the key.
1. Get access
Sign up at stav.ai/signup. Access is granted from the waitlist; once your account is enabled you land in Your workspace.
Inference is paid from your workspace's prepaid credit wallet. Top up under Billing in the account menu (your avatar) before sending traffic. See Credits and billing.
2. Create an API key
Open Your workspace → Connect → API keys and create a key. It is shown once — copy it then.
export STAV_API_KEY="sk_stav_live_..."
Check it works. This call costs nothing:
curl https://api.stav.ai/v1/auth/validate \
-H "Authorization: Bearer $STAV_API_KEY"
Key types, scopes and rotation: Authentication & API keys.
3. Send a request
Base URL: https://api.stav.ai/v1
curl
curl https://api.stav.ai/v1/chat/completions \
-H "Authorization: Bearer $STAV_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "auto",
"messages": [{"role": "user", "content": "Say hello in Norwegian."}]
}'
Python (OpenAI SDK)
import os
from openai import OpenAI
client = OpenAI(
api_key=os.environ["STAV_API_KEY"],
base_url="https://api.stav.ai/v1",
)
resp = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Say hello in Norwegian."}],
)
print(resp.choices[0].message.content)
print("served by:", resp
TypeScript (OpenAI SDK)
import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.STAV_API_KEY,
baseURL: "https://api.stav.ai/v1",
});
const resp = await client.chat.completions.create({
model: "auto",
messages: [{ role: "user", content: "Say hello in Norwegian." }],
});
Anthropic SDK
POST /v1/messages speaks the Anthropic wire format. The SDK sends x-api-key, which Stav accepts.
import os
from anthropic import Anthropic
client = Anthropic(
api_key=os.environ["STAV_API_KEY"],
base_url="https://api.stav.ai", # no /v1 — the SDK adds it
)
msg = client.messages.create(
model="anthropic/claude-sonnet-4-5",
max_tokens=512,
messages=[{"role": "user", "content": "Say hello in Norwegian."}],
)
print(msg.content[0].text)
4. Choose a model
The model field takes:
| Value | Meaning |
|---|---|
auto | The Smart Router picks, using your workspace's default Router |
@workspace/router | A named Router your workspace created in Your workspace → Connect → Routers |
creator/model | This model; Stav picks the Provider Endpoint |
creator/model/provider | This model on one Inference Provider |
Details in Models.
5. Stream
stream = client.chat.completions.create(
model="auto",
messages=[{"role": "user", "content": "Write a haiku about fjords."}],
stream=True,
stream_options={"include_usage": True},
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].
6. See what happened
Every response carries X-Stav-* headers: the model and Inference Provider that served it, the sovereignty level and the routing reason. See Response headers. Each request also appears in Your workspace → Monitor → Request log.
Surfaces
| Endpoint | Scope |
|---|---|
POST /v1/chat/completions | inference:chat |
POST /v1/responses | inference:chat |
POST /v1/messages, POST /v1/messages/count_tokens | inference:messages |
POST /v1/embeddings | inference:embeddings |
POST /v1/audio/transcriptions | inference:audio |
POST /v1/audio/speech | inference:audio |
POST /v1/decisions | inference:decisions |
GET /v1/models, GET /v1/models/{id} | inference:models |
Unknown or unsupported request parameters are refused with a 400 that names them, not silently left out. See Request parameters.
Next
- Try it in the Playground first, then copy the request as code
- Smart Router
- Sovereignty
- Errors