Docs · Start here
Quickstart
This page takes you from an API key to a streamed reply. Allow about 5 minutes.
1. Get an API key#
You need an account on the service and an API key for it. The key looks like shvia_usr_<id>_<secret>, it is valid for 365 days, and it is shown once, when you create it.
Create it in the app: open your account, go to the API key section and choose to generate a key. The app asks for your password. Authentication explains the alternatives, and what to do if the option is missing: API access is enabled per account group by the operator, and a new account may not have it yet.
Keep the key out of source control. Put it in the environment:
export SHVIA_URL="https://ai.shvia.org"
export SHVIA_API_KEY="paste the key here"2. List the models#
curl -s "$SHVIA_URL/v1/models" \
-H "Authorization: Bearer $SHVIA_API_KEY"{
"object": "list",
"data": [
{ "id": "claude-sonnet-4-6@anthropic", "object": "model", "created": 1767225600, "owned_by": "shvia" },
{ "id": "gpt-4o@openai", "object": "model", "created": 1767225600, "owned_by": "shvia" }
]
}A model id is <model>@<server>, where the server is a cloud provider or one of the operator's own servers. Use the id exactly as listed, and keep it in a variable:
export SHVIA_MODEL="claude-sonnet-4-6@anthropic"3. Send a message#
curl -s "$SHVIA_URL/v1/chat/completions" \
-H "Authorization: Bearer $SHVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$SHVIA_MODEL"'",
"messages": [{ "role": "user", "content": "Say hello in one short sentence." }]
}'{
"id": "chatcmpl-0b0f3c0e-6c4e-4d6f-9a0e-2f3b1d7a9c11",
"object": "chat.completion",
"created": 1767225600,
"model": "claude-sonnet-4-6@anthropic",
"choices": [
{ "index": 0, "message": { "role": "assistant", "content": "Hello! Nice to meet you." }, "finish_reason": "stop" }
],
"usage": { "prompt_tokens": 14, "completion_tokens": 8, "total_tokens": 22 }
}Always set Content-Type: application/json. Without it the body is not read as JSON and the request fails validation.
4. Stream the reply#
Add "stream": true and tell curl not to buffer with -N:
curl -sN "$SHVIA_URL/v1/chat/completions" \
-H "Authorization: Bearer $SHVIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "'"$SHVIA_MODEL"'",
"stream": true,
"messages": [{ "role": "user", "content": "Count from 1 to 3." }]
}'data: {"id":"chatcmpl-…","object":"chat.completion.chunk","created":1767225600,"model":"claude-sonnet-4-6@anthropic","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","created":1767225600,"model":"claude-sonnet-4-6@anthropic","choices":[{"index":0,"delta":{"content":"1, 2, 3"},"finish_reason":null}]}
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","created":1767225600,"model":"claude-sonnet-4-6@anthropic","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]5. Use an SDK#
The official OpenAI SDKs work by pointing them at the gateway. The base URL includes /v1.
import os
from openai import OpenAI
client = OpenAI(
base_url=os.environ["SHVIA_URL"] + "/v1",
api_key=os.environ["SHVIA_API_KEY"],
)
reply = client.chat.completions.create(
model=os.environ["SHVIA_MODEL"],
messages=[{"role": "user", "content": "Say hello in one short sentence."}],
)
print(reply.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
baseURL: process.env.SHVIA_URL + "/v1",
apiKey: process.env.SHVIA_API_KEY,
});
const reply = await client.chat.completions.create({
model: process.env.SHVIA_MODEL,
messages: [{ role: "user", content: "Say hello in one short sentence." }],
});
console.log(reply.choices[0].message.content);Things to know before you build#
- Use full model ids, and hold the key. A name with no
@providerthat the gateway does not know is not rejected: it is answered by another model, and themodelfield of the response shows it. A cloud model for which you have no key can be replaced by your default model with no sign at all. See models. - Mind the request limit. The default is 20 requests per minute per account, one counter for all the
/v1endpoints and some of the others. ReadX-RateLimit-Remainingon each response. See rate limits and quotas. - Message
contentis a string. Arrays of content parts, as used for images, are rejected with422on chat completions. - Sampling parameters depend on the model.
temperatureandmax_tokensare applied to models whosedriverisollama, and ignored for the others, cloud models included. See chat completions. - Cloud models need your provider key. Add it once in your account. See providers and your own keys.
Next steps#
- Authentication and API keys
- Chat completions, including tool calls
- Collections: let a model answer from your own documents
- Connect your tools: Claude Code, Cline, Continue and others
- Errors and rate limits and quotas