← All guides AI Release
RU Subscribe to @ai_release1

Best LLM API routers with free or cheap access to Claude, GPT, DeepSeek and GLM: 2026 comparison

Updated: 23.10.2026 · AI Release · @ai_release1
Best LLM API routers with free or cheap access to Claude, GPT, DeepSeek and GLM: 2026 comparison

TL;DR

Requirements and setup

Illustration: Requirements and setup
Illustration: Requirements and setup

Term check: an API router (also called an aggregator or gateway) is a single HTTP endpoint that forwards your request to whichever model vendor you name, so your code talks to one URL instead of four SDKs. "OpenAI-compatible" means the endpoint accepts the same request shape as OpenAI's /v1/chat/completions, which is why the Python snippet in Step 2 works unchanged against any router that supports it.

Router options at a glance

There are two shapes of router. Pick one before you write code, because the credential model differs.

CriterionHosted aggregatorSelf-hosted proxy
What it isA vendor-run API that already holds accounts with Anthropic, OpenAI, DeepSeek, ZhipuA process you run (for example LiteLLM) that holds *your* vendor keys and exposes one local port
Credentials you manageOne router keyFour vendor keys plus a local proxy key
Free/cheap accessDepends on the router's current trial credits and per-model pricing — verify on its pricing pageYou pay each vendor directly at list price; no markup and no free tier added
Billing visibilityOne invoice, vendor-level detail variesPer-vendor invoices, full detail
Data pathPrompts pass through a third party — check its retention policyPrompts go only to the vendors you configured
Best forInterns prototyping fast, one-key demosTeams with existing vendor contracts, compliance constraints

What each model family requires from the router:

Model familyEndpoint contractVerify in the docs
Claude (Anthropic)OpenAI-compatible `/v1/chat/completions`, or a native Anthropic passthroughExact model IDs, per-1M-token input/output price, context window
GPT (OpenAI)`/v1/chat/completions`Which model IDs your key tier can call, rate limits
DeepSeek`/v1/chat/completions`Whether the free/trial quota applies, price per 1M tokens
GLM (Zhipu)`/v1/chat/completions`Provider prefix used in self-hosted configs, model IDs

Step 1. Collect the endpoint, the key and the model IDs

What to do: create a router account (or install the proxy), copy the base URL, store the key in an environment variable, and pull the live model list.

Why: every later step depends on three strings — base URL, key, model ID. Guessing the model ID is the single most common cause of a 404 two steps later, so read them from the API instead of from a blog post.

export ROUTER_BASE_URL="https://<router-base-url>/v1"
export ROUTER_API_KEY="<your-api-key>"

curl -s "$ROUTER_BASE_URL/models" \
  -H "Authorization: Bearer $ROUTER_API_KEY" \
  | jq -r '.data[].id' | sort | head -20

Example output (IDs are illustrative — yours will differ):

anthropic/<claude-model-id>
deepseek/<deepseek-model-id>
openai/<gpt-model-id>
zhipu/<glm-model-id>

Why this works: /v1/models is part of the OpenAI-compatible surface, so any router that claims compatibility must answer it. If you get HTML back instead of JSON, the base URL is wrong.

Write the four IDs you plan to use into a local file so the later steps stay reproducible:

cat > models.env <<'EOF'
CLAUDE_MODEL=<id-from-the-list-above>
GPT_MODEL=<id-from-the-list-above>
DEEPSEEK_MODEL=<id-from-the-list-above>
GLM_MODEL=<id-from-the-list-above>
EOF

How to check: source models.env && echo $CLAUDE_MODEL prints the ID, not an empty line.

Verification checklist for the router's docs page — tick all six before spending money:

Step 2. Point one client at the router

Illustration: Step 2. Point one client at the router
Illustration: Step 2. Point one client at the router

What to do: configure the OpenAI Python SDK with the router's base URL, then — if you chose the self-hosted proxy — describe all four models in one YAML file.

Why: a single client with a base_url override replaces four vendor SDKs. Swapping models becomes a string change, and a fallback becomes a retry, not a refactor.

import os
from openai import OpenAI

client = OpenAI(
    base_url=os.environ["ROUTER_BASE_URL"],
    api_key=os.environ["ROUTER_API_KEY"],
    timeout=60.0,
)

MODELS = {
    "claude": os.environ["CLAUDE_MODEL"],
    "gpt": os.environ["GPT_MODEL"],
    "deepseek": os.environ["DEEPSEEK_MODEL"],
    "glm": os.environ["GLM_MODEL"],
}

def ask(family: str, prompt: str) -> str:
    r = client.chat.completions.create(
        model=MODELS[family],
        messages=[{"role": "user", "content": prompt}],
        max_tokens=128,
    )
    print(family, r.usage.prompt_tokens, r.usage.completion_tokens)
    return r.choices[0].message.content

print(ask("deepseek", "Reply with the single word: ready"))

Example: running it prints deepseek 12 1 followed by ready — the three numbers are family, input tokens and output tokens. Those token counts are what you multiply by the per-1M prices from Step 1 to get the real cost of a call.

Why this works: base_url is the only field that changes; the request body stays in the OpenAI schema, and the router rewrites it into each vendor's native format.

If you run the self-hosted proxy instead, keep every credential on the server and give clients only a local key:

model_list:
  - model_name: claude
    litellm_params:
      model: anthropic/<anthropic-model-id>
      api_key: os.environ/ANTHROPIC_API_KEY
  - model_name: gpt
    litellm_params:
      model: openai/<openai-model-id>
      api_key: os.environ/OPENAI_API_KEY
  - model_name: deepseek
    litellm_params:
      model: deepseek/<deepseek-model-id>
      api_key: os.environ/DEEPSEEK_API_KEY
  - model_name: glm
    litellm_params:
      model: <provider-prefix>/<glm-model-id>
      api_key: os.environ/ZHIPU_API_KEY
litellm --config config.yaml --port 4000

Why this works: the proxy translates the OpenAI schema into each vendor's API and maps model_name to a real model ID, so your application only ever sends claude or glm. The vendor prefix for GLM and the exact CLI flag are version-specific — check the proxy's documentation if startup fails.

How to check: curl -s localhost:4000/v1/models -H "Authorization: Bearer <local-key>" | jq '.data | length' returns 4.

Step 3. Verify answers, latency and cost

Illustration: Step 3. Verify answers, latency and cost
Illustration: Step 3. Verify answers, latency and cost

What to do: run a smoke test across all four families, measure round-trip time, and confirm the router returns a usage block — then break a key on purpose to see the error shape.

Why: a router can list a model and still fail on call (provider outage, quota exhausted, missing permission). You want that discovered in a test, not in a demo.

for m in "$CLAUDE_MODEL" "$GPT_MODEL" "$DEEPSEEK_MODEL" "$GLM_MODEL"; do
  printf '%s ' "$m"
  curl -s -o /dev/null -w '%{http_code} %{time_total}s\n' \
    "$ROUTER_BASE_URL/chat/completions" \
    -H "Authorization: Bearer $ROUTER_API_KEY" \
    -H "Content-Type: application/json" \
    -d "{\"model\":\"$m\",\"messages\":[{\"role\":\"user\",\"content\":\"Say OK\"}],\"max_tokens\":8}"
done

Example output:

anthropic/<claude-model-id> 200 1.842s
openai/<gpt-model-id> 200 0.914s
deepseek/<deepseek-model-id> 200 2.307s
zhipu/<glm-model-id> 200 1.115s

Four 200 lines mean the router is working end to end. Note the timings in a comment next to your config — they drift, and a sudden 10x jump usually means the router fell back to a slower provider silently.

Why this works: -o /dev/null throws away the body and -w prints only the status code and total time, so you get a clean matrix without parsing JSON.

How to check success on screen:

How to choose

Troubleshooting

Problem. Authentication fails on every model even though the key looks correct

Problem. One model returns 404 while the others answer

Problem. Long prompts time out

Summary and next steps

You now have one OpenAI-compatible endpoint that reaches Claude, GPT, DeepSeek and GLM, plus a repeatable smoke test that reports status codes and latency per model. Next, add a fallback list in your client so a failing model retries on a second one, and re-check /v1/models and the pricing page before every release.

FAQ

What is an API router in one sentence?

It is a single HTTP endpoint that forwards your request to different model vendors, so your code uses one URL, one key and one request format instead of four.

Is an OpenAI-compatible router slower than calling the vendor directly?

It adds one network hop, which is visible as extra latency in the time_total column of the Step 3 loop; measure your own numbers, since routing and retry behaviour differ per provider.

Can I use a router with free-tier access for production?

Only after reading the router's rate limits and retention policy — free tiers usually cap requests per minute and may log prompts; the tokens-per-minute figure is on the pricing or limits page.

Why does the same prompt give different token counts on different models?

Each vendor tokenises text differently, so usage.prompt_tokens varies; always multiply the returned counts by that specific model's per-1M price rather than assuming one rate.

🤖 AI summary