# Codex CLI

> Use Codex CLI with MirAPI through its OpenAI-compatible Responses API: a single provider block with wire_api = "responses" pointed at the MirAPI /v1 base URL.

Codex CLI is OpenAI's terminal coding agent. It reads a TOML config, so MirAPI plugs in as a custom model provider — no plugin required.

## What you need

| Element | Value |
|---|---|
| Base URL | `https://api.mirapi.ai/v1` — Codex appends `/responses` itself |
| API key | `MIRAPI_API_KEY`, referenced by `env_key` |
| Wire API | `responses` — the only value Codex accepts today |

## Configure

1. Create a key in https://console.mirapi.ai → **API Keys** and export it:

```bash
export MIRAPI_API_KEY=sk-...
```

2. Add a provider block to `~/.codex/config.toml` (or `$CODEX_HOME/config.toml`):

```toml
model = "deepseek-chat"
model_provider = "mirapi"

[model_providers.mirapi]
name = "MirAPI"
base_url = "https://api.mirapi.ai/v1"
env_key = "MIRAPI_API_KEY"
wire_api = "responses"
```

3. To leave the default config untouched, save this block as `~/.codex/mirapi.config.toml` and launch the CLI with the profile flag:

```bash
codex -p mirapi
```

:::tip
Verify the key and check available model IDs before starting Codex:

```bash
curl https://api.mirapi.ai/v1/models -H "Authorization: Bearer $MIRAPI_API_KEY"
```
:::

## Verify with a message

```bash
codex exec "Reply with exactly: connected to MirAPI"
```

The reply should contain `connected to MirAPI`. Any HTTP error carries a MirAPI `request id` at the end of the message — keep it when reporting an issue.

## Configuration reference

| Key | Purpose | Value for MirAPI |
|---|---|---|
| `model` | Model ID the CLI requests | `"deepseek-chat"` — verbatim from `GET /v1/models` |
| `model_provider` | Which provider block to use | `"mirapi"` |
| `name` | Display name in the CLI | `"MirAPI"` |
| `base_url` | Base URL Codex appends `/responses` to | `https://api.mirapi.ai/v1` |
| `env_key` | Environment variable holding the key | `MIRAPI_API_KEY` |
| `wire_api` | API dialect Codex speaks | `"responses"` — the only supported value |
| `model_reasoning_effort` | Optional reasoning strength for reasoning models | `"low"`, `"medium"`, `"high"` |

## Protocol and capabilities

Codex speaks the OpenAI **Responses API** (`POST /v1/responses`) on MirAPI's OpenAI-compatible surface at `https://api.mirapi.ai/v1`. Anthropic's `/v1/messages` and Gemini's `generateContent` are not reachable from Codex — `wire_api = "responses"` is the only dialect it accepts.

What works through this path when the chosen model supports it:

- **Tool calling** via the OpenAI `tools` / `tool_choice` format.
- **Structured outputs** via `response_format` (json_schema / JSON mode).
- **Web search** for models that advertise the capability in the catalogue.
- **Reasoning** — set `model_reasoning_effort` to control strength; reasoning tokens bill as output.
- **Prompt caching** is enabled automatically for OpenAI-compatible models.

Responses stream as standard SSE (`data:` lines, ending with `data: [DONE]`).

## Errors and troubleshooting

| Status | Meaning | What to do |
|---|---|---|
| 401 | Key missing, invalid, or unknown | Fix the exported `MIRAPI_API_KEY` |
| 403 | Key valid but rejected — balance, whitelist, quota, or IP | Resolve the cause, then retry |
| 413 | Payload too large | Reduce the request size |
| 429 | Rate limited | Jittered exponential backoff (1s→2s→4s, cap ~30s); no `Retry-After` header |
| 500 | Gateway or upstream error | Idempotent requests can be retried safely |

The gateway does not retry on your behalf. Errors use the OpenAI envelope `{"error":{"message","type","param","code"}}`, where `type` is `new_api_error` (gateway) or `upstream_error` (upstream failure, message sanitized). Every message ends with the MirAPI request ID — include it in support tickets.

## Billing

MirAPI billing is prepaid: top up a USD balance in https://console.mirapi.ai; there is no subscription, monthly fee, or minimum spend, and the balance never expires. Chat usage is metered per token (input / output / cache-read), and reasoning tokens count as output. When the balance runs out, requests return 403 — top up and the same key works again immediately. Reconcile usage in the console billing log, `GET /api/usage/token` (aggregate), or `GET /api/log/token` (per-request).

## Troubleshooting

- **`wire_api` must be `"responses"`.** The `"chat"` value was removed; a config with it fails to load.
- **The base URL must end in `/v1`.** Codex appends `/responses` to whatever you give it, so a bare `https://api.mirapi.ai` produces a wrong path.
- **Model names are verbatim.** `model = "deepseek-chat"` must match `GET /v1/models` exactly.
- **403 from a valid key** usually means the model is not on the key's whitelist or the balance is exhausted — top up or adjust the key, then retry.
- **401** usually means the CLI cannot read the key — confirm `MIRAPI_API_KEY` is exported in the shell that starts Codex.

## Related links

- [Quickstart](/docs/quickstart)
- [OpenAI compatibility](/docs/openai-compat)
- [Models & pricing](/docs/models)
- [Reasoning models](/docs/guides/reasoning)
- [Errors](/docs/api-reference/errors)