Configure Aider for Router One: base URL, key and openai/ model strings
Aider is an open-source AI pair programmer for the terminal: it edits the files you add to the chat, keeps a map of your repository and commits each change to git. It reaches models through LiteLLM, and its documented path for an OpenAI-compatible endpoint is two environment variables plus a model string: OPENAI_API_BASE set to https://api.router.one/v1, your Router One key in OPENAI_API_KEY, and --model openai/ followed by the exact catalog ID, such as openai/anthropic/claude-sonnet-5. Every chat turn then reaches Router One as POST /v1/chat/completions on your key and is billed and recorded in Dashboard → Logs, while the repository map, edit formats and git history stay in Aider. Aider has no presets for Router One's IDs, so it runs them on generic defaults, including whole-file edits and the main model for commit messages and history summaries; this guide shows the two small files that change that. Checked against Aider 0.86.2 on 2026-09-27.
Install Aider 0.86.2 and create a dedicated key
Aider's install docs recommend the aider-install helper, which puts Aider in its own Python environment: run python -m pip install aider-install, then aider-install. The current release on PyPI, aider-chat 0.86.2 (February 12, 2026), requires Python 3.10, 3.11 or 3.12 and pins LiteLLM 1.81.10, the library that actually sends the requests. aider --version should print aider 0.86.2. Then create a Router One key that only Aider uses and give it a maxSpend cap. Aider sends requests you never type, such as a commit message after each edit and a summary when the chat history grows, so the cap is the hard stop, and a separate key keeps Aider's spend apart from your other tools when you filter Dashboard → Logs by API key.
python -m pip install aider-install aider-install aider --version # aider 0.86.2
Configure Aider to use the Router One base URL
Export both variables in the shell that starts Aider (on Windows, run setx for each one and open a new terminal), then launch Aider from your project directory. OPENAI_API_BASE takes the /v1 base URL, because LiteLLM appends /chat/completions itself; the full endpoint URL would double the path. The model string is openai/ plus the exact catalog ID, and LiteLLM splits it at the first slash only: openai selects its OpenAI-compatible client, and the rest, anthropic/claude-sonnet-5 here, is sent unchanged as the model field. For catalog IDs that carry a vendor prefix the string therefore looks doubled, and that is correct: openai/openai/gpt-5.5 sends openai/gpt-5.5. IDs without a vendor prefix, such as deepseek-v4-flash or grok-4.7, take a single openai/. Dropping the inner prefix sends a bare name such as gpt-5.5 instead; the gateway accepts most official bare names as aliases but not all of them, and a model name it does not know returns 404, so keep the full catalog ID. Flags work as well: --openai-api-base and --openai-api-key, or the AIDER_OPENAI_API_BASE and AIDER_OPENAI_API_KEY variables, are copied into OPENAI_API_BASE and OPENAI_API_KEY at startup, and --api-key openai=sk-… sets the key the same way:
# macOS / Linux export OPENAI_API_BASE=https://api.router.one/v1 export OPENAI_API_KEY=sk-your-router-one-key cd /path/to/your-project aider --model openai/anthropic/claude-sonnet-5 # openai/ + the exact catalog ID; IDs keep their own vendor prefix: # aider --model openai/openai/gpt-5.5 # aider --model openai/deepseek-v4-flash # Windows (then open a new terminal): # setx OPENAI_API_BASE https://api.router.one/v1 # setx OPENAI_API_KEY sk-your-router-one-key
Send one billed test and match it in Logs
aider --model openai/anthropic/claude-sonnet-5 --message "Reply with OK" --no-auto-commits sends a single prompt and exits; --message (or -m) skips the interactive chat. For a model it has no metadata for, Aider first prints "Warning for openai/anthropic/claude-sonnet-5: Unknown context window size and costs, using sane defaults." That is expected, and the next two sections deal with it. The prompt goes out as one POST /v1/chat/completions with stream set to true, because Aider streams chat replies by default (--no-stream turns that off). In Dashboard → Logs the matching request shows the model, input and output tokens, cost, status, total time and, for a streamed request that produced output, time to first token (TTFT). Expect more input tokens than the prompt suggests: every request carries Aider's edit-format instructions and, inside a git repository, an excerpt of the repository map. If Aider reports a 404 whose message starts with "no route matched POST /chat/completions", OPENAI_API_BASE is missing /v1; "no route matched POST /v1/v1/chat/completions" means /v1 appears twice.
aider --model openai/anthropic/claude-sonnet-5 --message "Reply with OK" --no-auto-commits
Tell Aider how to treat Router One's IDs
Aider ships presets for the model names it knows, and Router One's catalog IDs match none of them, so it falls back to generic defaults: the whole edit format, which makes the model send back every file it changes in full; the main model doubling as the weak model; temperature 0; and a chat-history budget of 1,024 tokens, above which older turns are summarized. The repository map stays on at 1,024 tokens. A .aider.model.settings.yml file changes this per model. Aider reads it from your home directory, the git root and the current directory, in that order, with later files taking priority; --model-settings-file adds one more. The name must equal the --model string exactly. edit_format: diff switches to search-and-replace blocks, so the model returns only the lines it changes. weak_model_name moves commit messages and history summaries to a cheaper chat ID. use_temperature: false stops Aider from sending temperature 0, as Aider's own presets do for GPT-5 models; treat it as a precaution for GPT IDs, not a known requirement. accepts_settings: ["reasoning_effort"] lets --reasoning-effort through: for a model Aider has no settings for, it ignores that flag and prints a warning instead. Router One does not turn reasoning_effort into a thinking setting for Claude IDs, except on Claude Opus 5.5, where it maps the value to output_config.effort (none and minimal become low); other models may ignore it or reject the request with 400.
- name: openai/anthropic/claude-sonnet-5 edit_format: diff weak_model_name: openai/anthropic/claude-haiku-4.5 - name: openai/openai/gpt-5.5 edit_format: diff weak_model_name: openai/deepseek-v4-flash use_temperature: false accepts_settings: ["reasoning_effort"]
Register context windows in .aider.model.metadata.json
The metadata file removes the warning and gives Aider a context window to size things by. It is loaded from the same three places, plus --model-metadata-file. Each key is the full --model string, litellm_provider is openai and mode is chat. Take max_input_tokens from the model's page on /models, which shows the window rounded (1.05M, 200K), and write it as a whole number rounded down: 1000000 for anthropic/claude-sonnet-5, openai/gpt-5.5 and deepseek-v4-flash, 200000 for anthropic/claude-haiku-4.5. List the weak models too, because Aider checks them the same way. Leave out output limits and prices. Aider's docs note that it never enforces token limits and only reports the errors an API returns, and without prices Aider's own cost display simply has nothing to show; Router One's Logs are the billing record. A registered window changes three things. Aider warns before sending a chat it estimates is larger than the window. The chat-history budget grows to one sixteenth of the window, capped at 8,192 tokens, so summaries run less often. And the repository map grows to one eighth of the window, between 1,024 and 4,096 tokens, which can add about 3,000 input tokens to each request; --map-tokens pins the size, and --map-tokens 0 turns the map off. Without either file, --edit-format diff --weak-model openai/anthropic/claude-haiku-4.5 --max-chat-history-tokens 8192 on the command line covers most of the same ground.
{
"openai/anthropic/claude-sonnet-5": { "max_input_tokens": 1000000, "litellm_provider": "openai", "mode": "chat" },
"openai/anthropic/claude-haiku-4.5": { "max_input_tokens": 200000, "litellm_provider": "openai", "mode": "chat" },
"openai/openai/gpt-5.5": { "max_input_tokens": 1000000, "litellm_provider": "openai", "mode": "chat" },
"openai/deepseek-v4-flash": { "max_input_tokens": 1000000, "litellm_provider": "openai", "mode": "chat" }
}Keep the endpoint in config files, and watch project .env files
Aider loads .env files from your home directory, the git root and the current directory, then the file named by --env-file, and each one overrides values that are already set, including variables you exported in the shell. That is the most common reason a working setup breaks inside one project: a project .env that sets OPENAI_API_KEY or OPENAI_API_BASE for your own application silently replaces the Router One values, so requests fail with 401 or go to another endpoint and never appear in Dashboard → Logs. Put the Router One values in ~/.env and keep them out of project .env files, point --env-file at a dedicated file, or pass --openai-api-base and --openai-api-key, which are applied after every .env file. For everything except the key, .aider.conf.yml takes Aider's long option names as keys (model, openai-api-base, edit-format, weak-model, auto-commits) and is read from the home directory, the git root and the current directory, with the last file winning. Keep the key out of any file you commit.
model: openai/anthropic/claude-sonnet-5 openai-api-base: https://api.router.one/v1 edit-format: diff weak-model: openai/anthropic/claude-haiku-4.5 # The key goes in ~/.env as OPENAI_API_KEY=sk-your-router-one-key, not in this file
Where the extra requests in Logs come from
A session bills more requests than the prompts you type. Auto-commits are on by default: after each edit Aider applies, it asks the weak model for a one-line commit message and commits the change, and --no-auto-commits turns that off. When the chat history passes its budget, the weak model summarizes older turns. With no weak model configured, both jobs run on the main model, which is often the most expensive ID in the session. Architect mode (--architect, or /architect inside the chat) splits each change into two calls: the main model plans the change and the editor model, set with --editor-model openai/<catalog-id>, writes the edits. Aider waits up to 600 seconds for a response by default, and --timeout changes that. Aider's regular edit formats are plain text, so the chat model you pick does not need tool calling; only the legacy function-based edit formats send tool definitions. Aider never calls /v1/responses or /v1/messages: every request, including commit messages and summaries, is a Chat Completions call.
Which model ID should Aider send?
Copy the exact model ID from /models, preserving case, hyphens, and version suffixes; do not substitute a display name. Open its detail page and match the supported API endpoints, context window, and capabilities such as tool calling to the provider and features selected in Aider. A catalog listing does not mean the client can use every feature of that model. Give each client or application a dedicated API key with a maxSpend cap.
Which API protocol is Aider using?
OpenAI-compatible describes an interface format; it does not make Chat Completions (/v1/chat/completions), Responses (/v1/responses), and Anthropic Messages (/v1/messages) interchangeable. Check the installed client version, provider configuration, and actual request path against the model detail page and API compatibility fact sheet. A successful plain-text chat does not establish support for hosted tools, conversation state, or file-editing features.
Verify the Aider call in your request trace
Send a simple text request from Aider, then match its trace in Dashboard → Logs by time, model, and request_id: tokens, cost, latency, and status. Next, test streaming, tool calls, and multi-turn history separately. For failures, retain the actual request path, full error message, and request_id. If there is no matching log, either the request never reached the gateway (client configuration or connectivity) or the gateway refused it before calling a model — a 401 for the key, a 402 for funds, a 429 from your key's or account's limits, or a 400 or 404 for the model ID or endpoint; a streamed request that failed before any output may have no log either. The status and error message the client received tell which, so check them before attributing the error to the gateway or upstream.
FAQ
Why does the GPT model string start with openai/openai/?
Because Aider's model string joins two things: the LiteLLM client to use, then the model name to send. openai/ selects the OpenAI-compatible client that reads OPENAI_API_BASE, and LiteLLM strips only that first segment, so the catalog ID after it, openai/gpt-5.5 with its own vendor prefix, reaches Router One unchanged. Claude and Gemini IDs work the same way (openai/anthropic/claude-sonnet-5, openai/google/gemini-3.7-flash), while IDs without a vendor prefix, such as grok-4.7, need a single openai/. Don't shorten the string with Aider's anthropic/ or gemini/ prefixes: those select LiteLLM's native clients, which ignore OPENAI_API_BASE and look for their own API keys.
Aider says "Unknown context window size and costs, using sane defaults". Should I fix it?
You can keep working, and Aider's own docs say the warning is usually safe to ignore. On a gateway, though, the defaults it announces cost money: whole-file edits, the main model for commit messages and summaries, and no window to size the history and repository map by. Add the model to .aider.model.metadata.json (the key is the full --model string) and give it an edit format and a weak model in .aider.model.settings.yml, as shown above. --no-show-model-warnings only hides the message; it changes none of the defaults.
Why is Aider rewriting whole files?
Because whole is the edit format Aider uses for model names it has no preset for, and every Router One ID is one of those. With whole, the model returns the complete text of every file it changes, so output tokens grow with file size rather than with the size of the change. Set edit_format: diff for the model in .aider.model.settings.yml, or start Aider with --edit-format diff, and the model returns search-and-replace blocks for the changed lines only.
Why do I see small extra requests in Logs after each edit?
They are commit messages. Auto-commits are on by default, and after each applied edit Aider asks the weak model for a one-line message; once the chat history passes its budget, the weak model also writes summaries. Without a weak model configured, both run on your main model. Set weak_model_name (or --weak-model) to a cheaper chat ID such as openai/anthropic/claude-haiku-4.5 or openai/deepseek-v4-flash, or turn commits off with --no-auto-commits. Filtering Dashboard → Logs by model shows the split.
Does Aider need a model with tool calling?
No. Aider's regular edit formats (whole, diff and the other text formats) ask the model for plain text that Aider applies itself, so tool calling is not required; only the legacy function-based formats send tool definitions. Pick any current chat model from /models. Image-generation IDs in the catalog cannot serve chat turns.
My exported key is ignored and nothing shows up in Logs. What happened?
Most likely a .env file overrode it. Aider loads .env from your home directory, the git root and the current directory, and each file overrides variables that are already set, including ones exported in the shell. If your project's .env sets OPENAI_API_KEY or OPENAI_API_BASE for your own application, Aider uses those values instead: requests fail with 401 or go to another endpoint. Pass --openai-api-base and --openai-api-key explicitly (they are applied last), point --env-file at a dedicated file, or remove the two variables from the project .env.
Can I plan with one model and edit with another?
Yes, with architect mode. Start Aider with --architect (or switch with /architect in the chat) and set --editor-model openai/<catalog-id>: the main model proposes each change and the editor model turns it into file edits. Both run on the same Router One key as separate requests, so Dashboard → Logs lists them under their own model IDs. A common split is a strong model such as openai/openai/gpt-5.5 for planning and a cheaper one for the edits.
Where do I save OPENAI_API_BASE so I don't export it every session?
In ~/.env (OPENAI_API_BASE=https://api.router.one/v1 and OPENAI_API_KEY=sk-…), which Aider loads on every start, or as openai-api-base in ~/.aider.conf.yml with the key kept in ~/.env. On Windows, setx OPENAI_API_BASE https://api.router.one/v1 and setx OPENAI_API_KEY sk-… store both permanently for new terminals. Keep project .env files free of these two variables, since they would override the saved values.
Which models can Aider use through the gateway?
Choose a current catalog model that supports both the endpoint and the features Aider uses. Check /models and the model detail page for the exact ID, current rates, and capabilities; a family name such as GPT or Claude is not a compatibility guarantee. A client that lists a model has only read the ID, from its own configuration or from GET /v1/models; verify an actual request too.
Models are listed, but requests fail with 400 or 404. What should I check?
Record the actual request path and error message, then check the exact model ID. A 400 can indicate invalid parameters, unsupported tools, or a model/endpoint mismatch; a 404 can indicate an incorrect path or missing resource, so it does not by itself establish that a model was retired. If the error says must be called via, use the named endpoint or select a model supported on the current endpoint. Do not add or remove /v1 or /chat/completions across all clients indiscriminately.
Does this work from Mainland China?
Yes. The gateway is reachable from Mainland China without a VPN, and the configuration is identical to the global setup.
How do I debug a 401/402/403/429?
Start from what your client received: the status, the error body and the X-Request-ID header. A 401 (missing, unknown, revoked or expired key), a 402 (wallet balance, or the key's maxSpend cap) and a 429 from your key's or account's rate limits are refused before any model is called, so they never appear in Dashboard → Logs — nor does a 400 or 404 for a wrong model ID or endpoint. For 401, check that the full key is sent and still active in Dashboard → API Keys; for 402, top up or raise the key's maxSpend; for a 403, keep the full error body. For 429, back off and retry later; a 429 that does show up in Logs came back from upstream after the gateway's retries. Keep the request_id and follow the error-codes reference.