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
- Sign up at manage.zooapi.ai.
- Verify your email address to activate the account.
- 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 inhttps://api.zooapi.ai/v1 - Anthropic SDKs and Claude Code: no
/v1, justhttps://api.zooapi.ai
3. Store your key in an environment variable
# Replace sk-xxxx with your own key
export ZOOAPI_API_KEY="sk-xxxx"$env:ZOOAPI_API_KEY="sk-xxxx"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 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 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 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 -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.
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)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.
/v1 suffix.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)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();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:
- Find the "API key" setting and paste your
sk-...key. - Find "API base URL", "Custom API domain", or "Endpoint", and enter
https://api.zooapi.aiorhttps://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
curl -fsSL https://chatgpt.com/codex/install.sh | sh
# macOS can also use Homebrew
brew install --cask codexpowershell -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.tomland~/.codex/auth.json - Windows:
%USERPROFILE%\.codex\config.tomland%USERPROFILE%\.codex\auth.json - WSL: its own
~/.codex, separate from Windows
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{
"OPENAI_API_KEY": "sk-xxxx"
}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
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
codexif not exist "%USERPROFILE%\.codex" mkdir "%USERPROFILE%\.codex"
notepad "%USERPROFILE%\.codex\config.toml"
notepad "%USERPROFILE%\.codex\auth.json"
codexNew-Item -ItemType Directory -Force "$env:USERPROFILE\.codex" | Out-Null
notepad "$env:USERPROFILE\.codex\config.toml"
notepad "$env:USERPROFILE\.codex\auth.json"
codexStart 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.
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"
claudeset 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$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"
claudeThese 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
curl -fsSL https://x.ai/cli/install.sh | bash
grok update
grok --versionConfigure
[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 = falseThis 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.
yolo = true and permission_mode = "always-approve" under [ui]. Turn this on only for trusted projects and environments.Verify
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).
{
"$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" } }
}
}"permission": { "*": "allow", "external_directory": "allow", "doom_loop": "allow" }. Do this only for trusted projects.Set the key and run
export ZOOAPI_API_KEY="sk-xxxx"
opencode debug config
opencode run "Hello"set ZOOAPI_API_KEY=sk-xxxx
opencode debug config
opencode run "Hello"$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.
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.pngEdit 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.
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.jsonCommon 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
--yoloordanger-full-accessonly in throwaway containers, disposable VMs, or environments you can roll back.
codex --sandbox workspace-write --ask-for-approval on-requestWrite tasks you can verify
A good task states the goal, the scope, the constraints, and how to check the result.
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 minuteRPH/TPH: about 1 hourRPD/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.