# InferSpeed > InferSpeed is a pay-per-token model API with OpenAI- and Anthropic-compatible endpoints at https://api.inferspeed.ai, billed from a prepaid balance. Any agent harness that lets you set a base URL can use it. Models on sale and live prices: https://inferspeed.ai/model-plaza (JSON: https://inferspeed.ai/api/v1/public/pricing). The web app at https://inferspeed.ai is a JavaScript single-page app. The files below are plain text and readable without JavaScript. ## Settings - OpenAI-compatible base URL: `https://api.inferspeed.ai/v1` (clients append `/chat/completions` or `/responses`) - Anthropic-compatible base URL: `https://api.inferspeed.ai` (clients append `/v1/messages`; do not add `/v1` or any other path to it) - API key: read it from the environment variable `INFERSPEED_API_KEY`; send it as `Authorization: Bearer $INFERSPEED_API_KEY` (`x-api-key` also works) - Other wire formats on the same host and key: legacy `POST /v1/completions`; Gemini native `POST /v1beta/models/{model}:generateContent`, `:streamGenerateContent`, `:countTokens` (key via `x-goog-api-key`, Bearer or `?key=`). - Models: every public model ID is listed at https://inferspeed.ai/api/v1/public/pricing (`data.models[].id`). One API key calls every live model (`GET https://api.inferspeed.ai/v1/models` lists them); name the model in the request. - Use only the two base URLs above; there is no other API version or host (no `/v2`, no `/v3`). ## API - [API page (Markdown)](https://inferspeed.ai/developers.md): base URLs, auth, model ID, endpoints, copy-paste setup for Codex CLI, Claude Code, OpenCode, OpenClaw and OpenAI-compatible tools, SDK examples, errors and retries - [Agent setup](https://inferspeed.ai/agents.md): short instructions for an agent configuring itself to use InferSpeed - [Agent skill](https://inferspeed.ai/skill.md): base URLs, auth, model and price discovery, connection test, balance and usage, errors, and safety rules for handling the key - [Installer](https://inferspeed.ai/setup.sh): `curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- [--model ] [--dry-run]`; reads the key from INFERSPEED_API_KEY, shows a diff and backs up before writing one config file - [Prices (JSON)](https://inferspeed.ai/api/v1/public/pricing): USD per 1M tokens per model, no key needed - Vendor list prices: the pricing JSON publishes each model's vendor list price next to ours (`list_price`, present when known), so the two can be compared per model - Right now every model that has a vendor list price is 40% below it (the smaller of the input and output savings, rounded down; computed from the pricing JSON when this file was served) - Top up (agents): when the balance is low, call `POST https://inferspeed.ai/api/v1/billing/topup` with the API key and `{"amount_usd": 10}`, and give the returned payment URL to your user; details in [skill.md](https://inferspeed.ai/skill.md) ## Setup guides - [Codex CLI (Chinese)](https://inferspeed.ai/codex.md): configure Codex CLI with InferSpeed as a third-party API, common errors, live prices (page: https://inferspeed.ai/codex) - [GLM API, pay per token (Chinese)](https://inferspeed.ai/glm.md): glm-5.3 and glm-5.3-flash prices and Claude Code setup (page: https://inferspeed.ai/glm) - [Run Claude Code on GLM-5.3](https://inferspeed.ai/claude-code.md): Claude Code setup, live prices and limits (page: https://inferspeed.ai/claude-code) - [Claude Agent SDK on GLM-5.3](https://inferspeed.ai/claude-agent-sdk.md): Claude Agent SDK setup (TypeScript and Python), model routing, live prices and limits (page: https://inferspeed.ai/claude-agent-sdk) - [OpenAI Agents SDK on GLM-5.3 or Kimi K3](https://inferspeed.ai/openai-agents-sdk.md): OpenAI Agents SDK setup (Python), model routing, live prices and limits (page: https://inferspeed.ai/openai-agents-sdk) - [Everything in one file](https://inferspeed.ai/llms-full.txt): this index followed by developers.md, agents.md and skill.md ## Not supported - Models that are not on sale. One key calls every live model (each request is billed at the price of the model that served it; the key's spend limit, rate limits and IP allowlist apply to every model), but a model that is not on sale returns 404 `model_coming_soon` or `model_not_found` (agent default names such as `claude-*` and `gpt-*` are routed to a live model instead; see "Model routing" in developers.md). - Hosted tools such as web search are not executed by the gateway (in Codex CLI set `web_search = false`). - Above the default limits: 30 requests per minute and 5 concurrent requests per account, across all keys of the account. Over the limit you get HTTP 429 (`Retry-After` on `rate_limit_exceeded`); see https://inferspeed.ai/docs#rate-limits. - `glm-5.3-flash` is served on `POST /v1/chat/completions` only (not Responses or Messages). - No other API version or host: no `/v2`, no `/v3`. ## Optional - [Quickstart](https://inferspeed.ai/docs): the same setup for people - [Rate limits](https://inferspeed.ai/rate-limits): default limits and what happens when you exceed them - [Models and pricing](https://inferspeed.ai/model-plaza) - [Status](https://inferspeed.ai/status) # InferSpeed API: plug your agent in InferSpeed is a pay-per-token model API with OpenAI- and Anthropic-compatible endpoints, billed from a prepaid balance. Point your agent at the base URL, give it a key, pick the model. Nothing else changes. Models on sale and live prices: https://inferspeed.ai/model-plaza (JSON: https://inferspeed.ai/api/v1/public/pricing). Human-readable version: https://inferspeed.ai/docs ## The settings | Setting | Value | | ----------------------------- | ---------------------------------------------------------------------------- | | OpenAI-compatible base URL | `https://api.inferspeed.ai/v1` | | Anthropic-compatible base URL | `https://api.inferspeed.ai` (clients add `/v1/messages`) | | Authentication | `Authorization: Bearer $INFERSPEED_API_KEY` (`x-api-key` also works) | | Model IDs | Every public model, from `GET https://inferspeed.ai/api/v1/public/pricing` (`data.models[].id`) | | Models per key | Every live model (`GET /v1/models` with your key lists them) | | Context window | At least 324,955 prompt tokens accepted | | Max output tokens | 131,072 (`max_tokens` above this returns 400; reasoning tokens count toward it) | | Default limits | 30 requests per minute and 5 concurrent requests per account (see below) | `https://inferspeed.ai/v1` is the same gateway as `https://api.inferspeed.ai/v1`. The context window and max output above were measured on `glm-5.3`; each model's page on https://inferspeed.ai/model-plaza shows its own. The examples below use `glm-5.3`: put any public model ID in its place. **One key, every model.** An API key calls every live model: `glm-5.3`, `kimi-k3`, `MiniMax-M3` and the rest of `GET /v1/models`. Put the model ID in the request; nothing else changes. Each request is billed at the price of the model that served it, and the key's spend limit, rate limits and IP allowlist apply to every model. A model that is not on sale returns 404 `model_coming_soon` or `model_not_found` (or is routed, see Model routing below). `glm-5.3-flash` is the low-cost GLM model ($0.09 input / $0.30 output per 1M tokens at the time of writing; live prices at https://inferspeed.ai/api/v1/public/pricing). It is served on `POST /v1/chat/completions` only. Get a key: sign in at https://inferspeed.ai and open API keys (https://inferspeed.ai/keys). Keep it in an environment variable; anyone with the key can spend your balance. ``` export INFERSPEED_API_KEY="sk-..." ``` Reasoning models such as `glm-5.3` and `kimi-k3` think before they answer. The reasoning comes back separately (`reasoning_content` in Chat Completions, a `reasoning` output item in Responses, a `thinking` block in Messages) and counts as output tokens. Leave room in `max_tokens`: with a very small limit the answer itself can be empty (`finish_reason: "length"`). ## Endpoints | Endpoint | API shape | Used by | | --------------------------- | ------------------------------------------------------ | -------------------------------------------- | | `POST /v1/chat/completions` | OpenAI Chat Completions (stream with `"stream": true`) | OpenAI SDKs, OpenCode, Cline, Continue, curl | | `POST /v1/responses` | OpenAI Responses | Codex CLI | | `POST /v1/messages` | Anthropic Messages | Claude Code, Claude Agent SDK, Anthropic SDKs | | `POST /v1/messages/count_tokens` | Anthropic token counting | Claude Code, Claude Agent SDK, Anthropic SDKs | | `GET /v1/models` | Models your key can call (OpenAI or Anthropic list shape) | Any client | ## Model routing Agents often send a model name of their own (Claude Code and the Claude Agent SDK default to `claude-*` names, Codex and the OpenAI SDKs to `gpt-*` names). A request for a model that is not available on your key (not on sale yet, or a name no live model answers to) is routed to an available model instead of failing: `claude-*`, `gpt-*`, `codex-*`, `o*`, `gemini-*` and `grok-*` names go to `glm-5.3`, and small `gpt-*-mini` / `gpt-*-nano` names on `/v1/chat/completions` go to `glm-5.3-flash`. - The response says which model served it: the `model` field and the `X-Served-Model` header (the name you sent is in `X-Model-Routed-From`). - You are billed at the price of the model that served the request. Your usage lists the request under that model, with the name you sent shown as "Requested". - A model that is available on your key is always served as written. - Want an error instead? Send `X-Model-Strict: 1`: an unavailable model is then never routed and returns an error (404 `model_coming_soon` or `model_not_found`, or 400 `model_not_available`). If a model is temporarily unavailable (its upstream fails or is too slow to start answering), the request may be served by an equivalent model instead, before any output reaches you. The response says so: the `model` field and `X-Served-Model` name the model that served it, and `X-Model-Failover: 1` is set. You are never billed more than the price of the model you requested. Output that has started streaming is never switched to another model. `X-Model-Strict: 1` turns this off too. Set the model explicitly (the examples below do) so you know what you get. ## Connect your agent ### Codex CLI Uses the OpenAI Responses endpoint. Add to `~/.codex/config.toml`, export the key, run `codex`. Codex may print a warning that it has no metadata for `glm-5.3`; it still works. Codex sends `wire_api = "responses"` only (recent Codex versions no longer support `"chat"`). Without `model = ...` Codex asks for its default `gpt-*` model, which is routed to `glm-5.3` (see Model routing). Verified on 2026-10-14 with Codex CLI 0.162.1 (`npm i -g @openai/codex@0.162.1`) and this exact config against `https://api.inferspeed.ai`: shell commands and `apply_patch` edits, a three-turn session (`codex exec resume --last`) and a 17-minute build-and-test task (55 tests written and passing). In scripts, run `codex exec "..." < /dev/null`: when stdin is not a terminal, `codex exec` waits for more input. ``` model = "glm-5.3" model_provider = "inferspeed" [model_providers.inferspeed] name = "InferSpeed" base_url = "https://api.inferspeed.ai/v1" wire_api = "responses" env_key = "INFERSPEED_API_KEY" [tools] web_search = false # hosted tools are not executed by the gateway # then: export INFERSPEED_API_KEY= && codex ``` ### Claude Code Uses the Anthropic Messages endpoint. Set these in your shell, then run `claude`. ``` export ANTHROPIC_BASE_URL="https://api.inferspeed.ai" export ANTHROPIC_AUTH_TOKEN="$INFERSPEED_API_KEY" export ANTHROPIC_MODEL="glm-5.3" export ANTHROPIC_DEFAULT_OPUS_MODEL="glm-5.3" export ANTHROPIC_DEFAULT_SONNET_MODEL="glm-5.3" export ANTHROPIC_DEFAULT_HAIKU_MODEL="glm-5.3" export ANTHROPIC_DEFAULT_FABLE_MODEL="glm-5.3" export CLAUDE_CODE_SUBAGENT_MODEL="glm-5.3" export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1 claude ``` `ANTHROPIC_DEFAULT_HAIKU_MODEL` is the small fast model Claude Code uses for background calls (titles, summaries); `ANTHROPIC_SMALL_FAST_MODEL` is its older name and still read. To use Kimi, put `kimi-k3` in place of `glm-5.3` (the same key works). Keep `glm-5.3` (not `glm-5.3-flash`) for every Claude Code variable: `glm-5.3-flash` is served on `/v1/chat/completions` only. Responses and tool use work on `https://api.inferspeed.ai`, including the `"role": "system"` messages that recent Claude Code versions send inside `messages`. Verified on 2026-10-14 with Claude Code 2.1.296 and exactly these variables (also as written by `setup.sh claude`): Bash, Read, Write and Edit tool calls, a three-turn session (`claude -p` then `--continue`) and a seven-minute task whose longest single response streamed for 224 seconds. Every response ended with `message_stop`. Keep the model variables: without them Claude Code asks for its built-in `claude-*` model names, which are routed to `glm-5.3` (see Model routing) but show up under the `claude-*` name in Claude Code's own cost display. In `-p` mode Claude Code may print `unrecognized_model` for `glm-5.3` on stderr; it still works. Re-verified on 2026-10-18 with Claude Code 2.1.302 (`claude -p ... --output-format json`), with and without the model variables, with `ANTHROPIC_AUTH_TOKEN` and with `ANTHROPIC_API_KEY`. ### Claude Agent SDK The Claude Agent SDK runs Claude Code underneath, so it takes the same variables. Pass them in `env` (they are not read from `~/.claude/settings.json` unless you load settings). TypeScript (`npm i @anthropic-ai/claude-agent-sdk`): ``` import { query } from "@anthropic-ai/claude-agent-sdk"; const model = "glm-5.3"; for await (const msg of query({ prompt: "List the files in this directory.", options: { env: { ...process.env, ANTHROPIC_BASE_URL: "https://api.inferspeed.ai", ANTHROPIC_AUTH_TOKEN: process.env.INFERSPEED_API_KEY, ANTHROPIC_MODEL: model, ANTHROPIC_DEFAULT_OPUS_MODEL: model, ANTHROPIC_DEFAULT_SONNET_MODEL: model, ANTHROPIC_DEFAULT_HAIKU_MODEL: model, ANTHROPIC_DEFAULT_FABLE_MODEL: model, CLAUDE_CODE_SUBAGENT_MODEL: model, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1", }, }, })) { if (msg.type === "result") console.log(msg.result); } ``` Python (`pip install claude-agent-sdk`): ``` import asyncio, os from claude_agent_sdk import ClaudeAgentOptions, ResultMessage, query model = "glm-5.3" env = { "ANTHROPIC_BASE_URL": "https://api.inferspeed.ai", "ANTHROPIC_AUTH_TOKEN": os.environ["INFERSPEED_API_KEY"], "ANTHROPIC_MODEL": model, "ANTHROPIC_DEFAULT_OPUS_MODEL": model, "ANTHROPIC_DEFAULT_SONNET_MODEL": model, "ANTHROPIC_DEFAULT_HAIKU_MODEL": model, "ANTHROPIC_DEFAULT_FABLE_MODEL": model, "CLAUDE_CODE_SUBAGENT_MODEL": model, "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC": "1", } async def main(): async for msg in query(prompt="List the files in this directory.", options=ClaudeAgentOptions(env=env)): if isinstance(msg, ResultMessage): print(msg.result) asyncio.run(main()) ``` Tool calls (built-in tools and your own MCP tools), streaming, `count_tokens` and the `anthropic-beta` headers the SDK sends all work. Verified on 2026-10-18 with `@anthropic-ai/claude-agent-sdk` 0.3.302 and `claude-agent-sdk` 0.2.168 (Python), each running a query that calls an MCP tool. ### OpenAI Agents SDK Point the SDK's OpenAI client at InferSpeed and pick the model. Both the Responses and the Chat Completions model classes work, including function tools. ``` # pip install openai-agents import asyncio, os from openai import AsyncOpenAI from agents import Agent, OpenAIResponsesModel, Runner, function_tool, set_tracing_disabled set_tracing_disabled(True) # traces go to OpenAI otherwise, with a key InferSpeed does not issue client = AsyncOpenAI(base_url="https://api.inferspeed.ai/v1", api_key=os.environ["INFERSPEED_API_KEY"]) @function_tool def get_time() -> str: """Returns the current time.""" return "12:00" agent = Agent(name="assistant", model=OpenAIResponsesModel(model="glm-5.3", openai_client=client), tools=[get_time]) print(asyncio.run(Runner.run(agent, "What time is it?")).final_output) ``` Use `OpenAIChatCompletionsModel` in place of `OpenAIResponsesModel` for `/v1/chat/completions`. Verified on 2026-10-18 with `openai-agents` 0.24.0. ### CC Switch [CC Switch](https://github.com/farion1231/cc-switch) can hold InferSpeed as a provider for Claude Code and Codex. We have not yet run CC Switch itself against InferSpeed; the values below are the ones Claude Code and Codex were verified with directly. | CC Switch field | Claude Code | Codex | | --------------------------------- | -------------------------- | ----------------------------- | | Endpoint | `https://api.inferspeed.ai` | `https://api.inferspeed.ai/v1` | | API key | your InferSpeed key | your InferSpeed key | | API format | Anthropic (default) | OpenAI Responses (default) | | Model | `glm-5.3` | `glm-5.3` | | Haiku / Sonnet / Opus model | `glm-5.3` each | not used | Or import Claude Code with a deep link (CC Switch 4.0.10 or later). Put your key in place of `` (URL-encoded) and open the link on the computer that runs CC Switch; it shows a confirmation dialog before it changes anything. Keep the finished link private: it contains your key. The `config` value adds `CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC=1`. ``` ccswitch://v1/import?resource=provider&app=claude&name=InferSpeed&endpoint=https%3A%2F%2Fapi.inferspeed.ai&apiKey=&model=glm-5.3&haikuModel=glm-5.3&sonnetModel=glm-5.3&opusModel=glm-5.3&configFormat=json&config=eyJlbnYiOnsiQ0xBVURFX0NPREVfRElTQUJMRV9OT05FU1NFTlRJQUxfVFJBRkZJQyI6IjEifX0%3D ``` For Codex, CC Switch writes its own template (`model_reasoning_effort = "high"`, `disable_response_storage = true`, `requires_openai_auth = true`, key in `auth.json`), which is not the config verified above. For the verified Codex setup, use the `config.toml` block in the Codex CLI section instead of a CC Switch provider. The balance on the CC Switch card comes from `GET https://api.inferspeed.ai/v1/usage` with your key as `Authorization: Bearer`; pick CC Switch's built-in usage template that reads that endpoint, no custom script needed. ### OpenCode Uses the OpenAI Chat Completions endpoint. Add a provider to `opencode.json` (project) or `~/.config/opencode/opencode.json`, export the key, then pick `inferspeed/glm-5.3` (`opencode run -m inferspeed/glm-5.3 "..."`). ``` { "$schema": "https://opencode.ai/config.json", "provider": { "inferspeed": { "npm": "@ai-sdk/openai-compatible", "name": "InferSpeed", "options": { "baseURL": "https://api.inferspeed.ai/v1", "apiKey": "{env:INFERSPEED_API_KEY}" }, "models": { "glm-5.3": { "name": "glm-5.3" } } } } } ``` ### OpenClaw Uses the OpenAI Chat Completions endpoint. OpenClaw reads `~/.openclaw/openclaw.json` (JSON5). Add a provider and make it the default model, merging with what is already there, then run `openclaw doctor` to check the file. This block follows OpenClaw's configuration docs (https://docs.openclaw.ai/gateway/configuration). OpenClaw substitutes `${INFERSPEED_API_KEY}` from the environment when it loads the file, so the key is not written into it. Set `OPENCLAW_CONFIG_PATH` if your config lives elsewhere. Last verified: 2026-10-16, field by field against OpenClaw's custom-provider reference (https://docs.openclaw.ai/gateway/config-tools/custom-providers: `models.mode` `merge`, `providers..baseUrl` / `apiKey` / `api: "openai-completions"` for `/v1/chat/completions` backends, `models[].id` / `name`) and its environment-variable rules (`${VAR}` substitution). ``` { models: { mode: "merge", providers: { inferspeed: { baseUrl: "https://api.inferspeed.ai/v1", apiKey: "${INFERSPEED_API_KEY}", api: "openai-completions", models: [{ id: "glm-5.3", name: "glm-5.3" }], }, }, }, agents: { defaults: { model: { primary: "inferspeed/glm-5.3" } } }, } ``` ### Installer `setup.sh` writes the Claude Code, Codex CLI or OpenCode config shown above (for OpenClaw it only prints the block). It reads the key from `INFERSPEED_API_KEY` and never takes it as an argument, prints the one file it will change with a diff (secrets shown as ``), copies the old file to `.bak-`, writes, then checks the key against `GET /v1/models`. `--dry-run` prints and writes nothing. `--model ` picks the model; without it the installer uses the first model your key can call (`GET /v1/models`). Read it first: https://inferspeed.ai/setup.sh ``` curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- codex --dry-run curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- codex curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- codex --model kimi-k3 ``` For Claude Code it writes the variables above into the `env` block of `~/.claude/settings.json`, which then holds the key (written with mode 600). For an existing Codex `config.toml` it appends a `inferspeed` provider and profile and leaves your other settings alone; run `codex --profile inferspeed`. ### One-click config scripts One open-source script per tool, under https://inferspeed.ai/install/. Each reads the key only from `INFERSPEED_API_KEY`, never takes it as an argument and never prints it, backs up the file it changes (`.bak-`), changes nothing when run again with the same options, sends nothing over the network (no telemetry), and ends by printing a `curl` command that checks your key. The key is never written to disk unless you pass `--persist` (PowerShell: `-Persist`), which prints a warning and writes the file owner-only (mode 600; on Windows an ACL that grants only your account). After you switch back from `--persist`, the script lists the backups that still hold the key; `--purge-backups` (PowerShell: `-PurgeBackups`) deletes them. `--model ` picks the model (default `glm-5.3`); `--dry-run` prints the change and writes nothing. ``` curl -fsSL https://inferspeed.ai/install/codex.sh | sh -s -- --dry-run curl -fsSL https://inferspeed.ai/install/codex.sh | sh curl -fsSL https://inferspeed.ai/install/claude-code.sh | sh curl -fsSL https://inferspeed.ai/install/opencode.sh | sh curl -fsSL https://inferspeed.ai/install/openclaw.sh | sh -s -- --model kimi-k3 ``` Windows PowerShell (Codex CLI and Claude Code): ``` irm https://inferspeed.ai/install/codex.ps1 | iex irm https://inferspeed.ai/install/claude-code.ps1 | iex & ([scriptblock]::Create((irm https://inferspeed.ai/install/claude-code.ps1))) -Model kimi-k3 -DryRun ``` What each one writes: - `codex.sh` / `codex.ps1`: the Codex CLI block above in `~/.codex/config.toml`. An existing file keeps its lines and gets a marked `inferspeed` provider and profile block (`codex --profile inferspeed`); re-running either script replaces only that block. Codex reads the key from `INFERSPEED_API_KEY`. - `claude-code.sh` / `claude-code.ps1`: the Claude Code variables above in the `env` block of `~/.claude/settings.json`, plus `"apiKeyHelper": "printf %s \"$INFERSPEED_API_KEY\""`, so the key comes from your environment each time Claude Code starts. `--persist` writes `ANTHROPIC_AUTH_TOKEN` instead. - `opencode.sh`: the OpenCode provider above in `~/.config/opencode/opencode.json`, and `"model": "inferspeed/"` as the default. Models you added to the `inferspeed` provider are kept. - `openclaw.sh`: the OpenClaw block above merged into `~/.openclaw/openclaw.json` when that file is plain JSON (models you added to the `inferspeed` provider are kept); a JSON5 file (comments, unquoted keys) is left untouched and the block is printed. ### Cline, Continue and other OpenAI-compatible tools Choose the "OpenAI Compatible" provider (the name varies by tool) and fill in three fields. Field names differ between tools. ``` Provider: OpenAI Compatible Base URL: https://api.inferspeed.ai/v1 API key: Model ID: glm-5.3 ``` ## Call it from code ### curl (OpenAI) ``` curl https://api.inferspeed.ai/v1/chat/completions \ -H "Authorization: Bearer $INFERSPEED_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "glm-5.3", "messages": [{"role": "user", "content": "Say hello in one sentence."}] }' ``` ### Python (OpenAI) ``` # pip install openai import os from openai import OpenAI client = OpenAI( base_url="https://api.inferspeed.ai/v1", api_key=os.environ["INFERSPEED_API_KEY"], ) resp = client.chat.completions.create( model="glm-5.3", messages=[{"role": "user", "content": "Say hello in one sentence."}], ) print(resp.choices[0].message.content) ``` ### Python (Anthropic) ``` # pip install anthropic import os import anthropic client = anthropic.Anthropic( base_url="https://api.inferspeed.ai", api_key=os.environ["INFERSPEED_API_KEY"], ) msg = client.messages.create( model="glm-5.3", max_tokens=512, messages=[{"role": "user", "content": "Say hello in one sentence."}], ) print(next(block.text for block in msg.content if block.type == "text")) ``` ## Errors and retries Branch on the HTTP status and the top-level `code`, not on the message text (wording is not stable). Every error body has a top-level `code` and `message` on every endpoint. OpenAI-compatible endpoints also carry an OpenAI-style `error` object (`type`, `code`, `message`, `param`), which OpenAI SDKs read; `/v1/messages` carries `"type": "error"` and an Anthropic-style `error` object (`type`, `message`). Every `error` object has a `docs_url`; 401s add `keys_url`, unknown models `models_url`, balance errors `topup_url`. ``` HTTP/1.1 401 Unauthorized (POST /v1/chat/completions) {"code": "INVALID_API_KEY", "message": "Invalid API key", "keys_url": "https://inferspeed.ai/keys", "error": {"type": "invalid_request_error", "code": "invalid_api_key", "param": null, "message": "Invalid API key. Send your API key as ...", "docs_url": "https://inferspeed.ai/developers.md#errors-and-retries", "keys_url": "https://inferspeed.ai/keys"}} ``` `code` is the top-level field; `error.code` is the value on OpenAI-compatible endpoints when it differs. | Status | `code` (`error.code`) | Meaning | Retry? | | ------ | --------------------- | ------- | ------ | | 400 | `invalid_request_error` | The body is invalid or does not match the endpoint. | No. Fix the request. | | 401 | `API_KEY_REQUIRED`, `INVALID_API_KEY` (`invalid_api_key`) | Key missing or not recognised. | No. Ask your human. | | 401 | `API_KEY_DISABLED`, `USER_INACTIVE` (`api_key_disabled`, `user_inactive`) | Key disabled or account not active. | No. Ask your human. | | 403 | `INSUFFICIENT_BALANCE` (`insufficient_quota`), `permission_denied` (`error.type` `billing_error`) | Prepaid balance is used up. `INSUFFICIENT_BALANCE` has `topup_url` and `topup_api`; `permission_denied` (a billing check failed after the request was admitted, e.g. the balance ran out mid-wait or a subscription limit was hit) has neither. | No. Top up first. | | 403 | `API_KEY_QUOTA_EXHAUSTED` (`insufficient_quota`) | The spend cap set on this key is reached (see below). | No. Raise the cap. | | 403 | `API_KEY_EXPIRED`, `ACCESS_DENIED` | Key expired, or IP not allowed for this key. | No. Ask your human. | | 404 | `model_not_found` | The model is not available to this key. `GET /v1/models` lists the ones it can use. | No. Check the model. | | 404 | `model_coming_soon` | The model is not on sale yet and the request was sent with `X-Model-Strict: 1` (without it, the request is routed; see Model routing). | No. Pick a listed model. | | 429 | `rate_limit_exceeded` | Requests-per-minute limit, or balance held by your other in-flight requests. `Retry-After` is set. | Yes, after Retry-After. | | 429 | `rate_limit_exceeded`, `USAGE_LIMIT_EXCEEDED` | A key spend cap (5-hour, daily, 7-day) or an account or subscription allowance (daily, weekly, monthly) is used up. These carry `x-should-retry: false`; `Retry-After`, when set, is the time until the window resets. | Not until the window resets or the cap is raised. | | 429 | `gateway_concurrency_limit`, `gateway_queue_full` | Too many of your requests in flight. | Yes, with backoff. | | 429 | `rate_limit_exceeded` (`error.type` `rate_limit_error`) | The model is at capacity right now. | Yes, with backoff. | | 503 | `service_unavailable`, `API_KEY_AUTH_OVERLOADED` | No capacity is free for this model, or billing or key checks are briefly unavailable. | Yes, with backoff. | | 500 / 502 / 504 | `api_error` | The request failed or timed out. | Yes, with backoff. | | 400 | `model_not_available` | The model is not sold on this key. `available_models` lists the ones it can call. | No. Pick a listed model. | | 403 | `GROUP_NOT_ALLOWED` | The key is not allowed for this request. | No. Ask your human. | | 524 | none (the body is not JSON) | A non-streaming response took longer than about 100 seconds and was cut off. | Yes, with `"stream": true`. | Long responses: send `"stream": true` for anything that can take more than a minute (long outputs, a high `max_tokens`, agent turns over large contexts). A streaming response receives keepalives while the model works, so it is not cut off while waiting. A non-streaming response must arrive in full within about 100 seconds end to end at the edge; past that the connection is closed with HTTP 524 and a non-JSON body. Retrying the same non-streaming request usually runs into the same limit, so retry it once with `"stream": true` (or with a lower `max_tokens`) instead. Set your client's request timeout above 100 seconds so the 524 reaches you rather than a local timeout. Key spend cap: the cap is checked before each request. A request that starts under the cap runs to completion and is billed in full, so total spend can end above the cap by at most one request's cost (for example $0.104 on a $0.10 cap). The next request is then rejected with 403 `API_KEY_QUOTA_EXHAUSTED`. Raise or remove the cap on the key in the console to continue. Backoff: a 429 with `x-should-retry: false` means a window or spend cap is used up (the OpenAI and Anthropic SDKs honour this header and do not retry). Do not retry; wait for the window to reset (`Retry-After`, when set, is the seconds until then) or raise the cap. Retry with backoff only for 5xx and for other 429s: wait `Retry-After` seconds when present, otherwise 1, 2, 4 … up to 30 seconds with jitter. The 403 balance and spend-cap errors never clear by retrying. For support, quote the `x-request-id` response header. Limits for new accounts: 30 requests per minute and 5 concurrent requests, across all keys of the account. A request over the concurrency limit waits briefly for a free slot before it gets a 429. Details: https://inferspeed.ai/rate-limits ## Prices and balance - Prices, USD per 1M tokens, no key needed: `GET https://inferspeed.ai/api/v1/public/pricing` (`data.models[]`: `id`, `price` and `list_price` with `input`, `output`, `cache_read`, `cache_write`). - Balance and usage for your key: `GET https://api.inferspeed.ai/v1/usage` (`remaining`, `unit`, `usage.today` / `usage.total` with tokens and `actual_cost`). - Top up from code or an agent, with the same key: `POST https://inferspeed.ai/api/v1/billing/topup` with `{"amount_usd": 10}` (optional `Idempotency-Key` header) returns `data.payment_url` (a Stripe page: card, Apple Pay, Google Pay), `data.qr_code_png`, `data.expires_at` and `data.status_url`. Give the URL to a person; poll `GET /api/v1/billing/topup/{id}` until `status` is `completed`. `GET https://inferspeed.ai/api/v1/billing/balance` returns `balance_usd`. Both work at zero balance. ## More - Agent setup instructions: https://inferspeed.ai/agents.md - Agent skill: https://inferspeed.ai/skill.md - Installer: https://inferspeed.ai/setup.sh - Site index for language models: https://inferspeed.ai/llms.txt - Models and prices: https://inferspeed.ai/model-plaza - Status: https://inferspeed.ai/status # InferSpeed for agents You are an agent (or a harness) that needs a model backend. InferSpeed is a pay-per-token model API with OpenAI- and Anthropic-compatible HTTP endpoints, billed from a prepaid balance. Models on sale and live prices: https://inferspeed.ai/model-plaza (JSON: https://inferspeed.ai/api/v1/public/pricing). This file tells you how to configure yourself. ## What you need from your human One InferSpeed API key. They create it at https://inferspeed.ai/keys (sign-in required) and put it in the environment as `INFERSPEED_API_KEY`. Never write the key into files that are committed or shared. ## Settings - OpenAI-compatible base URL: `https://api.inferspeed.ai/v1` (clients append `/chat/completions` or `/responses`) - Anthropic-compatible base URL: `https://api.inferspeed.ai` (clients append `/v1/messages`; do not add `/v1` or any other path to it) - Use only the two base URLs above; there is no other API version or host (no `/v2`, no `/v3`). - API key environment variable: `INFERSPEED_API_KEY` - Auth header: `Authorization: Bearer $INFERSPEED_API_KEY` (`x-api-key` also works) - Model IDs: every public model is listed, with prices, at `GET https://inferspeed.ai/api/v1/public/pricing` (no key needed; use `data.models[].id`). The examples here use `glm-5.3`; put any listed ID in its place. - One key, every model: an API key (create one at https://inferspeed.ai/keys) calls every live model, such as `glm-5.3`, `kimi-k3` and `MiniMax-M3`. Name the model in the request; each request is billed at that model's price. `glm-5.3-flash` is served on `POST /v1/chat/completions` only. - List the models the key can call: `GET https://api.inferspeed.ai/v1/models` - `glm-5.3` limits: `max_tokens` up to 131072 (reasoning tokens count toward it). Context window: at least 324,955 prompt tokens accepted. - Reasoning models (such as `glm-5.3` and `kimi-k3`) think before answering and the reasoning counts as output tokens. Do not set `max_tokens` very low or the answer can come back empty. ## Pick your wire format - You speak OpenAI Responses (Codex CLI): `POST /v1/responses` - You speak OpenAI Chat Completions (most others): `POST /v1/chat/completions` - You speak Anthropic Messages (Claude Code, Anthropic SDK): `POST /v1/messages` - You speak legacy OpenAI Completions: `POST /v1/completions` - You speak Google Gemini native (`google-genai` SDK, Gemini CLI): `POST /v1beta/models/{model}:generateContent` or `:streamGenerateContent` (also `:countTokens`); send the key as `x-goog-api-key`, `Authorization: Bearer` or `?key=` Exact config blocks for Codex CLI, Claude Code, OpenCode, CC Switch and OpenAI-compatible tools, plus SDK examples: https://inferspeed.ai/developers.md. Verified against production on 2026-10-14 with Claude Code 2.1.296 and Codex CLI 0.162.1 (tool use, multi-turn, long streams). Installer (ask your human first; it reads the key from `INFERSPEED_API_KEY`, prints the one file it will change with a diff, backs it up, then tests the connection): `curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- [--model ] [--dry-run]` Without `--model` it uses the first model your key can call (`GET /v1/models`). One-click scripts, one per tool (same rules: key only from `INFERSPEED_API_KEY`, never written to disk unless `--persist`, backup before any change, idempotent, no network calls, prints a verify `curl`): `https://inferspeed.ai/install/codex.sh`, `claude-code.sh`, `opencode.sh`, `openclaw.sh`, and `codex.ps1`, `claude-code.ps1` for Windows. Usage: `curl -fsSL https://inferspeed.ai/install/codex.sh | sh -s -- [--model ] [--dry-run]`. Skill file with the same facts plus balance checks and key-handling rules: https://inferspeed.ai/skill.md ## OpenClaw Last verified: 2026-10-16 against OpenClaw's custom-provider and environment-variable docs (https://docs.openclaw.ai/gateway/config-tools/custom-providers). OpenClaw speaks OpenAI Chat Completions. Merge this into `~/.openclaw/openclaw.json` (JSON5; or the file `OPENCLAW_CONFIG_PATH` points at), then run `openclaw doctor`. OpenClaw fills `${INFERSPEED_API_KEY}` from the environment, so the key stays out of the file. ``` { models: { mode: "merge", providers: { inferspeed: { baseUrl: "https://api.inferspeed.ai/v1", apiKey: "${INFERSPEED_API_KEY}", api: "openai-completions", models: [{ id: "glm-5.3", name: "glm-5.3" }], }, }, }, agents: { defaults: { model: { primary: "inferspeed/glm-5.3" } } }, } ``` Or ask your human to run `curl -fsSL https://inferspeed.ai/install/openclaw.sh | sh` (it merges a plain-JSON file, backs it up first, and leaves a JSON5 file untouched). ## Prices and balance - Prices, USD per 1M tokens, no key needed: `GET https://inferspeed.ai/api/v1/public/pricing` - Balance and usage for your key: `GET https://api.inferspeed.ai/v1/usage` (`remaining`, `unit`, `usage.today.actual_cost`; details in https://inferspeed.ai/skill.md) - Low balance: call `POST https://inferspeed.ai/api/v1/billing/topup` with your key and `{"amount_usd": 10}`, and give the returned `data.payment_url` (or `data.qr_code_png`) to your user. Poll `data.status_url` until `status` is `completed`, then continue. Your human pays on a Stripe page; you never handle card details. Full contract: https://inferspeed.ai/skill.md ## Check that it works ``` curl https://api.inferspeed.ai/v1/chat/completions \ -H "Authorization: Bearer $INFERSPEED_API_KEY" \ -H "Content-Type: application/json" \ -d '{"model": "glm-5.3", "messages": [{"role": "user", "content": "Reply with OK."}]}' ``` ## When a request fails Branch on the status code and the error code (`code`, or `error.code` / `error.type`), not on the message text (message wording is not stable and may not be in English). - 400: the request is invalid or the model name is unknown. Fix it; the same body fails again. - 401: the key is missing, wrong or disabled. Stop and ask your human. - 403 `INSUFFICIENT_BALANCE`: the balance is used up. Retrying will not help. Create a top-up (`POST https://inferspeed.ai/api/v1/billing/topup`) and give the payment URL to your human, or send them to https://inferspeed.ai/purchase. Other 403s (expired key, IP not allowed): stop and ask. - 403 `API_KEY_QUOTA_EXHAUSTED` (`error.code` `insufficient_quota`): the spend cap on this key is reached. Stop and ask your human to raise it. Retrying will not help. - 403 `permission_denied` with `error.type` `billing_error`: the balance ran out while the request waited. Same as `INSUFFICIENT_BALANCE`, but the body has no `topup_url`. - 429 `USAGE_LIMIT_EXCEEDED`, or any 429 with an `x-should-retry: false` header: a spend cap on this key (5-hour, daily or 7-day) or an allowance is used up until its window resets (`Retry-After`, when set, is the seconds until then). Retrying soon will not help; stop and ask your human. - Any other 429: rate limited or at capacity. Wait `Retry-After` seconds, then retry with backoff. - 524, or a non-streaming request cut off after about 100 seconds: the response took too long to arrive in one piece. Retry once with `"stream": true` (or a lower `max_tokens`); the same non-streaming request will hit the same limit. Use `"stream": true` for long outputs. - 503 and other 5xx: temporary. Retry with backoff; https://inferspeed.ai/status shows live checks. --- name: inferspeed description: Use InferSpeed (pay-per-token model API, OpenAI- and Anthropic-compatible) as the model backend for an agent or coding tool. Covers base URLs, auth, model and price discovery, a connection test, balance checks, topping up through your human, errors and retries. version: 3 updated: 2026-10-15 --- # InferSpeed skill Version 3, 2026-10-15. Source: https://inferspeed.ai/skill.md. Site index: https://inferspeed.ai/llms.txt. InferSpeed is a pay-per-token model API with OpenAI- and Anthropic-compatible HTTP endpoints, billed from a prepaid balance. Models on sale and live prices: https://inferspeed.ai/model-plaza (JSON: https://inferspeed.ai/api/v1/public/pricing). ## Safety rules for the agent - The key belongs to your human. Never print it, log it, paste it into chat, or put it in a command line argument. Read it from the environment variable `INFERSPEED_API_KEY`. - If `INFERSPEED_API_KEY` is not set, ask your human to create a key at https://inferspeed.ai/keys and export it. Do not ask them to paste the key to you. - Ask your human before writing or changing any tool config file (for example `~/.claude/settings.json`, `~/.codex/config.toml`, `opencode.json`). Show them the file and the change first. Never write the key into a file that is committed or shared. ## Settings | Setting | Value | | ----------------------------- | ------------------------------------------------------------------- | | OpenAI-compatible base URL | `https://api.inferspeed.ai/v1` | | Anthropic-compatible base URL | `https://api.inferspeed.ai` (clients add `/v1/messages`) | | Auth header | `Authorization: Bearer $INFERSPEED_API_KEY` (`x-api-key` also works) | | Model IDs | Any public model; list: `GET https://inferspeed.ai/api/v1/public/pricing` | | Models per key | Every live model; `GET https://api.inferspeed.ai/v1/models` | Use only the two base URLs above; there is no other API version or host (no `/v2`, no `/v3`). Endpoints: `POST /v1/chat/completions` (OpenAI Chat Completions), `POST /v1/responses` (OpenAI Responses, Codex CLI), `POST /v1/messages` (Anthropic Messages, Claude Code), `GET /v1/models`. One API key calls every live model (`glm-5.3`, `kimi-k3`, `MiniMax-M3`, ...): name the model in the request, and it is billed at that model's price. `glm-5.3-flash` is served on `POST /v1/chat/completions` only. Examples use `glm-5.3`; put any ID from `GET /v1/models` in its place. Reasoning models (such as `glm-5.3` and `kimi-k3`) think before answering; the reasoning counts as output tokens. Do not set `max_tokens` very low or the answer can come back empty. Limits and context details: https://inferspeed.ai/developers.md ## Discover models and prices - Models this key can call (needs the key): `GET https://api.inferspeed.ai/v1/models` returns an OpenAI-style list; use the `id` values. - Prices (public, no key): `GET https://inferspeed.ai/api/v1/public/pricing`. The body is `{"code": 0, "data": {...}}`; `data.models[]` has `id`, `name`, `protocols` (when verified), `price` and `list_price` with `input`, `output`, `cache_read`, `cache_write` in USD per 1M tokens (`data.unit` is `per_1m_tokens`). Fields that are not priced are left out. ## Test the connection This prints the HTTP status and the model IDs, never the key: ``` curl -sS https://api.inferspeed.ai/v1/models \ -H "Authorization: Bearer $INFERSPEED_API_KEY" \ -w '\nHTTP %{http_code}\n' ``` 200 means the key works. 401 means the key is wrong or disabled; 403 means it is blocked (see errors below). ## Configure a coding tool Exact config blocks for Codex CLI, Claude Code, OpenCode, OpenClaw and other OpenAI-compatible tools: https://inferspeed.ai/developers.md. The Claude Code and Codex CLI configs were verified against production on 2026-10-14 with Claude Code 2.1.296 and Codex CLI 0.162.1. Or, with your human's approval, run the installer. It reads the key from `INFERSPEED_API_KEY`, prints the one file it will change with a diff (secrets hidden), backs the file up, writes it, then tests the connection. Read it first: https://inferspeed.ai/setup.sh ``` curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- claude --dry-run # show only, write nothing curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- claude # or codex, opencode, openclaw curl -fsSL https://inferspeed.ai/setup.sh | sh -s -- claude --model kimi-k3 # pick the model ``` Without `--model` the installer uses the first model the key can call (`GET /v1/models`). For `openclaw` it only prints the settings to add by hand. ## Check balance and usage `GET https://api.inferspeed.ai/v1/usage` with the same `Authorization` header. Fields to read: - `remaining` and `unit` (`"USD"`): what this key can still spend. For a key with its own spend cap, `quota.limit`, `quota.used` and `quota.remaining`; otherwise `balance` is the account's prepaid balance. - `usage.today` and `usage.total` for this key: `requests`, `input_tokens`, `output_tokens`, `cache_read_tokens`, `cache_creation_tokens`, `total_tokens`, and `actual_cost` (USD charged). - Optional query: `days=1..90` adds `daily_usage`; `start_date` / `end_date` (`YYYY-MM-DD`) set the range of `model_stats`. ## Top up when the balance is low When the balance is low or a request fails with 403 `INSUFFICIENT_BALANCE`, call `POST https://inferspeed.ai/api/v1/billing/topup` and give the URL to your user. You never see card details; your human pays on a Stripe page (card, Apple Pay, Google Pay). ``` curl -sS https://inferspeed.ai/api/v1/billing/topup \ -H "Authorization: Bearer $INFERSPEED_API_KEY" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: " \ -d '{"amount_usd": 10}' ``` The body is `{"code": 0, "data": {...}}`. Read from `data`: - `payment_url`: the payment page. Send it to your human, or show `qr_code_png` (a `data:image/png` QR of the same URL). `message_for_user` is a ready-to-send sentence. - `id`, `status` (`pending`), `amount_usd`, `credit_usd` (what lands in the balance, bonus included), `expires_at` (the link closes then; create a new one after that). - `status_url`: poll it with the same header every 5-10 seconds. `GET https://inferspeed.ai/api/v1/billing/topup/{id}` returns `status`: `pending` (not paid yet), `paid` (being credited), `completed` (credited; `balance_usd` is the new balance), or `expired`, `cancelled`, `failed` (make a new top-up). When it is `completed`, retry the request that failed. `GET https://inferspeed.ai/api/v1/billing/balance` returns `balance_usd`. Both billing endpoints work at zero balance. Rules: ask your human how much to add if they have not said; never create more than one open top-up at a time; amounts outside the allowed range fail with 400 and a reason. A person can also top up at https://inferspeed.ai/purchase. ## When a request fails Branch on the status code and the error code (`code`, or `error.code` / `error.type`), not on the message text. - 400: the request is invalid or the model name is unknown. Fix it; the same body fails again. - 401: the key is missing, wrong or disabled. Stop and ask your human. - 403 `INSUFFICIENT_BALANCE`: the balance is used up. Retrying will not help. Create a top-up (`POST https://inferspeed.ai/api/v1/billing/topup`, see above), give the `payment_url` to your human, wait for `completed`, then retry. The error body also has `topup_url` (the console page) and `topup_api`. Other 403s (expired key, IP not allowed): stop and ask. - 403 `API_KEY_QUOTA_EXHAUSTED` (`error.code` `insufficient_quota`): the spend cap on this key is reached. Stop and ask your human to raise it. Retrying will not help. - 403 `permission_denied` with `error.type` `billing_error`: the balance ran out while the request waited. Same as `INSUFFICIENT_BALANCE`, but the body has no `topup_url`. - 429 `USAGE_LIMIT_EXCEEDED`, or any 429 with an `x-should-retry: false` header: a spend cap on this key (5-hour, daily or 7-day) or an allowance is used up until its window resets (`Retry-After`, when set, is the seconds until then). Retrying soon will not help; stop and ask your human. - Any other 429: rate limited or at capacity. Wait `Retry-After` seconds, then retry with backoff. - 524, or a non-streaming request cut off after about 100 seconds: the response took too long to arrive in one piece. Retry once with `"stream": true` (or a lower `max_tokens`); the same non-streaming request will hit the same limit. Use `"stream": true` for long outputs. - 503 and other 5xx: temporary. Retry with backoff; https://inferspeed.ai/status shows live checks. Full error table: https://inferspeed.ai/developers.md ## More - Agent setup: https://inferspeed.ai/agents.md - API page: https://inferspeed.ai/developers.md - Site index: https://inferspeed.ai/llms.txt - Installer: https://inferspeed.ai/setup.sh - Prices (JSON): https://inferspeed.ai/api/v1/public/pricing