---
title: "Codex CLI setup with one API key"
canonical: https://uplinkswitch.ai/guides/codex-cli
generated: 2026-11-04T10:46:24.667Z
source: https://uplinkswitch.ai/guides/codex-cli
base_url: https://api.uplinkswitch.com/v1
---

[›uplinkswitch](https://uplinkswitch.ai/)

[api.uplinkswitch.com/v1](https://uplinkswitch.ai/models)[Console](https://uplinkswitch.ai/console)

[›uplinkswitch](https://uplinkswitch.ai/)

# Codex CLI

One provider block in ~/.codex/config.toml, one key, every model on the list, pay as you go with no subscription.

Checked 2026-10-28

·[All guides](https://uplinkswitch.ai/guides)·[Models](https://uplinkswitch.ai/models)

At the end you have Codex CLI on a provider block that points at `https://api.uplinkswitch.com/v1`, with one API key from the console and any model id on the [list](https://uplinkswitch.ai/models) as `model`, Claude included. No subscription and no OpenAI key: each request bills per token to the prepaid balance behind that key, and the live table below is the price on each model today.

## Before you start

You need Codex CLI installed, an account on the [console](https://uplinkswitch.ai/console) with credit on it, and one key created there. Create the key for Codex alone, so its requests sit apart from any other tool on the Usage page. Nothing is installed on the UplinkSwitch side: the base URL `https://api.uplinkswitch.com/v1`  and the key are the whole configuration.

## Where the settings are

`~/.codex/config.toml`, the user config. A project can carry its own `.codex/config.toml`, but that file ignores `model_provider` and `model_providers`, so the provider block goes in the user file ([Codex docs](https://developers.openai.com/codex/config-advanced), read 2026-10-28).

Codex only speaks the Responses API to a custom provider: `wire_api = "responses"` is the one value and the default. The gateway answers it at `/v1/responses` for every chat model, so the Anthropic-style variables from the [Claude Code guide](https://uplinkswitch.ai/guides/claude-code) do not apply here.

## The provider block

Add this to `~/.codex/config.toml`. The table id, `uplinkswitch`, is yours to choose as long as it is not `openai`, `ollama` or `lmstudio`, which Codex reserves; `model_provider` must match it.

~/.codex/config.toml

```
model = "claude-sonnet-5-5"
model_provider = "uplinkswitch"

[model_providers.uplinkswitch]
name = "UplinkSwitch"
base_url = "https://api.uplinkswitch.com/v1"
env_key = "UPLINKSWITCH_API_KEY"
wire_api = "responses"
http_headers = { "HTTP-Referer" = "https://uplinkswitch.ai", "X-Title" = "Codex CLI" }
```

`base_url` is the `/v1` root, as in the provider examples in the Codex docs. `http_headers` adds two static headers to every request so the console can attribute the traffic to Codex on the Usage page; `env_http_headers` does the same from environment variables if you prefer. The retry knobs `request_max_retries` (4), `stream_max_retries` (5) and `stream_idle_timeout_ms` (300000) keep their defaults unless you set them.

## The key

`env_key` names the environment variable Codex reads the key from. Export it before you start Codex:

shell

```
export UPLINKSWITCH_API_KEY="sk-uplink-live-..."
codex
```

The variable is the provider's credential (Codex docs, read 2026-10-28); nothing else is set up on the Codex side.

## Which model id to use

Any chat id on the [Models page](https://uplinkswitch.ai/models) goes in `model`, Claude included: tool calling works on every chat model here, and Codex needs it for each file read, edit and command. The ids in the table below are the coding flagships; the [uncensored coding builds](https://uplinkswitch.ai/uncensored) take the same slot.

To switch for one run pass `-m`, or keep a profile file next to the config with its own `model` and start with `--profile`. Profile files use top-level keys, not a `[profiles.name]` table (Codex docs, read 2026-10-28).

profile

```
# ~/.codex/opus.config.toml
model = "claude-opus-5-5"
model_provider = "uplinkswitch"
```

shell

```
codex -m gpt-6.1-sol
codex --profile opus
```

## Price per token

| Model | Input / 1M | Cached input / 1M | Output / 1M | List input | List output | Under list |
| --- | --- | --- | --- | --- | --- | --- |
| [Claude Sonnet 5.5](https://uplinkswitch.ai/models/claude-sonnet-5-5) | $1.20 | $0.075 | $3.00 | $2.00 | $10.00 | 40% on input |
| [Claude Opus 5.5](https://uplinkswitch.ai/models/claude-opus-5-5) | $2.80 | $0.15 | $10.00 | $4.00 | $20.00 | 30% on input |
| [GPT-6.1 Sol](https://uplinkswitch.ai/models/gpt-6.1-sol) | $0.60 | $0.06 | $3.00 | $2.00 | $10.00 | 70% on input |
| [Gemini 3.1 Pro Preview](https://uplinkswitch.ai/models/gemini-3.1-pro-preview) | $1.20 | $0.12 | $7.20 | $2.00 | $12.00 | 40% on input |
| [DeepSeek V4 Pro 0813](https://uplinkswitch.ai/models/deepseek-v4-pro-0813) | $0.792 | $0.0625 | $1.188 | $1.32 | $3.96 | 40% on input |
| [Kimi K3](https://uplinkswitch.ai/models/kimi-k3) | $0.90 | $0.12 | $4.50 | $3.00 | $15.00 | 70% on input |

USD per million tokens, live from GET /v1/catalog. List: the developer’s own published price. Cached input bills at the cache-read rate where the model has one, with no switch to set.

Codex sends the conversation and every tool result back on each step, so the input column decides what a session costs, and cached input brings it down further on the models that have a cache-read rate. The [Claude Code pricing post](https://uplinkswitch.ai/blog/claude-code-api-cost) works an hour of agent steps into days and months at these rates, and the 30-day price lock on each top-up holds them.

## Check it

From a shell, the same key should list the models:

shell

```
curl https://api.uplinkswitch.com/v1/models -H "Authorization: Bearer $UPLINKSWITCH_API_KEY"
```

Then send one request the way Codex does, to `/v1/responses`. `-i` prints the headers: `x-uplink-request-id` names the request, and on a non-streamed answer `x-uplink-charge` is what it cost in USD.

shell

```
curl -i https://api.uplinkswitch.com/v1/responses \
  -H "Authorization: Bearer $UPLINKSWITCH_API_KEY" \
  -H "content-type: application/json" \
  -d '{"model": "claude-sonnet-5-5", "input": "Say ok."}'
```

Then run `codex` and ask it something. The request shows on the [console](https://uplinkswitch.ai/console) Usage page within seconds, with its tokens and the same charge, filterable by key and model.

## Errors you will see

-   `401 invalid_api_key`: the key is wrong, revoked, or the variable named in `env_key` is not exported in the shell that runs Codex. Export it again, or copy the key from the console.
-   `404 model_not_found`: the id in `model` is not on the Models page at this base URL. Copy it from the page rather than typing it.
-   `402 insufficient_balance`: the balance does not cover the request. Top up in the console.
-   `402 monthly_limit_reached`: the key hit the monthly spend limit you set on it. Raise it in the console, or wait for the first of the month.
-   `403 scope_denied`: the key carries a model allowlist and this id is not on it. Pick an allowed id or use a key without the limit.
-   `429 rate_limited`: the key hit its requests-per-minute or concurrency limit. The response carries `retry-after` in seconds; Codex retries on its own up to `request_max_retries`.
-   The block has no effect: `model_provider` does not match the table id, or the block sits in a project `.codex/config.toml`, which ignores it. Move it to `~/.codex/config.toml`.

## Good to know

-   `-c key=value` overrides any config key for one run; values parse as TOML where they can.
-   `model_reasoning_effort` in the same file sets the reasoning level for models that take one.
-   Cached input bills at the cache-read price on the model page by itself; there is no switch to set.
-   A monthly spend limit and a model allowlist on the Codex key cap what it can spend and which ids it can call.

## The same key in other agents

[Claude Code](https://uplinkswitch.ai/guides/claude-code) takes two environment variables; [OpenCode](https://uplinkswitch.ai/guides/opencode) and [OpenClaw](https://uplinkswitch.ai/guides/openclaw) read a provider block much like this one; [Cline](https://uplinkswitch.ai/guides/cline), [Kilo Code](https://uplinkswitch.ai/guides/kilo-code) and [Cursor](https://uplinkswitch.ai/guides/cursor) take the base URL and key in a settings panel. One balance serves all of them, and a key per tool keeps the spend apart in the console.

## Questions

### 

Yes. Codex takes a custom provider as a model\_providers table in ~/.codex/config.toml with a base\_url and an env\_key, and model\_provider points at it (Codex docs, read 2026-10-28). The block on this page is that table filled in for https://api.uplinkswitch.com/v1.

### 

Yes. Set model to claude-sonnet-5-5 or claude-opus-5-5 under the provider block above. Codex speaks the Responses API, and every model on the list answers it at https://api.uplinkswitch.com/v1/responses, so the Claude ids need no second provider. Claude Sonnet 5.5 is $1.20 per million input tokens and $3.00 per million output tokens here today.

### 

Not with a custom provider. Codex reads the key named in env\_key and sends every request to base\_url, so no ChatGPT plan and no OpenAI key are involved. The bill is per token to the prepaid balance behind the key.

### 

~/.codex/config.toml, the user config. A project can add .codex/config.toml, but that file ignores model\_provider and model\_providers, so the provider block has to live in the user file (Codex docs, read 2026-10-28).

### 

Change model in config.toml, pass -m with an id for one run, or keep a profile file such as ~/.codex/opus.config.toml and start with --profile opus (Codex docs, read 2026-10-28). Any id on the Models page works under the same provider.

### 

The id in model is not on the Models page at this base URL, so the gateway returned 404 model\_not\_found. Copy the id from the Models page rather than typing it; a dot, a dash or a date suffix out of place is enough. Also check base\_url ends in /v1 and model\_provider matches the table name.

Get a key in the [console](https://uplinkswitch.ai/console): prepaid credit, no subscription, 30-day price lock.

## Related

-   [Claude Code pricing](https://uplinkswitch.ai/blog/claude-code-api-cost)
-   [Claude Code alternatives compared](https://uplinkswitch.ai/blog/claude-code-alternatives)
-   [Claude Code setup](https://uplinkswitch.ai/guides/claude-code)
-   [OpenCode Zen vs one key](https://uplinkswitch.ai/guides/opencode)
-   [pi coding agent setup](https://uplinkswitch.ai/guides/pi)
-   [Aider setup](https://uplinkswitch.ai/guides/aider)
-   [OpenClaw setup](https://uplinkswitch.ai/guides/openclaw)
-   [Claude Sonnet 5.5](https://uplinkswitch.ai/models/claude-sonnet-5-5)
-   [GPT-5.3-Codex](https://uplinkswitch.ai/models/gpt-5.3-codex)
-   [Kimi K2.7 Code](https://uplinkswitch.ai/models/kimi-k2.7-code)
-   [GLM 5.3](https://uplinkswitch.ai/models/glm-5.3)
-   [Claude API pricing](https://uplinkswitch.ai/pricing/claude)
-   [GPT API pricing](https://uplinkswitch.ai/pricing/gpt)
-   [Kimi API pricing](https://uplinkswitch.ai/pricing/kimi)
-   [GLM API pricing](https://uplinkswitch.ai/pricing/glm)
