Documentation

Connect your tools in minutes.

Create an API key, point your client at ZOOAPI, and connect SDKs and coding tools such as Codex CLI, Claude Code, Grok CLI, and OpenCode.

Quick start

ZOOAPI is an API router you can sign up for online. Three steps get you ready to send requests.

1. Create an account and get your key

  1. Sign up at manage.zooapi.ai.
  2. Verify your email address to activate the account.
  3. Check your inbox for the ZOOAPI API key created for your account.

2. Set the base URL

Replace the base URL in your SDK or app with ZOOAPI's:

  • Base URL: https://api.zooapi.ai
  • OpenAI SDKs and most OpenAI-compatible clients: add /v1, as in https://api.zooapi.ai/v1
  • Anthropic SDKs and Claude Code: no /v1, just https://api.zooapi.ai

3. Store your key in an environment variable

macOS / Linux
# Replace sk-xxxx with your own key
export ZOOAPI_API_KEY="sk-xxxx"
Windows PowerShell
$env:ZOOAPI_API_KEY="sk-xxxx"
Never commit your key to a repository or ship it in client-side code. Anyone who has the key can spend your credits.

Make a first request

ZOOAPI accepts several common API formats. Use the one your code already speaks. Model names below are examples; the console lists the models your plan can use.

OpenAI Responses API

curl
curl https://api.zooapi.ai/v1/responses \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ZOOAPI_API_KEY" \
  -d '{
    "model": "gpt-5.6-sol",
    "input": "Hello, ZOOAPI! Introduce yourself in one sentence."
  }'

OpenAI Chat Completions API

curl
curl https://api.zooapi.ai/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ZOOAPI_API_KEY" \
  -d '{
    "model": "gpt-5.6-sol",
    "messages": [
      {
        "role": "user",
        "content": "Hello, ZOOAPI! Introduce yourself in one sentence."
      }
    ]
  }'

Claude Messages API

Claude-format requests send the key in the x-api-key header.

curl
curl https://api.zooapi.ai/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: $ZOOAPI_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-opus-4-6",
    "max_tokens": 1024,
    "messages": [
      {
        "role": "user",
        "content": "Hello, Claude! Introduce yourself in one sentence."
      }
    ]
  }'

Gemini API

Gemini-format requests send the key in the x-goog-api-key header.

curl
curl -X POST "https://api.zooapi.ai/v1beta/models/gemini-3-flash-preview:generateContent" \
  -H "x-goog-api-key: $ZOOAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {
        "parts": [
          {
            "text": "Hello, Gemini! Introduce yourself in one sentence."
          }
        ]
      }
    ]
  }'

Usage and billing

Sign in at manage.zooapi.ai to see:

  • Real-time usage, broken down by model
  • Bills and top-up history

Plans and credits are explained on the pricing page and in the pricing guide.

OpenAI SDK

ZOOAPI works with the official OpenAI and Anthropic SDKs, so most apps move over with a configuration change and no code rewrite. For the OpenAI SDK, set the base URL to ZOOAPI with the /v1 suffix.

Python
import os
from openai import OpenAI

# Read the key from an environment variable
client = OpenAI(
    api_key=os.environ.get("ZOOAPI_API_KEY"),
    base_url="https://api.zooapi.ai/v1",
)

chat_completion = client.chat.completions.create(
    model="gpt-5.6-sol",
    messages=[
        {"role": "user", "content": "Write Hello World in Python"},
    ],
)

print(chat_completion.choices[0].message.content)
JavaScript / TypeScript
import OpenAI from "openai";

const openai = new OpenAI({
  apiKey: process.env.ZOOAPI_API_KEY, // your ZOOAPI API key
  baseURL: "https://api.zooapi.ai/v1",
});

async function main() {
  const chatCompletion = await openai.chat.completions.create({
    model: "gpt-5.6-sol",
    messages: [
      { role: "user", content: "Write Hello World in JavaScript" },
    ],
  });

  console.log(chatCompletion.choices[0].message.content);
}

main();

Anthropic SDK

For Claude-format requests, change only the base URL.

The Claude-compatible base URL differs from the OpenAI one: it has no /v1 suffix.
Python
import os
from anthropic import Anthropic

client = Anthropic(
    api_key=os.environ.get("ZOOAPI_API_KEY"),
    base_url="https://api.zooapi.ai",
)

message = client.messages.create(
    model="claude-opus-4-6",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Explain first-principles thinking"},
    ],
)

print(message.content[0].text)
JavaScript / TypeScript
import Anthropic from "@anthropic-ai/sdk";

const anthropic = new Anthropic({
  apiKey: process.env.ZOOAPI_API_KEY, // your ZOOAPI API key
  baseURL: "https://api.zooapi.ai",
});

async function main() {
  const message = await anthropic.messages.create({
    model: "claude-opus-4-6",
    max_tokens: 1024,
    messages: [
      { role: "user", content: "Explain first-principles thinking" },
    ],
  });

  console.log(message.content[0].text);
}

main();
On Codex plans, Claude model names map to GPT models by default: claude-opus* → gpt-5.6-sol, claude-sonnet* → gpt-5.6-terra, claude-haiku* → gpt-5.6-luna.

Other clients

Any client that lets you set a custom OpenAI or Claude endpoint connects the same way:

  1. Find the "API key" setting and paste your sk-... key.
  2. Find "API base URL", "Custom API domain", or "Endpoint", and enter https://api.zooapi.ai or https://api.zooapi.ai/v1, depending on what the client expects.

If a project hard-codes api.openai.com and has no base URL setting, change that address to api.zooapi.ai in its source code.

Codex CLI / App

Codex is a coding agent that reads your project, edits files, and runs commands. Connect it to ZOOAPI with a custom model provider. Codex supports only wire_api = "responses".

Install Codex

macOS / Linux / WSL
curl -fsSL https://chatgpt.com/codex/install.sh | sh

# macOS can also use Homebrew
brew install --cask codex
Windows PowerShell
powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"

Check the install with codex --version, and run codex app to open the desktop app. On WSL, keep projects inside the WSL file system, for example in ~/code.

Configuration files

  • macOS / Linux: ~/.codex/config.toml and ~/.codex/auth.json
  • Windows: %USERPROFILE%\.codex\config.toml and %USERPROFILE%\.codex\auth.json
  • WSL: its own ~/.codex, separate from Windows
config.toml
model_provider = "zooapi"
model = "gpt-5.6-sol"
model_reasoning_effort = "xhigh"
plan_mode_reasoning_effort = "xhigh"
model_reasoning_summary = "none"
model_context_window = 1050000
model_auto_compact_token_limit = 945000
stream_idle_timeout_ms = 900000
approval_policy = "on-request"
sandbox_mode = "workspace-write"
suppress_unstable_features_warning = true

[model_providers.zooapi]
name = "OpenAI"
base_url = "https://api.zooapi.ai"
wire_api = "responses"
experimental_bearer_token = "sk-xxxx"
requires_openai_auth = true

[features]
goals = true
remote_connections = true
auth.json
{
  "OPENAI_API_KEY": "sk-xxxx"
}
Put the same ZOOAPI key in experimental_bearer_token and in auth.json. Both files then contain your key, so keep them out of repositories and restrict their permissions.
on-request and workspace-write make Codex ask before it runs commands outside your project. Switch to approval_policy = "never" and sandbox_mode = "danger-full-access" only in disposable containers or VMs, or in environments you can roll back.

Create the files

macOS / Linux
mkdir -p ~/.codex
# Back up existing files first
[ -f ~/.codex/config.toml ] && cp ~/.codex/config.toml ~/.codex/config.toml.bak
[ -f ~/.codex/auth.json ] && cp ~/.codex/auth.json ~/.codex/auth.json.bak

# Paste the contents above into each file, then save
nano ~/.codex/config.toml
nano ~/.codex/auth.json
chmod 600 ~/.codex/auth.json

cd your-project
codex
Windows CMD
if not exist "%USERPROFILE%\.codex" mkdir "%USERPROFILE%\.codex"
notepad "%USERPROFILE%\.codex\config.toml"
notepad "%USERPROFILE%\.codex\auth.json"

codex
Windows PowerShell
New-Item -ItemType Directory -Force "$env:USERPROFILE\.codex" | Out-Null
notepad "$env:USERPROFILE\.codex\config.toml"
notepad "$env:USERPROFILE\.codex\auth.json"

codex

Start Codex from inside your project so it works in the right directory. If a setting doesn't take effect, check which config file Codex actually reads, the environment variables in your current shell, and whether a profile overrides your defaults.

Claude Code

Claude Code connects to ZOOAPI through environment variables. Set them in your terminal, then run claude.

macOS / Linux
export ANTHROPIC_AUTH_TOKEN="sk-xxxx"
export ANTHROPIC_BASE_URL="https://api.zooapi.ai"
# Optional: choose the models behind Claude Code's opus, sonnet, and haiku tiers
export ANTHROPIC_DEFAULT_OPUS_MODEL="gpt-5.6-sol"
export ANTHROPIC_DEFAULT_SONNET_MODEL="gpt-5.6-terra"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="gpt-5.6-luna"

claude
Windows CMD
set ANTHROPIC_AUTH_TOKEN=sk-xxxx
set ANTHROPIC_BASE_URL=https://api.zooapi.ai
set ANTHROPIC_DEFAULT_OPUS_MODEL=gpt-5.6-sol
set ANTHROPIC_DEFAULT_SONNET_MODEL=gpt-5.6-terra
set ANTHROPIC_DEFAULT_HAIKU_MODEL=gpt-5.6-luna

claude
Windows PowerShell
$env:ANTHROPIC_AUTH_TOKEN="sk-xxxx"
$env:ANTHROPIC_BASE_URL="https://api.zooapi.ai"
$env:ANTHROPIC_DEFAULT_OPUS_MODEL="gpt-5.6-sol"
$env:ANTHROPIC_DEFAULT_SONNET_MODEL="gpt-5.6-terra"
$env:ANTHROPIC_DEFAULT_HAIKU_MODEL="gpt-5.6-luna"

claude

These variables last for the current terminal session. Add them to your shell profile to keep them.

Grok CLI

Grok CLI connects through ZOOAPI's Responses-compatible endpoint. Its config file is ~/.grok/config.toml (Windows: %USERPROFILE%\.grok\config.toml).

Install or update

macOS / Linux
curl -fsSL https://x.ai/cli/install.sh | bash
grok update
grok --version

Configure

~/.grok/config.toml
[models]
default = "grok-4.7"

[endpoints]
models_base_url = "https://api.zooapi.ai"

[model."grok-4.7"]
model = "grok-4.7"
name = "Grok 4.7"
api_key = "sk-xxxx"
api_backend = "responses"
context_window = 500000
supports_backend_search = true

[session]
auto_compact_threshold_percent = 80

[ui]
max_thoughts_width = 120
compact_mode = false

This file contains your key. On macOS / Linux, run chmod 600 ~/.grok/config.toml. You can use any Grok model your plan includes; the console lists the current model names.

To let Grok run tool calls without asking, add yolo = true and permission_mode = "always-approve" under [ui]. Turn this on only for trusted projects and environments.

Verify

shell
grok inspect
grok models
grok --model grok-4.7 --output-format json -p 'Reply with GROK_OK only'

OpenCode

OpenCode connects through the Responses-compatible endpoint with gpt-5.6-sol. The global config file is ~/.config/opencode/opencode.jsonc (Windows: %USERPROFILE%\.config\opencode\opencode.jsonc).

opencode.jsonc
{
  "$schema": "https://opencode.ai/config.json",
  "model": "openai/gpt-5.6-sol",
  "small_model": "openai/gpt-5.6-sol",
  "provider": {
    "openai": {
      "options": {
        "baseURL": "https://api.zooapi.ai",
        "apiKey": "{env:ZOOAPI_API_KEY}"
      },
      "models": {
        "gpt-5.6-sol": {
          "headers": {
            "originator": "opencode"
          }
        }
      }
    }
  },
  "agent": {
    "title": { "options": { "reasoningEffort": "none" } },
    "build": { "variant": "xhigh", "options": { "reasoningSummary": "detailed", "textVerbosity": "high" } },
    "plan": { "variant": "xhigh", "options": { "reasoningSummary": "detailed", "textVerbosity": "high" } }
  }
}
To skip OpenCode's permission prompts, add "permission": { "*": "allow", "external_directory": "allow", "doom_loop": "allow" }. Do this only for trusted projects.

Set the key and run

macOS / Linux
export ZOOAPI_API_KEY="sk-xxxx"
opencode debug config
opencode run "Hello"
Windows CMD
set ZOOAPI_API_KEY=sk-xxxx
opencode debug config
opencode run "Hello"
Windows PowerShell
$env:ZOOAPI_API_KEY="sk-xxxx"
opencode debug config
opencode run "Hello"

Images API

gpt-image-2.5-flare generates and edits images through the Images API. Codex can help you write image workflows, but gpt-image-2.5-flare can't be Codex's main model.

Generate an image

Send POST /v1/images/generations, then decode data[0].b64_json from the response to get the image file.

shell
export API_BASE_URL="https://api.zooapi.ai"
export ZOOAPI_API_KEY="sk-xxxx"

curl --fail-with-body -sS "$API_BASE_URL/v1/images/generations" \
  -H "Authorization: Bearer $ZOOAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2.5-flare",
    "prompt": "A square poster for a modern tea brand with a glass cup, grapefruit slices, and a fresh white and green background",
    "n": 1,
    "size": "1024x1024",
    "quality": "low",
    "output_format": "png"
  }' > gpt-image-response.json

jq -er '.data[0].b64_json' gpt-image-response.json | base64 --decode > gpt-image.png

Edit an image

Send POST /v1/images/edits as multipart/form-data, uploading the source image as image[]. For inpainting, also send a mask with an alpha channel.

shell
curl --fail-with-body -sS "$API_BASE_URL/v1/images/edits" \
  -H "Authorization: Bearer $ZOOAPI_API_KEY" \
  -F 'model=gpt-image-2.5-flare' \
  -F 'image[]=@gpt-image.png' \
  -F 'prompt=Keep the subject and composition and change the background to a rainy neon street at night' \
  -F 'size=1024x1024' \
  -F 'quality=low' \
  -F 'output_format=png' > gpt-image-edit-response.json

Common sizes are 1024x1024, 1536x1024, and 1024x1536. quality can be low, medium, or high. The source image and mask must share the same format and size, and each file must be smaller than 50 MB.

Using coding agents safely

Coding agents such as Codex can edit files and run commands. Set clear access boundaries and keep a human checkpoint.

  • Sandbox controls what the agent can read and write. Approval controls when it must ask before running a command or leaving the sandbox.
  • Plan first, then edit. Review the diff and run the relevant tests after every round of changes.
  • Be careful with commands that delete, migrate, overwrite, or escalate privileges.
  • Keep keys in environment variables or a secret manager, and never commit them.
  • Use --yolo or danger-full-access only in throwaway containers, disposable VMs, or environments you can roll back.
shell
codex --sandbox workspace-write --ask-for-approval on-request

Write tasks you can verify

A good task states the goal, the scope, the constraints, and how to check the result.

Prompt
Goal: move the old payment callback handling to the new handler.
Scope: change only api/handler/payment* and the related tests.
Constraints: don't change the database schema or external API fields.
Verify: run the payment tests and list any risks they don't cover.

Troubleshooting

Why do some API calls return 404 Not Found?

Usually the base URL is wrong. Many libraries, such as LangChain, need the /v1 suffix rather than the bare domain. For OpenAI-compatible endpoints, use https://api.zooapi.ai/v1.

Why do I get "401: Incorrect API key provided"?

This usually means the request went to OpenAI's official servers instead of ZOOAPI. Make sure you changed the request address (base_url) to https://api.zooapi.ai, not only the API key.

What if my open-source project has no base_url setting?

Find where the project sets its API address in the source code and change the hard-coded api.openai.com to api.zooapi.ai.

Why does the user management API (such as /x-users) return 401 Unauthorized?

To prevent abuse, core management APIs, such as those that create or manage subaccounts, require a minimum balance on the calling account. Your balance usually needs to be above $100.

What do I need to create a subaccount?

Two conditions usually apply: the parent account's balance must be above $100, and the first top-up for the new subaccount must be at least $2.

Why do I see "Insufficient balance" when my account still has credit?

To prevent overdrafts and losses, new API calls are blocked once your balance drops below $1. Top up to continue.

Why do I get 429 Too many requests or "Rate limit XXX reached"?

You hit a rate-limit window for your account or the model. Common reasons are RPM, RPH, RPD, TPM, TPH, and TPD. If the error names RPH, the model's hourly request limit is used up.

  • Lower concurrency and retry with exponential backoff.
  • Check which limit the error names first.
  • Spread the load across time windows or models.
  • Ask your administrator to raise the relevant limit or model quota.
My RPH limit is 300. Why did only 40 requests succeed?

RPH counts every attempt that enters the limit check, while usage statistics record only successful requests. Concurrent requests, automatic retries, and requests that fail before the limit is reached can all consume RPH without showing up in usage.

Are concurrent requests blocked all at once? How long does a limit last?

No. Each request is checked on its own: requests under the limit succeed, and requests over it return 429.

  • RPM / TPM: about 1 minute
  • RPH / TPH: about 1 hour
  • RPD / TPD: a daily quota, restored when the server's day ends
Why does my limit never seem to reset?

Check the reason in the error. RPM, RPH, TPM, and TPH usually mean you are still inside a short window or cooldown. RPD and TPD mean the daily quota is used up until the server's date rolls over. Continuous retries can also extend a cooldown, so lower concurrency and use exponential backoff.

ZOOAPI is an independent service. It is not affiliated with or endorsed by OpenAI, Anthropic, Google, or xAI. Model availability and billing conditions can change, and the console is the source of truth.