One gateway, three protocols: OpenAI Chat Completions, OpenAI Responses and Anthropic Messages (including Anthropic token counting). Point any OpenAI-compatible SDK or coding agent (Claude Code, Codex CLI, OpenCode…) at this domain, authenticate with one of your API keys, and request any enabled model. All URLs on this page are generated from the host and install path serving it.
Sign in, open API Keys and generate a key. It starts with sk- — copy it when it is created, or use Show key on the same page later (revoked keys can no longer be displayed).
Use the base URLs below. OpenAI-style clients need the /v1 suffix; Claude Code and the official Anthropic SDKs use the root URL without it.
Choose a Model ID from the catalog at the bottom of this page and send your first request.
These URLs are generated from the host and install path serving this page, so they work unchanged on any host, sub-folder, port or HTTPS setup this application is installed under. Hosts are validated against the operator's allowlist; on an unrecognised host they fall back to localhost.
| Client type | Base URL | |
|---|---|---|
| OpenAI-compatible OpenAI SDKs, Codex CLI, OpenCode, LangChain, curl, anything speaking /v1/chat/completions |
https://cheapaapi.com/v1 | |
| Anthropic-compatible Claude Code and Anthropic SDKs — they append /v1/messages themselves |
https://cheapaapi.com |
Why two URLs? OpenAI SDKs treat the base URL as a prefix for /chat/completions, so it includes /v1. Claude Code and the official Anthropic SDK append /v1/messages to the base URL themselves, so their base URL must not include /v1. AI SDK's @ai-sdk/anthropic (used by OpenCode) appends only /messages, so its baseURL does include /v1 — see Connect OpenCode.
Every endpoint accepts your key as Authorization: Bearer YOUR_API_KEY. Anthropic-style clients may instead send x-api-key: YOUR_API_KEY — both are accepted on every endpoint.
CheapaAPI exposes an Anthropic Messages-compatible endpoint for Claude Code. Use the base URL without /v1: https://cheapaapi.com — Claude Code adds the Messages path itself.
On Windows, save the variables for your user account, then open a new terminal:
On macOS or Linux, add the three export lines to ~/.zshrc or ~/.bashrc, then open a new terminal.
ANTHROPIC_MODEL is optional — replace claude-opus-5.5 with any Model ID from the Available models list, or leave it unset and pick models inside Claude Code.ANTHROPIC_API_KEY also works on this gateway — it sends the same key via the x-api-key header.count_tokens calls are answered locally — no upstream request, no charge (see POST /v1/messages/count_tokens)./status inside the REPL.Troubleshooting: 401 → wrong key · 404 / model not found → the ANTHROPIC_MODEL ID is not in your catalog · connection refused → wrong base URL (must be the root, without /v1).
CheapaAPI supports the Responses API used by Codex CLI. A separate profile keeps your normal Codex settings unchanged.
Edit (or create) your Codex config file and add the profile below:
~/.codex/config.toml%USERPROFILE%\.codex\config.tomlIf your config.toml already defines model / model_provider at the top, leave them as they are — the profile only overrides them when you start Codex with --profile.
Persist for your user account, then reopen the terminal:
Add the export line to ~/.zshrc / ~/.bashrc to keep the key across sessions.
To use another CheapaAPI model for one session:
POST https://cheapaapi.com/v1/responses — see POST /v1/responses for current compatibility.env_key is just a name — it must match the environment variable you set. Keep the key out of the TOML file itself./status — it shows the active provider, base URL and model.OpenCode uses two CheapaAPI provider adapters. GPT, Grok and other OpenAI-compatible models use @ai-sdk/openai-compatible. Claude-protocol models must use @ai-sdk/anthropic so OpenCode calls CheapaAPI's Anthropic Messages endpoint.
Open or create:
~/.config/opencode/opencode.jsonc%USERPROFILE%\.config\opencode\opencode.jsoncopencode.jsonc in the project rootYou can replace or extend the lists with IDs from the Available models section below. Keep Claude-protocol models under cheapaapi-anthropic — putting them under the OpenAI-compatible provider produces a Messages endpoint error.
Persist: [Environment]::SetEnvironmentVariable("CHEAPAAPI_API_KEY", "sk-your-api-key", "User"), then open a new terminal.
Add the export line to ~/.zshrc / ~/.bashrc to keep the key across sessions.
For Claude-protocol models:
You can also run /models inside OpenCode and select a configured CheapaAPI model.
List the models enabled on this gateway with their context capacity, supported parameters and per-1M-token pricing. Requires a valid API key. Clients use the response to size requests before sending them. Listing still works while an account is awaiting email verification, so pre-configured clients can enumerate models before their first generation call.
type and display_name mirror Anthropic's model-list fields (Claude clients read them); context_length, max_output_tokens, supported_parameters and pricing are OpenRouter-style extras. OpenAI SDKs ignore all of them. supported_parameters is null when the model accepts every parameter, max_output_tokens is null when unbounded, and pricing.long_context is present only when the operator configured a long-context tier.
OpenAI Chat Completions format — streaming and non-streaming. Only n=1 is supported; system/developer, user, assistant and tool roles are accepted.
The response is a standard OpenAI chat.completion object including usage with prompt_tokens_details.cached_tokens and completion_tokens_details.reasoning_tokens (reported as 0 when the upstream does not provide them).
Set "stream": true. Chunks are forwarded to you incrementally as the upstream provider generates them — nothing is buffered server-side. The stream ends with a usage chunk and data: [DONE] — usage is always sent, so stream_options.include_usage is not required. The request ID is returned in the X-Request-Id response header.
OpenAI Responses API format (including streaming events like response.output_text.delta). Accepts input as a string or an array of message/function-call items. Top-level instructions is honored as the system prompt. Text and image parts are supported; audio input is not accepted here.
Anthropic Messages format for Claude-style clients and agents. Requires max_tokens (1–200000). Authentication uses the same key via x-api-key (sent automatically by Anthropic SDKs) or the standard Bearer header. system, tool_use/tool_result blocks and thinking are supported.
Remember: raw curl uses the full path above, but Claude Code and Anthropic SDKs want the base URL without /v1 — see Connect Claude Code.
Anthropic-compatible token counting, used by Claude Code to size a conversation before sending it. The count is estimated by the gateway — no upstream request is made, nothing is billed and no rate-limit quota is used. The body takes the same model and messages shapes as POST /v1/messages; max_tokens is not required.
The count covers the messages plus any tools definitions and ignores max_tokens, so it matches the gateway's own prompt estimate.
Send standard OpenAI tools definitions to any model with the tool_calling capability. Tool call deltas are streamed in OpenAI format (tool_calls in delta) and completed tool calls are returned in the message body for non-streaming requests. Anthropic-style tool_use/tool_result blocks are converted automatically on /v1/messages.
You can use real-time web search in two ways: (1) Live Web Grounding inside Chat / LLM requests, or (2) Direct Web Search API (POST /v1/web/search) to retrieve structured web search results or sourced answers directly.
Enable live web search on any supported model by appending :online (or :online/linkup-deep for deep research) to the model ID, or by passing "web_search": true in the request body:
Also accepts "web_search": true, "web_search_options": {"search_context_size": "medium"}, OpenRouter-style "plugins": [{"id": "web"}], OpenAI Responses "tools": [{"type": "web_search_preview"}], and Anthropic "tools": [{"type": "web_search_20250305", "name": "web_search"}]. Billing combines the model's token usage plus the per-search fee.
POST /v1/web/searchExecute a standalone web search without calling a chat model. Supports depth ("standard" or "deep"), output_type ("searchResults" or "sourcedAnswer"), max_results (1–20), include_domains, exclude_domains, from_date, and to_date.
Models with vision accept image input on every protocol. The gateway validates images before forwarding — unsupported input types, malformed images or oversized payloads return a clean 400 without consuming credits.
| Limit | Value |
|---|---|
| Formats | PNG, JPEG, WebP, GIF |
| Max size per image | 5 MB (decoded) |
| Max images per request | 8 via the API · 4 on the dashboard chat |
| Max total image payload | 20 MB (decoded) |
| Remote URLs | Must be public https:// URLs (private/loopback hosts are blocked), or use base64 data URLs |
A base64 data URL works in the same slot: {"type":"image_url","image_url":{"url":"data:image/png;base64,…"}}
Models whose Inputs include audio accept inline audio on Chat Completions (check the Available models table — most text/vision models do not). Send a base64 payload (no data: prefix) plus its container format:
Audio is forwarded only to OpenAI-compatible Chat Completions upstreams. /v1/responses does not accept input_audio, and Anthropic-protocol upstreams reject it with 400 unsupported_input — pick a chat-completions channel for audio models. Images, by contrast, are converted for every upstream protocol.
Images are billed as input tokens — exactly how OpenAI, Anthropic and Google charge for vision. The provider converts each image into input tokens (OpenAI: 512px tiles at 170 tokens each + 85 base; Anthropic ≈ width × height ÷ 750; Gemini: flat ~258) and reports them inside prompt_tokens / input_tokens in the usage. Your account is charged at the model's normal input price for those tokens — no separate image fee. Audio works the same way: it is billed as provider-reported input tokens with no separate fee (pre-authorization estimates each audio clip at roughly 1,600 tokens).
For models with the reasoning capability the gateway applies a default thinking effort of low automatically — small tasks stay fast and cheap. Any reasoning parameter you send yourself always wins over the default, and the default is skipped when the model's parameter policy does not allow reasoning parameters.
"reasoning_effort": "low" | "medium" | "high" (none, minimal and xhigh are also accepted and forwarded where the upstream supports them). OpenRouter-style "reasoning": {"effort": "..."} is accepted too."reasoning": {"effort": "low"}."thinking": {"type": "enabled", "budget_tokens": 2048} directly, or just "reasoning_effort": "low" and the gateway maps it to a thinking budget (low → 2048, medium → 8192, high → 16384, xhigh → 32768) that is always kept below your max_tokens. While thinking is enabled, temperature/top_p are dropped (Anthropic rejects them).Reasoning deltas stream as reasoning_content (chat), reasoning summary items (responses) or thinking blocks (messages), and reasoning tokens are included in usage when the provider reports them.
Each model advertises its real capacity via GET /v1/models (context_length, max_output_tokens). How oversized requests are handled:
400 context_length_exceeded (OpenAI wording) or prompt is too long (Anthropic wording on /v1/messages) — no credits are consumed. Coding agents treat these codes as a signal to compact their context.max_tokens exceeds the model's maximum output or the remaining context room, it is capped (not rejected). The response's usage always reflects the tokens actually processed.error event on streaming requests) and you are not charged.Some providers charge higher per-token rates once a request's input crosses a threshold (e.g. GPT-4.1 above 272K input tokens, Gemini 2.5 Pro above 200K). When an operator configures a threshold for a model, requests whose total input tokens exceed it are billed at the long-context rates, shown in pricing.long_context on GET /v1/models and in your dashboard pricing. Pre-authorization holds use the same tier, so the estimate matches the final charge.
Errors use OpenAI-compatible JSON (Anthropic shape on /v1/messages) with proper HTTP status codes:
| HTTP | type | When |
|---|---|---|
| 400 | invalid_request_error | Malformed body, unsupported input, context length exceeded |
| 401 | authentication_error | Missing/invalid/expired API key |
| 402 | insufficient_quota | Not enough credits for the pre-authorization estimate |
| 403 | permission_error | Email address not verified (only when the operator requires verification) |
| 404 | not_found_error | Unknown or disabled model |
| 413 | invalid_request_error | Request body too large (operator limit, default 4 MB) |
| 429 | rate_limit_error / insufficient_quota | Rate limit or spend cap reached; repeated failed key checks (60 per 2 minutes per IP) return auth_rate_limited |
| 500 | api_error | Internal server error — the hold is released and nothing is charged |
| 502/503 | api_error | Upstream provider failure (after automatic failover) |
| 503 | api_error | model_not_priced — the model has no pricing configured and cannot be billed |
Each request is pre-authorized against your credit balance (a hold equal to the estimated cost), then settled with the actual token usage when the response completes. Failed requests are never charged — holds are released automatically. Responses carry an X-Request-Id header you can quote in support requests (every endpoint except a successful GET /v1/models); the same ID appears in your usage history. Request bodies are capped by the operator (max_request_mb, default 4 MB) and larger bodies return 413 before any processing.
Per-key (default 60 req/min) and per-account (default 120 req/min) rate limits apply — a value of 0 means unlimited — along with optional daily/monthly spend caps, all as configured by the operator. The same limits cover the dashboard chat as well as the API.
| Model ID | Title | Inputs | Capabilities | Context | Max out | $/1M in/out |
|---|---|---|---|---|---|---|
| abliterated-hacker | abliterated-hacker | text,image | tool_calling,reasoning,web_search | 1,048,576 | 262,144 | $1.50 / $3.00 |
| deepseek-v4-free | deepseek-v4-free | text,image | tool_calling,reasoning,web_search | 264,000 | 64,000 | $0.00 / $0.00 |
| deepseek-v4.1-hacker | DeepSeek-V4.1-Hacker | text,image | tool_calling,web_search | 512,000 | 128,000 | $0.28 / $1.11 |
| ling-3.0 | ling-3.0-tiny | text | tool_calling,web_search | 262,144 | 32,768 | $0.02 / $0.07 |
| glm-5.3-hacker | glm-5.3-hacker | text,image | tool_calling,reasoning,web_search | 1,048,576 | 131,072 | $1.50 / $2.70 |
| mimo-v2.6-flash-hacker | mimo-v2.6-flash-hacker | text,image | tool_calling,reasoning,web_search | 1,048,576 | 65,536 | $0.60 / $1.80 |
| claude-opus-5.5 | claude-opus-5.5 | text,image | tool_calling,reasoning,web_search | 1,048,576 | 131,072 | $0.80 / $2.50 |
| claude-opus-4.8 | claude-opus-4.8 | text,image | tool_calling,reasoning,web_search | 1,048,576 | 131,072 | $0.80 / $2.50 |
| claude-fable-5.1 | claude-fable-5.1 | text,image | tool_calling,reasoning,web_search | 1,048,576 | 131,072 | $0.80 / $2.50 |
| gpt-5.6-sol | gpt-5.6-sol | text,image | tool_calling,reasoning,web_search | 1,048,576 | 131,072 | $0.60 / $1.88 |