Quickstart
Change the base URL. Keep your SDK.
The client keeps its native JSON. Codex and the OpenAI SDK POST OpenAI chat completions. Claude Code POSTs Anthropic messages. You pick the model id — pin sarvam/sarvam-30b and TokenSutra stays on Sarvam.
curl http://localhost:43127/api/v1/chat/completions \
-H "Authorization: Bearer sk-sutra-demo" \
-H "Content-Type: application/json" \
-d '{
"model": "sutra/india-only",
"india_only": true,
"messages": [{"role": "user", "content": "Namaste from TokenSutra"}]
}'import OpenAI from "openai";
const client = new OpenAI({
apiKey: "sk-sutra-demo",
baseURL: "http://localhost:43127/api/v1",
});
const completion = await client.chat.completions.create({
model: "sutra/bharat",
messages: [{ role: "user", content: "UPI failed. Reply in Hindi." }],
});Every harness discovers models the same way: GET /v1/models with the API key. Codex, the OpenAI SDK, and OpenAI-compatible tools get catalog ids. Claude Code hits that path too; TokenSutra prefixes ids with anthropic/ for its picker when the request has anthropic-version or a Claude user-agent. Point ANTHROPIC_BASE_URL at http://localhost:43127 (or …/api). Do not add /anthropic — that is DeepSeek’s own prefix, not TokenSutra’s.
export ANTHROPIC_BASE_URL=http://localhost:43127 export ANTHROPIC_AUTH_TOKEN=sk-sutra-demo export CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY=1 # Claude Code POSTs /v1/messages and GETs /v1/models (same as /api/v1/…). # /api also works: ANTHROPIC_BASE_URL=http://localhost:43127/api export ANTHROPIC_MODEL=anthropic/claude-sonnet-4
curl http://localhost:43127/v1/messages \
-H "x-api-key: sk-sutra-demo" \
-H "anthropic-version: 2023-06-01" \
-H "Content-Type: application/json" \
-d '{
"model": "sarvam/sarvam-30b",
"max_tokens": 256,
"messages": [{"role": "user", "content": "Namaste"}]
}'Codex and the OpenAI SDK POST chat.completions. Same TokenSutra key. They discover models with GET /v1/models (catalog ids, no Claude prefix). The model field is how you pin Sarvam — TokenSutra does not infer it from which client you used.
export OPENAI_BASE_URL=http://localhost:43127/v1 export OPENAI_API_KEY=sk-sutra-demo # Codex / OpenAI SDK POST /v1/chat/completions (OpenAI JSON). # Pin the model in the client: sarvam/sarvam-30b
Provider failover is automatic inside a model. Model fallbacks are opt-in: pass models[] or call a named route. Indian hops are local adapters unless you paste BYOK; the router still walks the list when a hop throws.
{
"model": "sarvam/sarvam-30b",
"models": [
"krutrim/krutrim-2",
"corover/bharatgpt",
"google/gemini-2.5-flash"
],
"route": "balanced",
"provider": { "allow_fallbacks": true },
"messages": [{ "role": "user", "content": "Stay up if Sarvam is down." }]
}Password signup, Google SSO through Neon Auth, and company SSO through the organization's OIDC issuer. Owners convert a personal workspace to an org, invite admin/member, and attach an email domain. Enforce SSO to block passwords on that domain.
Owner — billing, SSO, roles, convert. Admin — keys, settings, invite members, routes, webhooks. Member — create keys, playground, read settings. Dashboard APIs return 403 when the role cannot perform the action.
POST /api/v1/chat/completions · /v1/chat/completions (OpenAI JSON)
POST /api/v1/messages · /v1/messages (Anthropic JSON)
POST /v1/messages/count_tokens
GET /v1/models · /api/v1/models (API key; that key’s allow-list)
GET /api/v1/pubmodels (signed-in user; full workspace catalog)
GET /api/v1/health
GET|POST /api/v1/auth (password) · GET /api/v1/auth/oauth (SSO)
GET /api/v1/auth/sso
GET /api/v1/logs (org audit; also GET /api/v1/audit)
GET|POST /api/v1/orgs (convert, invite, role, SSO — owner/admin/member)
GET|POST|DELETE /api/v1/groups
GET|POST /api/v1/wallet
GET|POST|DELETE /api/v1/keys
GET /api/v1/generations
GET|POST|DELETE /api/v1/routes
GET /api/v1/stats
GET|POST /api/v1/platform
GET|POST|DELETE /api/v1/webhooks
GET|POST /api/v1/marketplace (organization workspaces)
POST /api/v1/embeddings
POST /api/v1/audio/transcriptions
POST /api/v1/audio/speech