Chat Completions API
The /v1/chat/completions endpoint is a drop-in replacement for OpenAI's chat API. Use any OpenAI-compatible SDK against any provider's model.
POST /v1/chat/completions accepts the OpenAI chat-completions request shape and
forwards it to one of your enabled upstreams. Use it as a drop-in replacement:
point your base_url at https://api.ada.ai/v1 and use your proxy key
(sk-rc-…) as the API key.
Authentication
Send the proxy key in the Authorization header (or X-API-Key):
Authorization: Bearer sk-rc-...Never use a Stytch session JWT or an admin token on /v1/*. See
API keys.
Request
curl https://api.ada.ai/v1/chat/completions \
-H "Authorization: Bearer sk-rc-..." \
-H "Content-Type: application/json" \
-d '{
"model": "swiss-ai/Apertus-70B-Instruct-2509",
"messages": [
{ "role": "system", "content": "You are a concise assistant." },
{ "role": "user", "content": "Explain routing in one sentence." }
],
"max_tokens": 200
}'The body follows OpenAI's schema. The fields that matter:
| Field | Required | Notes |
|---|---|---|
model | yes | Must match a model ID from one of your enabled upstreams. See Models & routing. No silent substitution — a missing model is an error. |
messages | yes | OpenAI message array (system / user / assistant / tool). |
max_tokens | no | Cap on output tokens. |
temperature, top_p | no | Sampling. |
stream | no | true returns SSE chunks. |
tools, tool_choice | no | OpenAI-style function calling. |
stop | no | Stop sequences. |
Response
A standard OpenAI chat-completion object:
{
"id": "chatcmpl-...",
"object": "chat.completion",
"model": "swiss-ai/Apertus-70B-Instruct-2509",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "Ada AI tries the highest-priority upstream that serves a model, failing over on 5xx." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 24, "completion_tokens": 19, "total_tokens": 43 }
}Streaming
Set "stream": true to receive Server-Sent Events in OpenAI's format
(data: {chunk} lines, terminated by data: [DONE]):
curl https://api.ada.ai/v1/chat/completions \
-H "Authorization: Bearer sk-rc-..." \
-H "Content-Type: application/json" \
-d '{
"model": "glm-4.7",
"stream": true,
"messages": [{"role": "user", "content": "Count to five."}]
}'data: {"choices":[{"delta":{"content":"1"}, ...}]}
data: {"choices":[{"delta":{"content":"2"}, ...}]}
...
data: [DONE]Tool calls
OpenAI-style function calling is passed through. The proxy does not invent or modify tool definitions.
curl https://api.ada.ai/v1/chat/completions \
-H "Authorization: Bearer sk-rc-..." \
-H "Content-Type: application/json" \
-d '{
"model": "Qwen/Qwen3.6-35B-A3B-FP8",
"messages": [{"role": "user", "content": "What is the weather in Zurich?"}],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"parameters": { "type": "object", "properties": { "city": { "type": "string" } } }
}
}]
}'Which model do I send?
The model value must exactly match an ID your key's owner has enabled. To see
what's available:
curl https://api.ada.ai/v1/models \
-H "Authorization: Bearer sk-rc-..."See Models & routing for how the proxy chooses among upstreams that expose the same model, Errors for the full status-code reference, and Coding agents to drive Pi and OpenCode against this endpoint.
Using reasoning models
Some models on Ada AI (for example Qwen/Qwen3.6-35B-A3B-FP8 and the
*-thinking variants) return a reasoning_content field alongside content.
To turn thinking off for Qwen-family models, send
chat_template_kwargs: { "enable_thinking": false } — this makes responses
faster and cheaper when you don't need the chain of thought:
{
"model": "Qwen/Qwen3.6-35B-A3B-FP8",
"messages": [{"role": "user", "content": "Hi"}],
"chat_template_kwargs": { "enable_thinking": false }
}