ShvIA

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:

bash
export SHVIA_URL="https://ai.shvia.org"
export SHVIA_API_KEY="paste the key here"

2. List the models#

bash
curl -s "$SHVIA_URL/v1/models" \
  -H "Authorization: Bearer $SHVIA_API_KEY"
json
{
  "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:

bash
export SHVIA_MODEL="claude-sonnet-4-6@anthropic"

3. Send a message#

bash
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." }]
  }'
json
{
  "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:

bash
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." }]
  }'
sse
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.

python
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)
javascript
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 @provider that the gateway does not know is not rejected: it is answered by another model, and the model field 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 /v1 endpoints and some of the others. Read X-RateLimit-Remaining on each response. See rate limits and quotas.
  • Message content is a string. Arrays of content parts, as used for images, are rejected with 422 on chat completions.
  • Sampling parameters depend on the model. temperature and max_tokens are applied to models whose driver is ollama, 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#