Skip to content
← Docs

Migrating to AI Token Router

If your code already speaks to the OpenAI SDK, moving is a base URL and a key. This page is the whole procedure, including the three things that do not behave identically.

1

Create a key

Sign in and create one from the dashboard. It is shown once — we store a hash, so a lost key has to be replaced rather than recovered.

Dashboard → API keys

2

Point the SDK at us

Two lines. Nothing else in your integration changes.

from openai import OpenAI

client = OpenAI(
    base_url="https://router.xark.io/api/v1",
    api_key="sk-...",            # the key you just created
)

response = client.chat.completions.create(
    model="moonshotai/kimi-k2.6",
    messages=[{"role": "user", "content": "Hello"}],
)
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://router.xark.io/api/v1",
  apiKey: process.env.AI_TOKEN_ROUTER_KEY,
});

Anything built on the OpenAI SDK inherits this — LangChain, LlamaIndex, Vercel AI SDK, Instructor. Set the base URL where that framework takes it and the rest is unchanged.

3

Map your model ids

Model names are namespaced publisher/model. The bare name is accepted too, so glm-5.2 and z-ai/glm-5.2 both resolve — use the full id in anything you keep.

ModelPass asInput / 1M
Kimi K2.6moonshotai/kimi-k2.6$0.55
Kimi K3moonshotai/kimi-k3$1.85
GLM-5.2z-ai/glm-5.2$0.82
GLM-5.2 Airz-ai/glm-5.2-air$0.17
DeepSeek V4 Prodeepseek/deepseek-v4-pro$0.28
DeepSeek V4 Flashdeepseek/deepseek-v4-flash$0.09

Full catalogue — or fetch it as JSON from GET /api/v1/models, which is unauthenticated.

4

Verify before you cut over

Run one request against the new base URL and compare the response shape to what you had. The usage block is where a billing surprise would first show up, so read it.

curl https://router.xark.io/api/v1/chat/completions \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "moonshotai/kimi-k2.6",
    "messages": [{"role": "user", "content": "Say hello"}]
  }'

What does not behave identically

Three differences worth knowing before you move production traffic, rather than after.

Running out of credit is a 429, not a 402

Both an exhausted balance and a rate limit return 429. They are distinguished by error.code insufficient_credits versus rate_limit_exceeded. A client that retries every 429 with backoff will retry forever on the first one, so branch on the code.

Only open-weight models exist here

There is no gpt-4, claude-* or gemini-*. If your code falls back to one of those on error, that fallback will fail with model_not_found rather than silently working. Why.

Organisation and project headers are ignored

OpenAI-Organization and OpenAI-Project are accepted and discarded — there is nothing behind them here. Use one API key per project instead; spend is attributed per key and appears that way in your usage log.

Rolling back

Change the base URL back. Nothing here writes to your side, and we hold no state your application depends on — keys and balance live with us, your data does not. Keep the old credentials until you are satisfied; there is no lock-in step to undo.