Skip to main content
kRouter

API Reference

kRouter's endpoints on localhost:20128: OpenAI Chat Completions, Anthropic Messages, the Responses API used by Codex, models, media, and auth.


kRouter serves one API on http://localhost:20128 (or the port you chose with --port). It accepts three request formats, OpenAI Chat Completions, Anthropic Messages and the OpenAI Responses API, and translates each into whatever the chosen provider speaks. The model field decides where a request goes: <provider-alias>/<model-id>, or the name of a combo.

Authentication

  • Requests from the machine kRouter runs on need no key, unless kRouter was started with REQUIRE_API_KEY=true.
  • Requests from anywhere else need a kRouter API key. Without one they get 401 with "API key required for remote API access".
  • Send the key as Authorization: Bearer <key> or as x-api-key: <key>.
  • "Same machine" is decided from the connection's peer address, not the Host header. Requests that arrive through a reverse proxy always count as remote.
  • Create keys on the dashboard's Endpoint page, in the API Keys section.

The examples below send $KROUTER_KEY. From the machine kRouter runs on you can leave that header out.

Endpoints

Method and pathWhat it does
POST /v1/chat/completionsOpenAI Chat Completions
POST /v1/messagesAnthropic Messages, used by Claude Code
POST /v1/messages/count_tokensAnthropic token count
POST /v1/responsesOpenAI Responses API, used by Codex
POST /v1/responses/compactResponses context compaction
GET /v1/modelsModels of your connected providers, plus your combos
GET /v1/models/tts (also stt, embedding, image, video, web)Models of one kind
POST /v1/embeddingsEmbeddings
POST /v1/images/generationsImage generation
POST /v1/audio/speech, POST /v1/audio/transcriptions, GET /v1/audio/voicesText to speech, speech to text, voice list
POST /v1/videos/generations, GET /v1/videos/IDVideo generation and its result, through xAI only
POST /v1/search, POST /v1/web/fetchWeb search and URL fetch
POST /api/v1beta/models/MODEL:generateContentGemini format; note the /api prefix
POST /v1/api/chatOllama-compatible chat

A doubled /v1/v1/... path is accepted too, and /codex/... is an alias for /v1/responses. The media endpoints are covered in Multimodal & Agent Skills.

POST /v1/chat/completions

Standard OpenAI shape. Streaming and tool calls use the OpenAI formats whichever provider serves the model.

curl http://localhost:20128/v1/chat/completions \
  -H "Authorization: Bearer $KROUTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cc/claude-opus-4-7",
    "messages": [
      {"role": "user", "content": "Hello!"}
    ],
    "stream": true
  }'

POST /v1/messages

The Anthropic Messages API, used by Claude Code and other Anthropic clients. Point them at http://localhost:20128/v1 (for Claude Code, ANTHROPIC_BASE_URL). The model does not have to be a Claude model: kRouter translates to and from the provider's format.

curl http://localhost:20128/v1/messages \
  -H "x-api-key: $KROUTER_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cc/claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

POST /v1/responses

The OpenAI Responses API. Send model, input (a string, or a list of message, function-call and function-call-output items) and, optionally, instructions, tools and "stream": true. kRouter converts the request for whichever provider serves model, then converts the reply back: Responses events when streaming, a Responses object when not. Any connected model, and any combo, can sit behind a Responses client. How the two OpenAI formats differ: Responses API vs Chat Completions.

curl http://localhost:20128/v1/responses \
  -H "Authorization: Bearer $KROUTER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cc/claude-sonnet-4-6",
    "instructions": "Answer in one sentence.",
    "input": "What does HTTP 429 mean?",
    "stream": true
  }'

kRouter does not store responses, so it cannot resolve a previous_response_id. Send the whole conversation in input on every request.

POST /v1/responses/compact takes the same body and asks for a compacted conversation. It is meant for OpenAI Codex models: with a cx/... model, kRouter forwards it to Codex's own compact endpoint.

Codex uses this endpoint. kRouter's Codex setup (dashboard CLI Tools, OpenAI Codex CLI / App) writes a [model_providers.krouter] entry with base_url = "http://localhost:20128/v1" and wire_api = "responses" to ~/.codex/config.toml, so every Codex request arrives here. The full block is in Getting Started; running Codex on other providers' models is covered in Codex CLI with any model.

What changed in v0.5.163. A non-streaming /v1/responses request now gets a proper Responses object back, where it used to get a chat-format reply. Three more fixes apply to providers that kRouter itself reaches through a Responses API (GitHub Copilot, Codex, Grok CLI):

  • Every system and developer message reaches the model, in order. Before, only the first system message did, and Codex sends developer messages.
  • A reply cut off by the token limit ends with a finish reason and usage.
  • A failed reply reaches non-streaming clients as a real error (429 for rate limits), not as a success whose text is the error message.

Responses-only models

Some upstream models are served only on a Responses endpoint, for example GitHub Copilot's Codex models and some OpenCode Go models. kRouter sends them there whatever format your tool used, so a Chat Completions or Claude Code client can call them like any other model.

On OpenCode Go (ocg) these are grok-4.5, grok-4.6, grok-4.7, gpt-5.6-luna, gpt-6-luna, muse-spark-1.2-contributor and muse-spark-1.3-contributor. Since v0.5.163 they are routed to OpenCode's Responses endpoint automatically, so ocg/grok-4.7 works from Codex, Claude Code or a plain Chat Completions client. In the same release, OpenCode's "model not supported" error stopped counting as a bad key: it is now reported as a 400 and no longer cools down your whole OpenCode Go account.

Choosing the protocol per OpenCode Go model

OpenCode Go serves its models on three protocols: Chat Completions, Messages and Responses. On the OpenCode Go provider page in the dashboard, every model row has a Protocol control:

  • Auto: kRouter's built-in choice, named in brackets
  • Chat Completions, Messages or Responses: force that endpoint

If OpenCode moves a model to a different endpoint, switch it here the same day instead of waiting for a kRouter release. The setting belongs to the model, not to an account, so it applies to all your OpenCode Go connections, including ones you add later, from the next request on. Background: OpenCode Go's three protocols.

GET /v1/models

Lists the models of the providers you have connected, plus your combos, in the OpenAI list format.

curl http://localhost:20128/v1/models -H "Authorization: Bearer $KROUTER_KEY"

GET /v1/models/tts, /stt, /embedding, /image, /video and /web list models of one kind.

Combos

A combo is a named list of provider/model IDs that you create in the dashboard and call by name, like a model:

{
  "model": "my-coding-stack",
  "messages": [{"role": "user", "content": "..."}]
}

With the default strategy, kRouter tries the combo's models one after another and returns the first success. Rate limits, quota errors, account errors and upstream 5xx move on to the next model. Errors caused by the request itself, such as a prompt that is too long, come back at once, because every model would reject them. When every model fails, kRouter returns an error, with a retry time when a provider gave one.

See Combos & fallback for strategies and the full list of fallback triggers.