1. Get an API key

Create an account, verify your email, then open /keys and create a key. It's shown once, in the form llmr_sk_live_… — store it like any other secret.

Requests without a valid key, or with a key past its expires_at, get a 401. New accounts start on prepaid credits — top up at /settings/credits before sending live traffic.

2. Make a request

The serving API is OpenAI-compatible: POST /v1/chat/completions with a Bearer key. Setting model:"auto" lets our router pick the cheapest model that clears the quality bar for your prompt; pinning an explicit model id skips the router entirely.

curl
# model:"auto" — LLMRouter picks the cheapest model that fits
curl https://api.llmrouter.sh/v1/chat/completions \
  -H "Authorization: Bearer llmr_sk_live_..." \
  -H "content-type: application/json" \
  -d '{
    "model": "auto",
    "mode": "balanced",
    "messages": [{"role": "user", "content": "Write a Python web scraper"}]
  }'

mode is one of cost · balanced · quality — it only affects requests routed via "auto" and defaults to your key's configured mode.

3. Use the OpenAI SDK

No new client library. Point any existing OpenAI SDK at our base_url and swap the key — everything else (streaming, tool calls, response shape) works unchanged.

quickstart.py
# pip install openai
from openai import OpenAI

client = OpenAI(
    base_url="https://api.llmrouter.sh/v1",
    api_key="llmr_sk_live_...",
)

# model:"auto" routes; a slug (e.g. "anthropic/claude-opus-4.8") pins it
resp = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user",
               "content": "Summarize this contract..."}],
)

print(resp.choices[0].message.content)

Same idea in any OpenAI-compatible client (Node's openai package, LangChain, LlamaIndex, etc.) — set the base URL and key, nothing else changes.

Choosing a model

You can call any model in our catalog directly by its slug (provider-prefixed, e.g. anthropic/claude-opus-4.8, openai/gpt-5) — see the full, current list at GET /v1/models or browse /models. Every model, explicit or auto-routed, is billed the same way: provider list price plus a flat 1% fee — see /pricing.

Not sure which model to pick? Leave model:"auto" — the router predicts what your query needs (reasoning, code, tools, vision, context length) and picks the cheapest model in the catalog that meets it. Every deployment also carries automatic provider failover, so a single upstream outage doesn't fail your request.

Streaming

Set stream: true for a standard SSE stream of chat.completion.chunk events, ending in data: [DONE] — identical shape to the OpenAI API.

stream.py
stream = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "Count to 5"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

Failover only happens before the first token — once bytes are streaming, a mid-stream upstream error surfaces as an SSE error event carrying the request's trace id instead of silently switching providers. Non-streaming requests can fail over across the full response.

Response headers

Every response — streaming or not — carries headers explaining the routing decision, so you never have to guess what actually served the request:

x-llmrouter-modelthe model slug that actually served the request
x-llmrouter-served-viawhich deployment/transport served it (direct, fallback, sandbox)
x-llmrouter-cost-usdtotal cost billed for this request, provider price + 1%
x-llmrouter-trace-idlook this up under /logs for the full request trace
x-llmrouter-routing-mstime spent selecting a model, excluding the upstream call
x-llmrouter-difficulty / -reasonpresent on "auto" requests — why this model was chosen

Send x-llmrouter-explain: true to also get an llmrouter: {chosen, ranked, mode, reason, profile} block inline in the JSON response body. Want to see the decision without spending anything? Call POST /v1/route with the same body — it returns the routing decision only, with no upstream call.

Errors & rate limits

Errors are OpenAI-shaped: {"error": {"message", "type", ...}}.

Status Meaning
401missing, invalid, or expired API key
402prepaid credit balance is ≤ $0, or your key's monthly spend cap is reached — top up at /settings/credits
429per-key RPM/TPM limit hit — a Retry-After header tells you how long to back off

A retryable upstream failure (timeout, 429, or 5xx from the provider) doesn't reach you as an error — the gateway automatically walks the ordered fallback list for that model first. You only see an error if every candidate fails.

Test keys (sandbox)

Create a test-mode key at /keys (prefixed llmr_sk_test_…) to exercise the full request/response shape, streaming, and routing decision against an in-process sandbox echo — no upstream call, no spend, no credits required. Swap in a live key when you're ready to serve real traffic.

Next steps