Windsurf: connecting to Claude and GPT
Windsurf may let you add a custom provider and reach Claude, GPT and GLM with one key. Here are the settings fields, the limitations, and where people usually get stuck.
4 min · · Updated · IDE
A caveat up front: at the time of writing, Windsurf doesn't let you set your own base URL for every model; check the current BYOK (bring-your-own-key) settings in your version. If your build has a Base URL field for an OpenAI-compatible provider or for Anthropic, both paths work through the gateway with the same fetch_... key — the only difference is the base URL and headers. If there's no such field, a reliable alternative is the Cline, Roo Code or Kilo Code extensions in VS Code, which support a custom base URL out of the box (see https://zukko.pro/docs/ide-integrations/vscode-extensions).
Where to find the settings
In Windsurf this lives under model management (Settings → Models / Cascade → Manage Models). Look for Base URL and API Key fields — for an OpenAI-compatible provider and/or for Anthropic. The fetch_... key goes in unchanged, but without a Base URL field requests won't reach the gateway and the key won't work; in that case, use the alternatives from the top of the article.
OpenAI-compatible slot: GPT and GLM
The Base URL field needs exactly:
https://api.zukko.pro/v1
Put the key, prefix included, into the API Key field. Windsurf adds Authorization: Bearer and the /chat/completions path itself. In the model list, or in the free-text model field, enter the exact catalogue id: gpt-5.6-sol, gpt-5.6-luna, glm-5.3, glm-5.3-flash (current list: GET https://api.zukko.pro/v1/models).
If Windsurf restricts the choice to a dropdown for a specific provider and won't take a custom name, use the "custom model" text field that most Windsurf builds expose for non-standard providers.
Anthropic slot: Claude without the extra /v1
For Claude the base URL is without /v1:
https://api.zukko.pro
This is the most common mistake spot: copy the same address used for the OpenAI-compatible field and add /v1 to it, and every Claude request through this slot starts failing with 404 while the key still looks accepted. Anthropic clients append the path to /v1/messages themselves, so the suffix is redundant here.
Models for this slot: claude-opus-5-5 and claude-sonnet-5.
Checking outside the IDE
When Windsurf stays silent or shows no readable error text, it is faster to test the key directly with curl, bypassing the interface:
curl https://api.zukko.pro/v1/messages \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-H "anthropic-version: 2023-06-01" \
-d '{"model":"claude-sonnet-5","max_tokens":64,"messages":[{"role":"user","content":"test"}]}'For the OpenAI-compatible path:
curl https://api.zukko.pro/v1/chat/completions \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.6-sol","messages":[{"role":"user","content":"test"}]}'If both come back fine but Windsurf still refuses to work, the problem is in the IDE itself (cached settings, a stale config, the wrong field) rather than in the key or the gateway. A full restart after changing the Base URL usually helps — some builds cache the provider list at startup.
Common error codes
If curl returns a JSON error instead of a model response, the rest is straightforward:
401— the key never arrived intact (a stray space from pasting is the usual cause).402withinsufficient_balance— the balance ran out, the request never reached a model, and retrying after topping up costs nothing extra.404withmodel_not_found— a typo in the model id; check againstcurl https://api.zukko.pro/v1/models(no key needed).400withmodel_retired— the model was pulled from the catalogue, and the error text names the replacement.503withmodel_disabled— the model is disabled in the catalogue; pick another one from/v1/models.403withmodel_not_allowed_for_key— this key has an allowed-models list configured in the dashboard, and the requested model isn't on it.
Web search for models without one built in
GLM and some GPT models in this catalogue don't have their own web search, unlike some Claude modes. If Windsurf needs an answer that requires fresh data and the model has no built-in search, you can hit a separate endpoint before the main request and feed the result into the prompt yourself:
curl https://api.zukko.pro/v1/web-search \
-H "Authorization: Bearer fetch_your_key" \
-H "Content-Type: application/json" \
-d '{"query":"latest Windsurf changelog updates"}'Windsurf doesn't do this automatically — it's a manual technique for when an API call needs more current context than the model itself has.
How much a key has spent in total
It's handy to check spend history separately from the overall balance — the /v1/usage endpoint returns history with cursor-based pagination. Note that it covers the whole account: all keys together, no per-key filter:
curl "https://api.zukko.pro/v1/usage?limit=20" \
-H "Authorization: Bearer fetch_your_key"Useful when several people work in Windsurf at once — /v1/usage shows which models and requests the money went to, not just the final remaining balance. Current limits and prices per model live at GET /v1/models/info, also without a key.
Limits, cost, and what to watch in the dashboard
Every key can get a daily or monthly dollar spending cap right from its page in the dashboard (https://zukko.pro/app/api-keys) — worth creating a separate key for Windsurf with its own cap so IDE experiments don't eat into the shared balance. Regular (non-streaming) responses carry X-Zukko-Cost-Micros (the cost of that specific request in micro-dollars) and X-Fetch-Balance-Cents (the remaining balance after the charge, also in microdollars despite the name) — visible with curl's -i flag. The streaming responses an IDE receives don't carry these headers — check that spend in the dashboard or /v1/usage.
If this is your first connection and the balance is zero, you can get $0.50 for testing once: link Telegram in the dashboard, subscribe to @zukkopro, and press "Check". There's no starting balance. Top-ups by card, SBP, or crypto (from $1) are available on the /app/payments page.
zukko
Pay 25×
less
for Claude Code & ChatGPT
One fetch_* key and base URL api.zukko.pro — for Cursor, Claude Code, Codex, and any SDK.
Related articles
- JetBrains AI Assistant not working: causes and workaroundsAI Assistant will not activate, stays silent or is off for some files. We go through the causes in the JetBrains docs and connect your own models via a gateway.
- DeepSeek in VS Code: connecting through Cline, Kilo Code and ContinueWe connect DeepSeek to Cline, Kilo Code and Continue with a single key, choose between Flash and Pro, and estimate the cost of a working day with an agent in the editor.
- GitHub Copilot alternatives with your own API key: what to chooseCline, Kilo Code, Continue and Cursor work with your own key. We compare where they live, how they connect to a gateway and how to estimate spend.
- Invalid API key in opencode: why the key is rejected and how to checkThe Invalid API key error in opencode almost always comes down to four causes. We test the key outside opencode and find where the chain breaks.