SDKs

Official TypeScript and Python clients, generated from the OpenAPI document so they never drift from the gateway. Thin by design: one method per operation, typed request and response shapes, streaming, retries and the management API.

View as Markdown

TypeScript — @elevenrouter/sdk

npm install @elevenrouter/sdk
import { ElevenRouter } from '@elevenrouter/sdk';

const client = new ElevenRouter({ apiKey: process.env.ELEVENROUTER_API_KEY, metadata: true });

const res = await client.chat.completions.create({
  model: 'anthropic/claude-sonnet-5',
  models: ['openai/gpt-5.6-terra'],
  messages: [{ role: 'user', content: 'Summarise this in one line.' }],
});
console.log(res.choices[0]?.message.content, res.elevenrouter_metadata?.cost);

// Streaming
const stream = await client.chat.completions.create({ model: 'openai/gpt-5.6-luna', messages, stream: true });
for await (const chunk of stream) process.stdout.write(chunk.choices[0]?.delta.content ?? '');
console.log(stream.meta.generationId);

Works in Node 20+, Bun, Deno, edge runtimes and browsers (bring a key from your backend). No dependencies. Every other endpoint is one call away: client.models.list(), client.embeddings.create(), client.messages.create() (Anthropic format), client.generation(id), client.credits(), client.status(), client.analytics.query(), and the management resources keys, workspaces, budgets, policies, presets, notificationRules, byok and members. Anything else: client.call('operationId', …).

apiKey / baseUrloptions
Default to ELEVENROUTER_API_KEY and ELEVENROUTER_BASE_URL. Point baseUrl at a self-hosted gateway.
metadataboolean
Adds X-ER-Metadata: enabled so inference responses carry the elevenrouter_metadata route receipt.
maxRetries / timeoutMsnumber
Idempotent calls, 429s and 5xx responses are retried with exponential backoff honouring Retry-After (default 2). Streams are never timed out once started.
defaultHeadersobject
Sent on every request — use it for HTTP-Referer / X-Title app attribution or X-ER-Session-Id.
errorsclasses
ElevenRouterError with subclasses BadRequestError, AuthenticationError, PermissionError, NotFoundError, InsufficientCreditsError, RateLimitError, ServerError, ConnectionError, AbortError; each carries status, type, code, param, metadata, requestId and retryAfterMs.

Python — elevenrouter

pip install elevenrouter
from elevenrouter import ElevenRouter

client = ElevenRouter()  # reads ELEVENROUTER_API_KEY

res = client.chat.completions.create(
    model="anthropic/claude-sonnet-5",
    models=["openai/gpt-5.6-terra"],
    messages=[{"role": "user", "content": "Summarise this in one line."}],
)
print(res["choices"][0]["message"]["content"], res["_meta"]["generation_id"])

# Streaming
for chunk in client.chat.completions.create(model="openai/gpt-5.6-luna", messages=messages, stream=True):
    print(chunk["choices"][0]["delta"].get("content", ""), end="", flush=True)

# Async
from elevenrouter import AsyncElevenRouter
async with AsyncElevenRouter() as aclient:
    res = await aclient.chat.completions.create(model="openai/gpt-5.6-luna", messages=messages)

Python 3.9+, one dependency (httpx), sync and async clients with the same surface. Responses are plain dicts in the wire format plus a _meta entry with the generation id, vendor, request id and rate-limit headers. Errors mirror the TypeScript classes (RateLimitError, InsufficientCreditsError, …).

Management API from the SDKs

const admin = new ElevenRouter({ apiKey: process.env.ELEVENROUTER_MANAGEMENT_KEY });
const { data: ws } = await admin.workspaces.create({ name: 'Production', environment: 'production' });
await admin.budgets.create({ scope_type: 'workspace', scope_id: ws.id, interval: 'daily', limit: 250 });
const dry = await admin.policies.dryRun({ rules: { vendors: { mode: 'allow_only', slugs: ['anthropic', 'openai'] } } });
console.log(`would block ${dry.data?.blocked} of ${dry.data?.requests} requests`);
const { key } = await admin.keys.create({ name: 'support-backend', workspace_id: ws.id, preset_id: 'support-bot' });

Generate your own client

Both SDKs are produced by a small generator over openapi.json; any OpenAPI 3.0 toolchain (openapi-typescript, openapi-generator, Kiota, …) works against the same document for other languages. The document is versioned with the API and listed in the changelog.