Skip to main content
Home/Blog/Qwen Code API Key Setup: Model Studio, OpenRouter & Local — Without the 401 Errors
Developer Tools

Qwen Code API Key Setup: Model Studio, OpenRouter & Local — Without the 401 Errors

A practical auth and troubleshooting guide for Qwen Code: configure Model Studio/DashScope, OpenRouter, or local endpoints in settings.json — and fix the 401 errors caused by region mismatches and the protocol-key-naming gotcha.

By Sean

You installed Qwen Code, ran qwen, pointed it at Model Studio or OpenRouter, and got a wall of 401 Invalid API-key provided. The key works in curl. It works in another tool. But the CLI rejects it. Welcome to the most common Qwen Code support thread on the internet.

The frustrating part is that almost none of these 401s are about a bad key. They're about which endpoint the key is being sent to, which environment variable actually wins at runtime, and a config schema where one wrong word makes your provider vanish silently. This guide walks the auth model end to end — Model Studio, OpenRouter, and local — and then fixes the 401s by cause.

The four ways Qwen Code authenticates

Qwen Code supports several auth routes, and picking the wrong one for your situation is half the battle:

  • Qwen OAuth — browser login to a qwen.ai account. The free tier here was reportedly discontinued in 2026, so this is no longer the default path for most people.
  • Alibaba Cloud Coding Plan — a subscription with its own dedicated endpoint, separate from standard pay-as-you-go keys.
  • API Key — the workhorse. OpenAI-compatible, Anthropic, or Google GenAI protocols, covering Model Studio/DashScope, OpenRouter, ModelScope, and self-hosted/local servers.

Most of this guide is about the API-key route, because that's where the 401s live.

How config actually resolves

Qwen Code reads config from ~/.qwen/settings.json (C:\Users\<user>\.qwen\settings.json on Windows). The fields that matter for auth are modelProviders, env, security.auth.selectedType, and model.name.

But settings.json isn't the only source. Config resolves in this priority order, highest to lowest:

  1. CLI flags
  2. System/exported environment variables
  3. .env file (search order: .qwen/.env.env~/.qwen/.env~/.env)
  4. The env field inside settings.json

This ordering is the single most important thing to understand for debugging 401s. A OPENAI_API_KEY you exported in your shell three weeks ago overrides the key in your settings.json. You edit the file, restart, and nothing changes — because the stale exported variable still wins.

When in doubt, check what's actually in your environment (env | grep -i openai on macOS/Linux) before you touch settings.json.

The protocol-key-naming gotcha

This one burns everybody once. Inside modelProviders, the top-level key is the protocol/auth type, and it must be exactly one of openai, anthropic, or gemini. That key decides which SDK handles the request:

Protocol keySDK usedUse for
openaiOpenAI Node SDKModel Studio, OpenRouter, Ollama, LM Studio, vLLM, any OpenAI-compatible endpoint
anthropicAnthropic SDKAnthropic-protocol endpoints
geminiGoogle GenAI SDKGemini-protocol endpoints

If you invent a key — say openai-custom, or dashscope, or openrouter — the entire entry is silently skipped. No error. No warning. The model just never shows up in the /model picker, and you'll spend an hour wondering why. If your model is missing after editing settings.json, the protocol key is the first thing to check.

A couple of related rules: each provider entry needs an id (the model identifier sent to the API) and an envKey. And envKey holds the name of an environment variable, not the key value itself. Putting your literal sk-... string into envKey is a classic misconfiguration. Optional fields include name (display name, falls back to id), description, baseUrl (defaults to the provider's official URL), and generationConfig.

Two more sharp edges worth knowing:

  • Duplicate model IDs within the same authType aren't supported — the first occurrence wins, later ones are skipped with warnings.
  • A selected provider's generationConfig replaces all lower-layer config atomically. The provider layer is impermeable: fields you don't define become undefined rather than inheriting from the rest of settings.

Model Studio / DashScope: get the region right

For OpenAI-compatible API-key auth, the relevant environment variables are OPENAI_API_KEY (auth), OPENAI_BASE_URL (endpoint override), and OPENAI_MODEL (model selection). Protocol-specific variants exist too: ANTHROPIC_API_KEY and GEMINI_API_KEY.

Model Studio (DashScope) is OpenAI-compatible, but it publishes different base URLs per region, and this is the number-one cause of 401s with Alibaba's service:

RegionOpenAI-compatible base URL
China / Beijinghttps://dashscope.aliyuncs.com/compatible-mode/v1
Singapore / Internationalhttps://dashscope-intl.aliyuncs.com/compatible-mode/v1
US / Virginiahttps://dashscope-us.aliyuncs.com/compatible-mode/v1
Hong Konghttps://cn-hongkong.dashscope.aliyuncs.com/compatible-mode/v1

A key created in the international (Singapore) console used against the China endpoint is rejected with a 401. The key is bound to the region's account where it was created — you have to pair it with the matching regional base URL. If your key is "definitely correct" and still 401s, this is almost certainly why.

A minimal OpenAI-compatible settings.json looks like this:

{
  "modelProviders": {
    "openai": [
      {
        "id": "qwen3-coder-plus",
        "baseUrl": "https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
        "envKey": "DASHSCOPE_API_KEY"
      }
    ]
  },
  "env": {
    "DASHSCOPE_API_KEY": "your-key-here"
  },
  "security": { "auth": { "selectedType": "openai" } },
  "model": { "name": "qwen3-coder-plus" }
}

Note selectedType matches the protocol key (openai), and model.name matches the id. One caveat on the variable name: the env var for the Model Studio key is reported inconsistently across sources — DASHSCOPE_API_KEY, BAILIAN_API_KEY, and for Coding Plan BAILIAN_CODING_PLAN_API_KEY all show up. Verify the exact name against the current official docs for your account; whatever it is, envKey must point to that same name.

Standard key vs. Coding Plan

Standard pay-as-you-go DashScope keys and Alibaba Cloud Coding Plan keys use different endpoints. The Coding Plan uses a dedicated base URL (reported as https://coding.dashscope.aliyuncs.com/v1 for China, with an international equivalent). Use a Coding Plan endpoint with a standard key — or the reverse — and you get 401s. Match the key type to its endpoint.

Available model IDs (e.g., qwen3-coder-plus, qwen3-coder-next, and broader qwen-max/plus/flash, plus partner models like GLM and Kimi via the Coding Plan) vary by region and endpoint. Confirm what's live in your console rather than copying an ID from a blog.

OpenRouter: global, free-ish, and OpenAI-compatible

OpenRouter is the easiest escape hatch if you're hitting the China region block, because it's globally reachable and OpenAI-compatible. The setup is pure environment variables:

export OPENAI_API_KEY=sk-or-v1-...        # your OpenRouter key
export OPENAI_BASE_URL=https://openrouter.ai/api/v1
export OPENAI_MODEL=qwen/qwen3-coder:free  # provider/model[:tag] format

Note the model name format: provider/model[:tag], not a bare model ID.

Two OpenRouter-specific failures to watch for:

  • 401 / "Incorrect API key provided" while it's actually hitting api.openai.com. This happens when the OpenAI provider ignores your configured base URL and falls back to OpenAI's default. The fix is to ensure OPENAI_BASE_URL is set to exactly https://openrouter.ai/api/v1 and to clear any conflicting env vars or settings entries that might override it. (Remember the resolution order — an exported var beats settings.json.)
  • "404 no tool use." Qwen Code is agentic and leans on tool/function calls. If OpenRouter routes you to a provider variant that doesn't support tool calling, the request fails. Pin a tool-capable route.

Also budget for OpenRouter's own free-tier rate limits — reported as roughly 20 requests/minute and around 200 requests/day per model. Those are OpenRouter's limits, not Qwen Code's, and they change.

Local: Ollama, LM Studio, vLLM

Fully local works because these servers all speak OpenAI-compatible HTTP. Just point the base URL at the local endpoint:

ServerLocal base URL
Ollamahttp://localhost:11434/v1
LM Studiohttp://localhost:1234/v1
vLLMhttp://localhost:8000/v1

Set OPENAI_BASE_URL to the local endpoint and OPENAI_MODEL to the served model. For servers that don't require auth, any non-empty placeholder value works for the API key — the SDK just needs something in the field.

If you want local-first economics without giving up a cloud fallback, you can also point OPENAI_BASE_URL at a local-first AI gateway like Wide Area AI, which presents an OpenAI-compatible endpoint that serves requests from your own hardware first and fails over to cloud providers (OpenAI/Gemini/Claude) when a local node is unavailable. Requests served locally carry zero per-token cost, and because the gateway is OpenAI-compatible the same OPENAI_BASE_URL/OPENAI_MODEL setup applies unchanged.

Keeping your key out of git

Because envKey references a variable name and the real key lives in env or a .env file, the safe pattern is to put the key in a .env that's gitignored — or in exported shell variables — and keep settings.json free of literal secrets. Given the .env search order, .qwen/.env is a clean per-project home for it.

Bottom line

Qwen Code 401s are rarely about a bad key. Work the causes in order: (1) confirm the protocol key in modelProviders is exactly openai/anthropic/gemini, or the provider is silently dropped; (2) confirm envKey names a variable and the key lives in env/.env; (3) check the config resolution order — a stale exported OPENAI_API_KEY will quietly override your settings; (4) for Model Studio, match the key's region to its base URL, and don't mix standard and Coding Plan endpoints; (5) for OpenRouter, set OPENAI_BASE_URL to exactly https://openrouter.ai/api/v1 and pin a tool-capable model. Get those five right and the 401s disappear. The tools and quotas move fast, so verify current model IDs, env-var names, and free-tier terms in the live console before you commit to a setup.

Frequently Asked Questions

Find answers to common questions

Add an entry under modelProviders.openai with an id (the model ID the API expects), a baseUrl (the regional DashScope OpenAI-compatible endpoint), and an envKey naming the environment variable that holds your key. Store the actual key in your env field or a .env file, set security.auth.selectedType to "openai", and set model.name to the same id. The selectedType must match the protocol key you used.

The most common causes are a region mismatch (a key from one regional console used against a different region's base URL), a stale exported OPENAI_API_KEY overriding settings.json, or putting the literal key in envKey instead of a variable name. Check which key is actually being sent and confirm the base URL matches the region where the key was created.

Model Studio publishes region-specific OpenAI-compatible base URLs — China/Beijing, Singapore/International, US/Virginia, and Hong Kong each have their own. A key is bound to the region's console where it was created; pairing it with a different region's base URL produces a 401. Match the key to its regional endpoint.

Set OPENAI_API_KEY to your OpenRouter key (it starts with sk-or-v1-), OPENAI_BASE_URL to https://openrouter.ai/api/v1, and OPENAI_MODEL to a provider/model[:tag] value such as qwen/qwen3-coder:free. OpenRouter is OpenAI-compatible and works globally, which sidesteps the China region block.

That happens when the OpenAI provider ignores your configured base URL and falls back to the default, producing "Incorrect API key provided." Make sure OPENAI_BASE_URL is set to exactly https://openrouter.ai/api/v1 and clear any conflicting environment variables or settings that might override it.

The top-level key is the protocol/auth type and determines which SDK processes the request — openai uses the OpenAI Node SDK, anthropic uses the Anthropic SDK, gemini uses the Google GenAI SDK. Only those three values are valid. A non-standard key like "openai-custom" is silently skipped, so your model never appears in the /model picker.

It holds the NAME of an environment variable, not the key value. Putting the literal key string in envKey is a common misconfiguration. Store the real key in your env field or a .env file under the variable name that envKey points to.

All three expose OpenAI-compatible servers. Set OPENAI_BASE_URL to the local endpoint — Ollama at http://localhost:11434/v1, LM Studio at http://localhost:1234/v1, vLLM at http://localhost:8000/v1 — and set OPENAI_MODEL to the served model. For servers that don't require auth, any non-empty placeholder value works as the API key.

The Qwen OAuth free tier was reportedly discontinued in 2026, with the daily quota cut sharply shortly before. Users are directed to the Alibaba Cloud Coding Plan or API-key auth instead. Treat the exact dates and quota numbers as moving targets and confirm current terms before relying on them.

Qwen Code is an agentic CLI that depends on tool/function calling. If OpenRouter routes you to a provider variant that doesn't support tool calls, the request fails with a 404 no-tool-use error. Pin a tool-capable model/provider route on OpenRouter.

Building Something Great?

Our development team builds secure, scalable applications. From APIs to full platforms, we turn your ideas into production-ready software.