If you are switching from OpenRouter, the change for a standard OpenAI-compatible integration is one base URL and a model-ID prefix. The parts that bite are the edge cases: batch routes, free variants, provider-pinned models, and any code that hardcodes a vendor prefix. This guide walks through the whole path and ends with a dual-run setup so you can go back in one environment variable.

Written 2026-10-26. Commands assume an OpenAI-compatible client; Python and Node examples are at the bottom.

Why teams migrate

The usual reason is the recent ownership change at OpenRouter. That is a signal, not a verdict: it means the terms, pricing, and routing you signed up for are now controlled by a different team. Some teams are fine with that. Others want a second path that does not require rewriting their app if the terms change again.

JZS is a smaller gateway: one USD balance, one published price per model, and a catalog of 69 models we route and support. The trade-off is breadth. If you need the long tail, free models, or batch routes, staying on OpenRouter may be the right call. If you mostly use the current GPT, Claude, DeepSeek, Qwen, and Gemini models, the migration below is short.

Before you start: inventory the assumptions

Spend five minutes listing what your code actually depends on. A migration that ignores these will work in staging and fail in production:

  • Model IDs in use. Search for strings containingopenai/,anthropic/,google/, and:free or:batch.
  • Provider preferences. If you pin an upstream provider or use OpenRouter's routing preferences, that concept does not exist here. We route through the channels we operate.
  • Batch jobs. Batch endpoints are not supported. Keep those on OpenRouter or move them to a direct provider batch API.
  • Headers. HTTP-Referer and X-Title are OpenRouter metadata. They are not required here; removing them is safe.

Step 1: create an account

Go to jzstoken.com/register and sign up with your email. New accounts may receive a one-time signup credit while the current promotional round lasts; check the signup page for the current offer. The credit is a trial, not a permanent free tier.

Step 2: create an API key

After verification, open Dashboard → API Keys and create a key. It starts with sk- and is shown once; store it in your secret manager. The key is scoped to one account and draws on the shared USD balance.

Add a small amount of credit before you test if the signup credit is not active. The Buy Credits page has the current minimum and payment methods.

Step 3: change the base URL

This is the whole integration change for most apps. Keep the same OpenAI SDK and the same Authorization header:

# Before
OPENAI_BASE_URL=https://openrouter.ai/api/v1
OPENAI_API_KEY=sk-or-v1-...
# After
OPENAI_BASE_URL=https://jzstoken.com/api/v1
OPENAI_API_KEY=sk-...   # the JZS key you just created

The available endpoints include /chat/completions, /responses, and /messages. Standard streaming and ordinary function tool calls work at the same boundary.

Step 4: map the model IDs

OpenRouter IDs use a vendor prefix. Our catalog does not. Remove the prefix and keep the rest of the name exact — model IDs are case-sensitive.

OpenRouter IDJZS IDNotes
openai/gpt-5.5gpt-5.5GPT-4o is still listed on OpenRouter at $2.50 / $10 per 1M, but it is not in our catalog. GPT-5.5 is the current OpenAI model we serve.
anthropic/claude-sonnet-5.5claude-sonnet-5.5Direct mapping.
deepseek/deepseek-v4-prodeepseek-v4-proDirect mapping.
qwen/qwen3.7-maxqwen3.7-maxDirect mapping.
google/gemini-4-argongemini-4-argonUpstream availability for this model has been intermittent. Test it before moving production traffic.

If you use a model that is not on this list, check the full catalog. Do not guess: an unknown ID returns a 403 model_not_supported, not a silent fallback.

For the same five models, here is the standard per-1M price on both platforms at the time of writing. Use this as a sanity check that the ID you mapped is the model you meant to buy.

ModelOpenRouter in / outJZS in / out3:1 blended (OR → JZS)JZS saves
GPT-5.5gpt-5.5$5.00 / $30.00$0.39 / $2.34$11.250 → $0.87692.2%
Claude Sonnet 5.5claude-sonnet-5.5$2.00 / $10.00$0.78 / $3.89$4.000 → $1.55761.1%
DeepSeek V4 Prodeepseek-v4-pro$0.96 / $1.91$0.45 / $2.25$1.194 → $0.89824.8%
Qwen3.7 Maxqwen3.7-max$1.48 / $4.42$0.78 / $2.34$2.213 → $1.16847.2%
Gemini 4 Argongemini-4-argon$2.00 / $10.00$0.39 / $1.95$4.000 → $0.77880.5%

USD per 1M tokens, standard (non-batch) routes, captured 2026-10-26. Blended assumes 3 input tokens per output token. OpenRouter batch routes are often half price and are not compared here.

Sources: JZS public pricing API and OpenRouter public model list, both read on 2026-10-26. Prices move; check both pages before you commit to a provider.

Step 5: send one test request

Start with a cheap, stable model. This uses DeepSeek V4.1 Flash and a single sentence:

curl https://jzstoken.com/api/v1/chat/completions \
  -H "Authorization: Bearer $JZS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek-v4.1-flash",
    "messages": [{"role": "user", "content": "Reply with the word ok."}],
    "max_tokens": 8
  }'

A 200 with a normal OpenAI-shaped response means the key, base URL, and model ID are all correct. If you get a 403 with model_not_supported, the model ID is wrong or not in the catalog; 401 means the key is missing or malformed; 402 means the balance is below the estimated cost.

Python

from openai import OpenAI
client = OpenAI(
    api_key="sk-...",
    base_url="https://jzstoken.com/api/v1",
)
r = client.chat.completions.create(
    model="deepseek-v4.1-flash",
    messages=[{"role": "user", "content": "Reply with the word ok."}],
    max_tokens=8,
)
print(r.choices[0].message.content)

Node

import OpenAI from "openai";
const client = new OpenAI({
  apiKey: process.env.JZS_KEY,
  baseURL: "https://jzstoken.com/api/v1",
});
const r = await client.chat.completions.create({
  model: "deepseek-v4.1-flash",
  messages: [{ role: "user", content: "Reply with the word ok." }],
  max_tokens: 8,
});
console.log(r.choices[0].message.content);

Step 6: dual-run before cutover

Do not flip production in one commit. Put both gateways behind an environment variable, route a small percentage of traffic to JZS, and compare latency, error rates, and token accounting for a few days. The API shape is the same, so this is a routing change, not a code change:

const BASE =
  process.env.LLM_GATEWAY === "jzs"
    ? "https://jzstoken.com/api/v1"
    : "https://openrouter.ai/api/v1";

Keep the OpenRouter key and account active during the comparison. If error rates or quality regress, flip the variable back. Cancelling the old account is the last step, not the first.

Feature parity: what moves and what does not

Most applications only use a small slice of the API. Check the slice you actually call; the rest of this table is irrelevant to your migration.

FeatureJZSNotes
OpenAI chat completionsYesSame request/response shape.
Responses APIYesFor clients that already use /responses.
Anthropic Messages APIYesFor Claude-native clients.
SSE streamingYesStandard OpenAI-style stream.
Function / custom toolsYesModel-dependent; ordinary tool calling is portable.
Provider-specific server toolsNoNot portable across gateways; check before relying on them.
Batch endpointsNoKeep batch jobs on OpenRouter or a direct provider.
Free model variantsNoThe signup credit is a trial, not a free tier.
Per-request provider routingNoWe route through the channels we operate.

A safe cutover runbook

  • Day 0: add JZS as a second provider behind an environment variable or feature flag. Do not remove OpenRouter.
  • Day 1: route 1% of traffic. Compare p50/p95 latency, 4xx/5xx rates, token usage per request, and a sample of outputs.
  • Day 3: raise to 10% if the error and latency curves match. Keep the same model IDs and prompt versions so the comparison is real.
  • Day 7: cut over the remainder. Keep the OpenRouter key active for at least 30 days in case you need to roll back.
  • Rollback: flip the environment variable. No deploy, no code revert. That is the point of doing this behind a flag.

Measure cost per successful request, not cost per token. A gateway with a lower token price but more retries can be more expensive per completed task. The same applies to output length: a model that rambles costs more even at a lower per-token rate.

What changes for your team

Two operational things move, and both are easy to miss:

  • Secrets. The JZS key belongs in the same secret store as the OpenRouter key. Do not commit it, and rotate it if it ever appears in a log or a support ticket.
  • Billing reconciliation. JZS reports usage in USD per request; OpenRouter may show credits and route-level detail. If finance reconciles monthly, export both usage reports for the dual-run window and compare per-model spend, not just totals.
  • Support path. Add the JZS contact channel to your incident runbook. A 429 or a model outage should have a named owner and a documented escalation path on both gateways during the transition.

Common errors and what they mean

403 — model not supported

You kept the vendor prefix, used the wrong case, or picked a model we do not serve. Compare the ID against the catalog exactly. :free and :batch suffixes are not supported; use the base model ID.

401 — unauthorized

The Authorization header is missing, the key was copied with whitespace, or you are using an OpenRouter key. Create a JZS key and use it with the new base URL.

402 — insufficient balance

The prepaid USD balance is below the request estimate. Add credit or lower max_tokens. The response includes the estimated cost and the balance.

Streaming and tool calls

Standard OpenAI streaming and ordinary function tools work. If you rely on OpenRouter-specific provider routing or server-side web search on non-OpenAI models, check the model page or ask support before moving that workload. Not every tool type is portable across gateways.

Billing differences

JZS is prepaid in USD. There is no subscription and no monthly minimum; each request deducts the published per-token rate from your balance. OpenRouter also uses prepaid credits, but its per-token price can depend on the upstream route and it offers batch and free variants. If you use batch jobs, keep them where they are or compare that price separately — it is not an apples-to-apples migration.

The price comparison shows the 100M-token math, including the cases where OpenRouter is cheaper.

FAQ

Do I need to change my SDK?

No, if your SDK lets you set a base URL and uses the OpenAI chat/responses shape. Change the base URL and the model ID. If your SDK is OpenRouter-specific and does not expose the base URL, switch to the OpenAI SDK for that client.

Can I keep OpenRouter as a fallback?

Yes. Keep both keys and route by environment or by a retry policy. That is the safest cutover and the reason this guide recommends a dual run.

What about free and batch models?

They are not available here. Free endpoints and batch routes are OpenRouter-specific products. If they are a meaningful part of your bill, they are a reason to stay or to split workloads rather than migrate everything.

How do I get help?

Use the contact page or WhatsApp. Include the request time and model ID; we can look up the exact request.

Migrate now

Create an account, make a key, and run the curl above. If you want a second pair of eyes on the cutover, send us the model IDs you use and we will check the mapping.

Migrate nowRead the quick start