Documentation
Quickstart, providers, modes, encryption internals, and the API reference, everything to get the most out of sarmalink.
Quickstart
Get from zero to your first answer in under two minutes. Sign in with a magic link, create your encryption passphrase, and paste a single free-tier provider key.
- 1Sign in with your email, no password to remember.
- 2Create a passphrase. It encrypts everything locally.
- 3Add one free key — any provider unlocks every mode it can serve.
- 4Start chatting. Add more keys anytime in Settings.
Providers
sarmalink routes across 17 OpenAI-compatible providers. Each has a generous free tier. Any single key enables every mode its provider can serve; extra keys deepen the failover ladder.
| Provider | Free tier | Unlocks |
|---|---|---|
| Groq | 14,400 requests/day, 30 RPM | Smart, Reasoner, Live, Fast, Coder, Vision |
| SambaNova | Frontier model, generous daily quota | Smart, Reasoner, Live, Fast, Coder |
| Cerebras | 1M tokens/day free | Smart, Reasoner, Live, Fast, Coder |
| Google Gemini | Flash + Pro, Search grounding | Smart, Reasoner, Live, Fast, Coder, Vision |
| OpenRouter | 17+ models, free variants | Smart, Reasoner, Live, Fast, Coder, Vision |
| NVIDIA NIM | 1000 free credits at sign-up | Smart, Reasoner, Live, Fast, Coder |
| DeepSeek | Pay-as-you-go, very cheap | Smart, Reasoner, Live, Fast, Coder |
| Alibaba Qwen | Free tier on DashScope | Smart, Reasoner, Live, Fast, Coder, Vision |
| Moonshot Kimi | Free trial credits | Smart, Reasoner, Live, Fast, Coder |
| Zhipu GLM | Generous free quota | Smart, Reasoner, Live, Fast, Coder |
| Mistral | La Plateforme free tier | Smart, Reasoner, Live, Fast, Coder |
| OpenAI | Paid — usage-based | Smart, Reasoner, Live, Fast, Coder, Vision |
| Anthropic | Paid — usage-based | Smart, Reasoner, Live, Fast, Coder, Vision |
| xAI Grok | Paid — usage-based | Smart, Reasoner, Live, Fast, Coder |
| Together AI | Free endpoints on select open models | Smart, Reasoner, Live, Fast, Coder |
| Fireworks AI | Paid — usage-based | Smart, Reasoner, Live, Fast, Coder |
| Novita AI | Free trial credits | Smart, Reasoner, Live, Fast, Coder |
Modes
A mode is a curated engine + behaviour. Pick one per message; the gateway selects the best available provider and fails over silently.
Smart
DeepSeek V3.2 685B MoE
Professional emails, deep analysis, long-form reasoning.
Reasoner
DeepSeek R1
Chain-of-thought made visible for GDPR-shaped questions.
Live
Gemini 2.5 Flash
Fast, broad-knowledge answers from Google’s Flash model.
Fast
Groq GPT-OSS 20B
41ms first token, built for quick lookups.
Coder
DeepSeek V3.2 + Qwen 3 Coder
Debug, refactor, and write tests with a code-tuned engine.
Vision
Llama-4 Scout
Llama-4 Scout via Groq. Image upload is on the roadmap.
Encryption
Your passphrase derives a vault key with PBKDF2 (600,000 iterations, above OWASP 2024 guidance). Provider keys and messages are sealed with AES-256-GCM in the browser.
const key = await crypto.subtle.deriveKey(
{ name: 'PBKDF2', salt, iterations: 600_000, hash: 'SHA-256' },
passphraseKey,
{ name: 'AES-GCM', length: 256 },
false,
['encrypt', 'decrypt'],
)API reference
Send a chat completion through the gateway. Specify a mode and the gateway picks the provider.
POST /api/chat
Authorization: Bearer <session-token>
Content-Type: application/json
{
"mode": "smart",
"messages": [
{ "role": "user", "content": "Summarise this contract clause" }
]
}Personal endpoint
sarmalink also exposes an OpenAI-compatible relay at/api/v1so Claude Code, Cursor, VS Code Continue, OpenAI client libs, and any tool that speaks the OpenAI shape can use your keys through one base URL. Authenticate with your Supabase access token (see Settings → Personal API for the live one).
List models
GET https://ai.sarmalinux.com/api/v1/models
Authorization: Bearer $SARMALINK_TOKEN
→ 200 { object: "list", data: [{ id: "groq/default", ... }, ...] }Chat completion
Provider routing follows the failover order for the requested mode and skips providers you have no remote key for.
POST https://ai.sarmalinux.com/api/v1/chat/completions
Authorization: Bearer $SARMALINK_TOKEN
Content-Type: application/json
{
"model": "groq/default",
"mode": "smart",
"messages": [{ "role": "user", "content": "Hello from Cursor" }],
"stream": true
}Response: standard text/event-stream forwarded directly from the upstream provider. TheX-Sarmalink-Providerheader tells you which provider answered.
Manage remote keys
# List
GET /api/v1/keys
→ { keys: [{ provider, enabled, created_at }, ...], server_ready: boolean }
# Add / replace
POST /api/v1/keys
{ "provider": "deepseek", "key": "sk-…" }
# Remove
DELETE /api/v1/keys?provider=deepseekUse sarmalink from coding toolsBeta
The personal endpoint speaks the OpenAI wire format, so any OpenAI SDK or OpenAI-compatible client can point at it. Three things to configure:
- Base URL:
https://ai.sarmalinux.com/api/v1 - API key: your personal token from Settings → Personal API, sent as
Authorization: Bearer <token>(exactly what every OpenAI SDK does with itsapiKeyfield) - Model: any id from
GET /api/v1/models, e.g.groq/default
How the model parameter behaves: the segment before the slash names the provider sarmalink tries first; the relay then falls back through the failover order for the requested mode (smart, reasoner, live, fast, coder, vision; default smart), skipping providers you have not enabled. Each provider serves its curated model for that mode, and responses are always streamed as server-sent events. Only providers you have enabled under Settings → Personal API are used.
curl
curl https://ai.sarmalinux.com/api/v1/chat/completions \
-H "Authorization: Bearer $SARMALINK_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"model": "groq/default",
"messages": [{ "role": "user", "content": "Hello from curl" }]
}'OpenAI JS SDK
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'https://ai.sarmalinux.com/api/v1',
apiKey: process.env.SARMALINK_TOKEN,
})
const stream = await client.chat.completions.create({
model: 'groq/default',
messages: [{ role: 'user', content: 'Hello from my editor' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
}OpenAI Python SDK
import os
from openai import OpenAI
client = OpenAI(
base_url="https://ai.sarmalinux.com/api/v1",
api_key=os.environ["SARMALINK_TOKEN"],
)
stream = client.chat.completions.create(
model="groq/default",
messages=[{"role": "user", "content": "Hello from Python"}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")Continue / Cline-style config
Any editor extension with an “OpenAI-compatible” provider option works the same way — set the base URL, paste the token as the API key, pick a model id.
{
"models": [
{
"title": "sarmalink",
"provider": "openai",
"apiBase": "https://ai.sarmalinux.com/api/v1",
"apiKey": "<token from Settings → Personal API>",
"model": "groq/default"
}
]
}Claude Code (Anthropic-format endpoint)
sarmalink also speaks the Anthropic Messages format at /api/v1/messages, so Claude Code and any tool built on the Anthropic SDK can use your keys too. The Anthropic SDK appends /v1/messages to its base URL itself, so the base URL ends at /api — not /api/v1:
export ANTHROPIC_BASE_URL="https://ai.sarmalinux.com/api"
export ANTHROPIC_API_KEY="<token from Settings → Personal API>"
claude- Model mapping: any
claude-*model id (what Claude Code sends by default) maps to your failover-ladder default, so no model config is needed. To pin a provider first, setANTHROPIC_MODELto a provider-prefixed id likegroq/default— same semantics as the OpenAI endpoint. - Auth: both
x-api-key(what the Anthropic SDK sends) andAuthorization: Bearerare accepted; theanthropic-versionheader is accepted and ignored. - Beta, text-only: image blocks are rejected with a clear error and tool calls are not relayed, so agentic tool use degrades to plain chat. Token counts in
usageare estimates (chars ÷ 4), and the same Settings → Personal API remote-key setup applies. TheX-Sarmalink-Providerresponse header names the provider that answered.
Beta caveats: the endpoint relays through server-side remote keys, so enable at least one provider under Settings → Personal API first (you will get 400 no_remote_keys otherwise, or 501 remote_keys_unconfigured if the deployment has remote keys switched off). Tokens are session-bound and expire — refresh from Settings if you see 401 invalid_bearer. Long-lived personal access tokens are on the roadmap.
Error shapes
Every JSON error follows the OpenAI shape so your existing SDK error handling keeps working.
{
"error": {
"type": "invalid_request_error",
"code": "missing_bearer",
"message": "Missing bearer token"
}
}401 missing_bearer· no Authorization header.401 invalid_bearer· token expired or wrong project.400 no_remote_keys· enable at least one provider in Settings → Personal API first.501 remote_keys_unconfigured· server is missing the master key env.502 all_providers_failed· every enabled provider returned an error; check your keys.