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.
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.
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.
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.
| Model | Pass as | Input / 1M |
|---|---|---|
| Kimi K2.6 | moonshotai/kimi-k2.6 | $0.55 |
| Kimi K3 | moonshotai/kimi-k3 | $1.85 |
| GLM-5.2 | z-ai/glm-5.2 | $0.82 |
| GLM-5.2 Air | z-ai/glm-5.2-air | $0.17 |
| DeepSeek V4 Pro | deepseek/deepseek-v4-pro | $0.28 |
| DeepSeek V4 Flash | deepseek/deepseek-v4-flash | $0.09 |
Full catalogue — or fetch it as JSON from GET /api/v1/models, which is unauthenticated.
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.