Kafox Docs
v1 Sign in
Guides

Introduction

Kafox is an AI gateway compatible with the OpenAI API: one key, one endpoint and many models. Swap the base URL and the key in your SDK, keep the same request body, and your balance, in Brazilian reais (BRL), is charged on every response.

Request flow

Quickstart

  1. Create a key

    In API Keys, create a kafox_live_... key. The secret is shown only once, so save it before closing the dashboard. The dashboard is currently available in Portuguese only.

  2. Point to the base URL

    Use https://api.kafox.dev/v1 instead of https://api.openai.com/v1. Nothing else changes.

  3. Send the request

    A POST /chat/completions with model and messages returns the answer and charges the tokens. The kafox-free model in the example is free and works even with a zero balance.

No balance? Free models (kafox-free and the ones ending in (free)) keep answering with a zero balance, within the daily quota. See Limits and Balance and billing.
Guides

Authentication

Every call carries the key in the Authorization header. The key identifies which account pays for the request.

Headers
Authorization: Bearer kafox_live_xxxxxxxx
Content-Type: application/json

The X-Api-Key: kafox_live_xxxxxxxx header is also accepted, for clients that do not let you customize Authorization.

  • A missing, invalid or revoked key returns 401. See Errors.
  • No balance returns 402 before the model is called, and nothing is charged. Free models go through anyway.
  • One key per project keeps usage history separate and lets you revoke a key without changing your password. Each account can have up to 10 active keys.
  • Never put the key in browser code or in a distributed app. Call Kafox from your server and, if a key leaks, revoke it in API Keys.
  • The secret is shown only once. We store only a hash of it.
Guides

API Tester

Run a real call without leaving the browser. The key stays in this tab's memory only: it is not saved or logged.

POST /chat/completions

Create one in API Keys. The key is used for this call only.

curl
Response No request run yet
// fill in the key and click Run
Endpoints

Chat completions

POST /chat/completions

Same body and same response as OpenAI. It supports SSE streaming, tool calling and images on vision models.

FieldTypeDescription
modelstringRequired. An id from the models list, kafox-free or an alias (fast, smart).
messagesarrayRequired. A list of { role, content } with system, user, assistant and tool. content can be text or a list of text and image_url parts.
streambooleanReturns the answer as SSE events, token by token.
stream_optionsobjectWith { "include_usage": true } the last event carries the response usage.
temperaturenumberFrom 0 to 2. Lower is more predictable.
max_tokensnumberCap on generated tokens.
tools, tool_choicearray, stringTool calling in the OpenAI format.

Other OpenAI-format fields are passed through to the model. Not every model accepts all of them: an unsupported field may be ignored or return 400.

Response
{
  "id": "chatcmpl-7e39862f-9c53-49ce-bbc3-fcaf38c5f913",
  "object": "chat.completion",
  "created": 1793593191,
  "model": "deepseek-ai/DeepSeek-V4.1-Flash",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Hello! How can I help?" },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 18, "completion_tokens": 9, "total_tokens": 27 }
}

Response headers

HeaderValue
X-Request-IdCall identifier. Give it to support if you need something investigated.
X-PyFlow-Cachemiss, exact or semantic: whether the answer came from the gateway cache.
X-Kafox-ModelOnly on kafox-free: the model that actually answered.

Streaming

With "stream": true the answer arrives as SSE events (data: {...}, separated by a blank line) and ends with data: [DONE]. Ask for stream_options.include_usage to get the consumption in the last event.

SSE events
data: {"object":"chat.completion.chunk","model":"...","choices":[{"index":0,"delta":{"role":"assistant","content":"Hel"}}]}

data: {"object":"chat.completion.chunk","model":"...","choices":[{"index":0,"delta":{"content":"lo!"},"finish_reason":"stop"}]}

data: {"object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":21,"completion_tokens":9,"total_tokens":30}}

data: [DONE]
  • Reasoning models send their thinking in delta.reasoning_content (or message.reasoning_content without streaming) before the content. Those tokens count toward usage. With a very low max_tokens the model can spend everything thinking and return a null content with finish_reason: "length".
  • Error in the middle of a stream: if the model fails after it has started, you get an {"error":{"message":"...","type":"api_error","code":"upstream_error"}} event instead of an HTTP status, because the 200 was already sent.

Tool calling

tools and tool_choice follow the OpenAI format. The model returns tool_calls; run the function and reply with a role: "tool" message carrying the matching tool_call_id. Not every model supports tools.

  • Fallback: if one route fails, the next one takes over silently. The answer still comes from the same key, in the same format.
  • Cache: repeated prompts can be answered by the gateway cache (exact, or semantic when the question is similar enough). The X-PyFlow-Cache header tells you what happened.
Endpoints

Models

GET /models

Lists the model ids your key can use. Always send the exact id: deepseek-ai/DeepSeek-V4.1-Flash, not just deepseek.

Response
{
  "object": "list",
  "data": [
    { "id": "deepseek-ai/DeepSeek-V4.1-Flash", "object": "model", "created": 1793593191, "owned_by": "kafox" },
    { "id": "kafox-free", "object": "model", "created": 1793593191, "owned_by": "kafox" },
    { "id": "openai/gpt-oss-120b (free)", "object": "model", "created": 1793593191, "owned_by": "kafox" }
  ]
}
  • kafox-free is a virtual model: it picks an available free model on its own and switches route if one is limited.
  • Ids ending in (free) are specific free models. Use the full name, suffix included.
  • The fast and smart aliases are accepted in the model field but are not in the list.
  • Prices are not in this response: they are at GET https://kafox.dev/api/public/pricing, public and keyless. Values are integer micro-reais per million tokens (input_micros_per_1m, cached_micros_per_1m, output_micros_per_1m); R$ 1 = 1,000,000.
Endpoints

Errors

Errors arrive as JSON in the OpenAI format. code is the HTTP status itself, and type tells you where the error came from.

Format
{
  "error": {
    "message": "chave de API invalida",
    "type": "http_error",
    "code": 401
  }
}

The message text is currently written in Portuguese. Rely on code and type in your code, not on the text.

StatusTypeWhat it means and what to do
400gateway_error, invalid_request_errorInvalid JSON, missing model or messages, or a field outside the format. Fix the request; retrying will not help.
401http_errorMissing, invalid or revoked key. Check the header and your keys in API Keys.
402http_errorInsufficient balance. Top up in Credits. Free models keep working.
404gateway_errorThe requested model does not exist or is unavailable. Check the id with GET /models.
429rate_limit_error, gateway_errorThe key's request limit or the day's free quota was reached. Wait for the time in the Retry-After header. See Limits.
500internal_errorInternal gateway error. Try again; if it persists, contact support with the X-Request-Id.
502gateway_errorNo route managed to answer. Try again in a moment.
503gateway_errorService temporarily unavailable. Try again in a moment.
  • Retry (with growing waits) only on 429, 500, 502 and 503. 400, 401, 402 and 404 do not fix themselves.
  • Error messages never mention the upstream provider.
Limits and billing

Limits

Each key has a per-minute and per-hour request limit, and each account has a daily quota of free tokens.

LimitValueWhen it is hit
Requests per minute60 per key429 rate_limit_error with Retry-After in seconds.
Requests per hour2000 per keySame as above.
Free tokens per day5,000,000 per account429 until midnight UTC.
Active keys10 per accountRevoke a key you no longer use to create another.
  • The request values are the default for keys without their own limit. A key can have custom limits.
  • Limits count requests, not tokens, and use sliding windows: Retry-After tells you how many seconds until a slot opens.
  • The free quota is one per account (creating more keys does not raise it): it adds up every free model used in the day, it is not per model. It resets at midnight UTC.
Limits and billing

Balance and billing

The balance is prepaid, in Brazilian reais (BRL), and is charged on every response according to the tokens used. Credits do not expire.

  • How cost is computed: input tokens × input price + output tokens × output price, per million tokens. The part of the prompt the provider served from its own cache is billed at the much lower cache rate. Each model's prices are in Models and pricing.
  • Top up by PIX (Brazil's instant payment system) in Credits, from R$ 5. Packages are R$ 5, 10, 25, 50 and 100, and you can also choose a custom amount.
  • Welcome bonus: each account's first paid top-up of at least R$ 5 gets another R$ 5 as a bonus, once.
  • Zero balance: calls to paid models return 402 before the model is called, and nothing is charged. Free models keep working within the daily quota.
  • Where to see your balance: in the dashboard, or in the terminal with kafox balance.
Reference

Models and pricing

Values in Brazilian reais (BRL) per 1 million tokens. The dashboard uses this same table to compute the cost of each call.

ModelInput / 1MCache / 1MOutput / 1M
Loading table...

Free tier: models marked free do not use your balance. Each account gets 5 million free tokens per day across all free models (not per model), resetting at midnight UTC. Use "model": "kafox-free" and Kafox picks a free model and switches route when one is limited.

The same table as JSON, for scripts: GET https://kafox.dev/api/public/pricing.

CLI

Terminal CLI

Kafox also lives in the terminal. The CLI is a full TUI: streaming, reasoning, file editing with diffs, shell tools, MCP and subagents, all on your account and billed as tokens.

Installation

Install or update
npm install -g https://kafox.dev/static/downloads/kafox-cli-latest.tgz

Requires Node.js 22.5 or newer. The same command updates to the newest version, and kafox --version shows which one is installed. Releases live in /static/downloads/, one file each (kafox-cli-<version>.tgz).

First steps

  1. Sign in

    kafox login shows a short code and a link. Confirm in the browser and the session is saved in ~/.kafox/.

  2. Open the TUI

    Just kafox opens the interface in the current folder, which becomes the project. Pick the model with /model.

  3. Or run without the interface

    kafox agent "review src/ and point out bugs" runs without the TUI, good for CI, scripts and automated audits.

Terminal commands

Reference
kafox                       opens the TUI
kafox login | logout        sign in or out
kafox whoami | status       account, balance and gateway
kafox models                models and prices per 1M tokens
kafox balance | pricing     balance and top-up packages
kafox key                   creates an API key
kafox ask "question" [-m model]
kafox agent "goal" [-y] [--max-steps N] [--json]
kafox -p "prompt" [-y] [--output-format json]   headless mode (scripts and CI)
kafox history [n]           saved conversations
kafox resume [code]         resumes a conversation
kafox continue | -c         back to the most recent conversation
kafox theme | background    theme and background image
kafox provider              alternative providers (external keys)
kafox mobile                use the CLI from your phone via QR Code
kafox update [--check]      updates the CLI (verifies the SHA-256 before installing)
kafox doctor                diagnoses login, API, model, git, sandbox, MCP and version
kafox --allow-all | -y      starts with every tool pre-approved
kafox --version | --help

Commands inside the TUI

Type / to open the menu (arrows navigate, Tab completes, Enter runs).

CommandWhat it does
/model, /modelsPick the model, or directly with /model <id>.
/balance, /pricing, /statusBalance, top-up packages, account and gateway.
/allowAuto-approval for this session; /allow off goes back to asking.
/image, /pasteAttach an image to the next turn (file or clipboard).
/copiarCopies the whole last answer.
/mouseTurns the mouse wheel on or off (when off, the terminal selects text).
/mcpLists MCP servers and tools; /mcp reload reconnects.
/agents, /queueThe session's subagents and the message queue.
/theme, /backgroundTheme and background image.
/compact, /clearCompacts or clears the context.
/key, /login, /logout, /whoami, /exitAccount and exit.

Shortcuts

  • Enter queues a message while the AI is working; Esc twice interrupts the current step.
  • Ctrl+V or Alt+V paste a copied image (screenshot) as an attachment, with side-by-side previews and a button to remove each one. If your terminal swallows Ctrl+V, use /paste.
  • Ctrl+Y copies the last answer; PgUp/PgDn and the mouse wheel scroll the conversation.
  • F2 toggles the mouse wheel. To select text while the wheel is on, hold Shift (Option on macOS) and drag.

Headless mode (scripts and CI)

With -p (or --print) the CLI runs a single task without opening the interface and returns the result. Use it in scripts, automations and pipelines. Available from version 0.12.

Usage
OptionWhat it does
--output-format text|json|stream-jsontext (default) prints only the answer. json prints one object at the end. stream-json prints one object per line for each event.
-y, --allow-allApproves writes and command execution. Without it the AI can only read; anything that needs approval is refused. The blocked-command lists still apply.
--planRead-only: the AI plans and changes nothing.
--max-turns NAgent step limit (default 25).
--max-custo R$Stops when the run's spending passes the amount. The balance is checked after each step, so spending can slightly exceed the cap.
-m, --modelModel for the run.
--cwd folderWorking folder.
-c, --continue, --resume codeContinues the latest conversation or a saved one.
--no-memoryDoes not load KAFOX.md or AGENTS.md.

With the json format the object has result, model, session_id, is_error, usage, cost_brl, duration_ms, turns and tool_calls (plus error on failure). In the JSON formats stdout contains only JSON; warnings and errors go to stderr.

Exit codeMeaning
0Task completed.
1Task or model error, step limit reached or budget exceeded.
2Invalid usage or not logged in (kafox login).
3A tool was refused for lack of approval or because it is blocked.
130Interrupted (Ctrl+C or SIGTERM). Processes the run started are stopped.

Example CI step (GitHub Actions) that reviews a pull request:

GitHub Actions

In CI there is no browser to log in: run kafox login once on your own machine and store the contents of ~/.kafox/token.json as a pipeline secret (KAFOX_TOKEN in the example). The session expires; renew the secret when needed. MCP servers defined in the project folder do not start in headless mode, because nobody can approve them.

Version 0.11 features

Available from CLI 0.11 on. Check yours with kafox --version and update with kafox update.

CommandWhat it does
/memory, /initShows the loaded project memory; /init asks the AI to analyze the project and write KAFOX.md (it goes through write approval).
/planPlan mode: the AI only reads and proposes a plan. /plan aprovar runs it and /plan off leaves plan mode.
/undo, /undo turno, /checkpointsUndoes the AI's last file change, or all changes of the last turn, and lists what can be undone.
/permissoesThe project's allowed and blocked commands (allow, deny, remove).
/custoCost of the conversation and of the session (also in the footer).
/diff, /commit, /branchGit: changes, a commit whose message the AI proposes and you approve, and switching or creating a branch.
/sandbox on|offIsolates the AI's commands (Linux and macOS).
/auto on|offAutomatic model choice: cheap for simple tasks, strong for hard ones.
/doctor, /updateDiagnostics and a check for a newer version.
  • Project memory: create a KAFOX.md (or AGENTS.md) at the project root with what the AI needs to know: how to run the tests, conventions, cautions. A ~/.kafox/KAFOX.md applies to every project. The files go into the prompt on every message (up to 12,000 characters per file and 24,000 in total) and the interface tells you when it loaded one. A file from a third-party repository is untrusted content: read it before opening unknown projects.
  • Checkpoints: before every write_file or edit_file the CLI saves the file's previous state in ~/.kafox/checkpoints/, outside the project. Limit of 300 points per project; files above 5 MB are not saved.
  • Permissions: .kafox/permissions.json (project) and ~/.kafox/permissions.json (global) list allow and deny, with * matching any text. A blocked command never runs, not even with --allow-all. An allowed command only skips the prompt when every part of it is on the list.
  • Sandbox: uses bwrap (Linux) or sandbox-exec (macOS): commands can only write to the project folder, /tmp and the caches. With the sandbox on but unavailable, the command does not run. Windows has no simple equivalent, so it stays off.
  • Automatic model: short questions go to the cheap model (default kafox-free); code, bugs, refactoring, several files, images and long requests go to the strong one. Picking a model with /model turns automatic mode off.
  • Live cost: the footer shows the conversation and session spend, and your balance. A free model shows as free.

What the agent does

  • Reads and edits files (read_file, list_dir, write_file, edit_file), with the diff in the conversation. Every path is locked inside the project directory.
  • Runs commands (run_command). Anything that writes, edits or executes asks for approval: allow once, allow always or deny.
  • A command that does not finish (server, watcher, loop) moves to the background after about 60 s: the agent keeps working and checks or stops the process later (process_output, stop_process, list_processes).
  • Launches subagents in parallel to investigate several points, and calls tools from configured MCP servers.
  • If the network drops, it retries on its own with growing waits; Esc cancels the wait. Conversations are saved in ~/.kafox/chats/ and come back with kafox resume.

MCP

Configure it in ~/.kafox/mcp.json (or ./mcp.json in the project, which wins). The tools appear in the agent as mcp__server__tool. Servers from a project's mcp.json only start after you approve them: the CLI shows each command and you choose to approve once, approve always for that folder, or decline (/mcp aprovar shows the prompt again). If the file changes, it asks again. Servers from your personal config in ~/.kafox start on their own.

mcp.json
{
  "mcp": {
    "playwright": {
      "type": "local",
      "command": ["npx", "-y", "@playwright/mcp@latest"]
    },
    "remote": {
      "type": "remote",
      "url": "https://example.com/mcp",
      "headers": { "authorization": "Bearer ..." }
    }
  }
}

Configuration

The session and preferences live in ~/.kafox/ (or in the folder pointed to by KAFOX_HOME). KAFOX_API_URL changes the API and KAFOX_ALLOW_ALL=1 starts with the tools pre-approved. The CLI only answers with a balance, or with a free model.

Node.js

The official OpenAI SDK for JavaScript and TypeScript. Install it, swap the base URL and the key.

npm
npm install openai
Example

Python

The official OpenAI SDK for Python 3.8+. The same client.chat.completions as OpenAI.

pip
pip install openai
Example

PHP

openai-php/client, the most used community client. Works with PHP 8.2+.

composer
composer require openai-php/client
Example
Reference

Frequently asked questions

Which SDK should I use?

Any OpenAI-compatible client: the official Python and Node.js SDKs, openai-php, or plain HTTP. Only the base URL and the key change.

Do I need a balance to try it?

No. kafox-free and the models with (free) do not use your balance. The quota is 5 million tokens per day per account and resets at midnight UTC.

I got a 402. Now what?

Your balance ran out. Top up by PIX in Credits; the minimum is R$ 5. Meanwhile, free models keep answering.

I got a 429. What does it mean?

Either the key went over its per-minute or per-hour request limit, or the day's free quota is used up. Wait the number of seconds in the Retry-After header and try again. See Limits.

Do streaming, tools and images work?

Yes. SSE streaming, tools and image_url follow the OpenAI format. Tools and images depend on the model you pick: a model without vision does not accept images.

Why did the answer come back empty?

On reasoning models, the thinking consumes max_tokens. Raise the limit, or also read the reasoning_content field.

How do I reach support?

By email at [email protected], or through the community on Discord, which also has support tickets. Include the X-Request-Id of the failed call.

Is this documentation available to AIs?

Yes, as plain text in the llm.txt format.