One key. Every model. Codex and Claude Code included.
Codex CLI and Claude Code now connect to unbottled.ai directly, next to OpenCode, Continue, Aider and Cline. One base URL, one key, one command per tool.
Your coding agent is locked to one vendor's models. Want a second opinion from another lab, a cheaper model for grunt work, or a model that does not refuse? That means another account, another key, another bill.
unbottled.ai speaks all three formats coding agents use: OpenAI chat completions, the OpenAI Responses API and the Anthropic Messages API. Nothing to install in between. Point a tool at us once, then switch between Claude, GPT, DeepSeek, GLM, Kimi, Qwen and the uncensored models by changing one model id.
Why bother
- One key, one balance. No separate accounts at Anthropic, OpenAI, DeepSeek, Moonshot and Z.ai.
- Uncensored models in your editor. Security research, red-team prompts, fiction tooling, data that trips mainstream filters. You pick the filter level, not the vendor.
- Right model per task. A frontier model for the hard refactor, a flash model for renames and test scaffolding. Same config, different id.
- Same credits as the chat app, same prices. Every response reports what it cost.
Get a key and a base URL
Two values. Every tool below needs exactly these.
Create a key under Settings > API keys. It starts with sk-unb- and is shown once. The API is part of every paid plan: an active subscription or any credit pack unlocks it.
For OpenAI-style tools: Codex, OpenCode, Continue, Aider, Cline. The locale in the path only changes the language of error messages.
Anthropic base URL: https://unbottled.ai/api/en-GLOBAL
For Claude Code and Anthropic SDKs. Same URL without /v1: they add /v1/messages themselves.
export UNBOTTLED_API_KEY="sk-unb-YOUR_KEY"
curl https://unbottled.ai/api/en-GLOBAL/v1/models \
-H "Authorization: Bearer $UNBOTTLED_API_KEY"curl https://unbottled.ai/api/en-GLOBAL/v1/chat/completions \
-H "Authorization: Bearer $UNBOTTLED_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"glm-5.3","messages":[{"role":"user","content":"Hello"}]}'Keep the key in an environment variable, never in a file you commit. The curl call proves the key works and lists every model id your account can call, with context size, tool support and credit prices.
Every tool connects directly
Coding agents speak three different wire formats. We serve all three, on the same key and the same models.
- Codex CLI: OpenAI Responses API.
- Claude Code: Anthropic Messages API.
- OpenCode, Continue, Aider, Cline: OpenAI chat completions.
Anything else with a base URL field works the same way: base URL, key, model id.
# OpenAI-compatible tools (chat completions or Responses API)
Base URL: https://unbottled.ai/api/en-GLOBAL/v1
API key: sk-unb-YOUR_KEY
Model: glm-5.3
# Anthropic-compatible tools (Messages API)
Base URL: https://unbottled.ai/api/en-GLOBAL
API key: sk-unb-YOUR_KEY
Model: glm-5.3Codex CLI
OpenAI's terminal agent. Reads your repo, runs commands, edits files. Tested with Codex CLI 0.118.0.
Codex speaks the Responses API, and so do we. The one command defines the provider inline: nothing to edit, nothing to install. For daily use, append the config once and start Codex with the profile.
UNBOTTLED_API_KEY="sk-unb-YOUR_KEY" codex \
-c 'model_providers.unbottled={name="unbottled.ai",base_url="https://unbottled.ai/api/en-GLOBAL/v1",env_key="UNBOTTLED_API_KEY",wire_api="responses"}' \
-c model_provider=unbottled \
-m glm-5.3[model_providers.unbottled]
name = "unbottled.ai"
base_url = "https://unbottled.ai/api/en-GLOBAL/v1"
env_key = "UNBOTTLED_API_KEY"
wire_api = "responses"
[profiles.unbottled]
model_provider = "unbottled"
model = "glm-5.3"export UNBOTTLED_API_KEY="sk-unb-YOUR_KEY"
codex --profile unbottledSwitch models with -m or the model line in the profile. Keep wire_api = "responses": current Codex accepts nothing else.
Claude Code
Anthropic's terminal agent. Plans, edits, runs tests, spawns subagents. Tested with Claude Code 2.1.323.
Claude Code reads its gateway from environment variables. ANTHROPIC_BASE_URL is the base URL without /v1. ANTHROPIC_MODEL sets the main model. The OPUS and SONNET defaults cover the model picker and plan mode, the HAIKU default moves background jobs such as session titles to a cheap model, and CLAUDE_CODE_SUBAGENT_MODEL covers subagents. CLAUDE_CODE_MAX_CONTEXT_TOKENS tells Claude Code the real context size of a non-Claude model, so it compacts at the right point.
ANTHROPIC_BASE_URL="https://unbottled.ai/api/en-GLOBAL" \
ANTHROPIC_AUTH_TOKEN="sk-unb-YOUR_KEY" \
ANTHROPIC_MODEL="glm-5.3" \
ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5.3" \
ANTHROPIC_DEFAULT_SONNET_MODEL="glm-5.3" \
ANTHROPIC_DEFAULT_HAIKU_MODEL="glm-5.3-flash" \
CLAUDE_CODE_SUBAGENT_MODEL="glm-5.3" \
CLAUDE_CODE_MAX_CONTEXT_TOKENS="1048576" \
CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1" \
claude{
"env": {
"ANTHROPIC_BASE_URL": "https://unbottled.ai/api/en-GLOBAL",
"ANTHROPIC_AUTH_TOKEN": "sk-unb-YOUR_KEY",
"ANTHROPIC_MODEL": "glm-5.3",
"ANTHROPIC_DEFAULT_OPUS_MODEL": "glm-5.3",
"ANTHROPIC_DEFAULT_SONNET_MODEL": "glm-5.3",
"ANTHROPIC_DEFAULT_HAIKU_MODEL": "glm-5.3-flash",
"CLAUDE_CODE_SUBAGENT_MODEL": "glm-5.3",
"CLAUDE_CODE_MAX_CONTEXT_TOKENS": "1048576",
"CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1"
}
}claudeWant Claude itself? Drop the model lines. Claude Code asks for its usual Claude ids and we route them to our matching Claude model, billed in credits.
Claude Code sends a big system prompt, over 30k input tokens even for a trivial task. A cheap default model keeps that affordable.
OpenCode
Open-source terminal agent with a TUI and a headless run mode. Tested with OpenCode 1.19.5.
Save the config as opencode.json in your project, or as ~/.config/opencode/opencode.json for every project. The key stays in your environment. Add any id from GET /v1/models to the models map, then pick one with /models in the TUI.
UNBOTTLED_API_KEY="sk-unb-YOUR_KEY" \
OPENCODE_CONFIG_CONTENT='{"provider":{"unbottled":{"npm":"@ai-sdk/openai-compatible","options":{"baseURL":"https://unbottled.ai/api/en-GLOBAL/v1","apiKey":"{env:UNBOTTLED_API_KEY}"},"models":{"glm-5.3":{}}}},"model":"unbottled/glm-5.3"}' \
opencode{
"$schema": "https://opencode.ai/config.json",
"provider": {
"unbottled": {
"npm": "@ai-sdk/openai-compatible",
"name": "unbottled.ai",
"options": {
"baseURL": "https://unbottled.ai/api/en-GLOBAL/v1",
"apiKey": "{env:UNBOTTLED_API_KEY}"
},
"models": {
"glm-5.3": { "name": "GLM-5.3" },
"claude-sonnet-5.5": { "name": "Claude Sonnet 5.5" },
"glm-5.3-uncensored": { "name": "GLM 5.3 Uncensored" }
}
}
},
"model": "unbottled/glm-5.3"
}export UNBOTTLED_API_KEY="sk-unb-YOUR_KEY"
opencodeContinue
Coding assistant for VS Code and JetBrains, plus the cn CLI. Tested with Continue 1.5.47.
name: unbottled
version: 1.0.0
schema: v1
models:
- name: GLM-5.3
provider: openai
model: glm-5.3
apiBase: https://unbottled.ai/api/en-GLOBAL/v1
apiKey: ${{ secrets.UNBOTTLED_API_KEY }}
roles: [chat, edit, apply]export UNBOTTLED_API_KEY="sk-unb-YOUR_KEY"
cn --config ./config.yamlsecrets.UNBOTTLED_API_KEY resolves from your environment. Add -p with a prompt for a headless run. The IDE extension reads ~/.continue/config.yaml: put the same model entry there.
Aider
Pair programming in your terminal, commits included. Tested with Aider 0.86.2.
One command, no config file. Aider wants openai/ in front of the model id and strips it before it calls us. --edit-format diff keeps edits small; without it Aider falls back to resending whole files for model ids it does not know. Name the files to edit on the command line, as usual with Aider.
OPENAI_API_BASE="https://unbottled.ai/api/en-GLOBAL/v1" \
OPENAI_API_KEY="sk-unb-YOUR_KEY" \
aider --model openai/glm-5.3 --edit-format diff --no-show-model-warningsCline
Autonomous coding agent, in VS Code and as a CLI. Tested with Cline 3.0.74.
Two commands with the Cline CLI: save the provider once, then run cline. Base URL, key and model id are the same three values as everywhere else.
cline auth -p openai -k "sk-unb-YOUR_KEY" -b "https://unbottled.ai/api/en-GLOBAL/v1" -m glm-5.3clineWhich model for which job
All of these call tools, which agents need. Ids are what goes in your config.
Hard problems
Large refactors, unfamiliar codebases, multi-step debugging. Higher credit prices, fewer wrong turns.
- claude-sonnet-5.5Claude Sonnet 5.5
- claude-opus-5.5Claude Opus 5.5
- gpt-6.1-solGPT-6.1 Sol
- kimi-k3.1-proKimi K3.1 Pro
- deepseek-v4-proDeepSeek V4 Pro
Cheap and fast
Renames, tests, boilerplate, background jobs. A fraction of a frontier model's price. Good default for agents that send big prompts.
- glm-5.3GLM-5.3
- glm-5.3-flashGLM-5.3 Flash
- qwen-3.8-flashQwen 3.8 Flash
- claude-haiku-5.5Claude Haiku 5.5
Uncensored
Same agent workflow, no refusal reflex. Exploit analysis, red-team tooling, adult fiction pipelines, scrapers other models lecture you about. You stay responsible for what you build.
- glm-5.3-uncensoredGLM 5.3 Uncensored
- venice-deepseek-v4.1-flash-uncensoredDeepSeek V4.1 Flash Uncensored
- qwen-3.6-plus-uncensoredQwen 3.6 Plus Uncensored
- venice-uncensoredVenice Uncensored 1.2
Gotchas we hit
So you do not have to.
- Copy the base URL exactly, /api/<locale>/v1 included. Without the locale you get a redirect that some clients drop. Without /api you get an HTML page instead of JSON.
- Claude Code gets the base URL without /v1. With /v1 it calls /v1/v1/messages and gets a 404.
- Use the exact id from GET /v1/models, like glm-5.3. Aider wants openai/ in front. Claude Code's built-in Claude ids are mapped for you to our newest Claude of the same family. Any other unknown id returns 404 model_not_found.
- HTTP 402 with paid_plan_required means the account has no paid plan yet. Any credit pack fixes it.
- A model without tool support returns 400 tools_not_supported once the agent sends tools. Check supports_tools in GET /v1/models.
- Each key allows 60 requests per minute. Agents fire many small calls. If you hit 429, give the agent its own key.
Wired up in one command.
Create a key, copy the block for your tool, pick a model. The API docs cover every endpoint, field, error code and streaming detail.