Running Claude Code on your MirAPI balance
Point Claude Code at MirAPI with three environment variables, add Codex CLI with one TOML block, and let both agents spend from the same prepaid balance.
Coding agents burn tokens fast, and they rarely stay on one model. Running Claude Code against Anthropic, Codex against OpenAI and everything else on a third provider means three accounts, three keys and three invoices to reconcile at the end of the month. MirAPI replaces all of that with one key and one balance. That includes Claude Code, because MirAPI serves the Anthropic Messages API natively instead of translating it.
Claude Code
Claude Code talks to POST /v1/messages, which MirAPI implements directly, so the setup is three environment variables:
export MIRAPI_API_KEY=sk-...
export ANTHROPIC_BASE_URL="https://api.mirapi.ai"export ANTHROPIC_AUTH_TOKEN="$MIRAPI_API_KEY"export ANTHROPIC_MODEL="deepseek-chat"Two details can cost you an afternoon:
- Do not append
/v1to the base URL. Anthropic clients build the full path themselves, sohttps://api.mirapi.aiis the entire value. Leave/v1on the end and the request resolves to/v1/v1/messages, which 404s. - Define
MIRAPI_API_KEYbeforeANTHROPIC_AUTH_TOKEN. The token variable expands when the profile is sourced. If the key is not defined yet, you export an empty string, and every request comes back 401.
Prefer ANTHROPIC_AUTH_TOKEN over ANTHROPIC_API_KEY: the first sends Authorization: Bearer and the second sends x-api-key. MirAPI accepts both, but if ANTHROPIC_API_KEY still holds a real Anthropic key from an earlier setup, Claude Code may prompt you or fall back to Anthropic. Set it to an empty string if you are not sure.
Reload the shell, run claude and check /status: the base URL and auth token it reports should be MirAPI’s.
Scoping it to one project
If you would rather not touch your shell profile, put the same values in .claude/settings.local.json at the project root:
{ "env": { "ANTHROPIC_BASE_URL": "https://api.mirapi.ai", "ANTHROPIC_AUTH_TOKEN": "sk-...", "ANTHROPIC_MODEL": "deepseek-chat" }}Codex CLI
Codex reads its configuration from a TOML file instead of environment variables, and it expects the Responses API, so you add MirAPI as a custom provider:
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"Codex wants /v1 on the base URL and Claude Code must not have it: Claude Code builds the path for you, while Codex appends to whatever you hand it.
To leave your default config untouched, save the block as ~/.codex/mirapi.config.toml and start Codex with codex -p mirapi.
Choosing a model
Both agents take a model name from the catalog, and GET /v1/models is the authoritative list. It returns the exact id to pass, along with context length and per-1M-token pricing:
curl https://api.mirapi.ai/v1/models -H "Authorization: Bearer $MIRAPI_API_KEY"Two constraints when picking one:
- Your key has to be whitelisted for that model, or the request comes back 403.
- Both agents lean hard on tool calling. A model that cannot call tools will answer your first message and then be useless as an agent.
Keeping a long run from surprising you
- Cap the key. A MirAPI key can carry a quota cap, a validity period, an IP allowlist and a model whitelist. Give a long-running agent its own key with a quota, so the worst case is that it stops instead of draining your balance.
- Reasoning tokens bill as output. On a thinking-heavy model the output side dominates the invoice, so the input rate is not the number to plan around.
- Cache reads cost less than fresh input. Agents replay a large, stable prefix every turn, which is exactly the pattern prompt caching rewards (see Prompt caching).
- Reconcile from the logs. The Platform billing log,
GET /api/usage/tokenfor account totals, andGET /api/log/tokenfor per-request detail all report the same data.
When something breaks
| Code | What it means | What to do |
|---|---|---|
| 401 | Key missing, invalid or unknown | Check that the variable is set and not empty |
| 403 | Valid key, but the request is refused (balance, whitelist, quota or IP) | Top up, or lift the restriction on the key |
| 429 | Rate limited | Back off with jitter (1s → 2s → 4s). The gateway sends no Retry-After header and does not retry for you. |
One harmless error is worth recognizing: Claude Code calls /v1/messages/count_tokens during startup, and MirAPI returns 404. The endpoint is not implemented, and nothing depends on it.
Every error message ends with a request ID. Keep it, because it identifies the exact request and its billing entry in the logs.
Related reading
- Claude Code: the reference setup
- Codex CLI: full configuration table
- Claude Code advanced
- Billing & top-ups