Skip to content

API Reference

One OpenAI-compatible endpoint. Send model: "auto" and ZeroOptimize™ routes the request to the best free model available at that moment, with automatic failover. Inference cost is $0 on every plan; plans differ by daily call volume.

Overview

Base URL
https://www.zerolimitai.com/api/v1
Authentication
Authorization: Bearer zlai_…
Format
JSON · SSE when stream: true
Compatible with
openai SDKs, LangChain, Cline, Continue, Aider…

Always use the www host. The apex domain redirects with a 307 and some HTTP clients drop the Authorization header on the hop.

Authentication

Every request carries your key as a Bearer token. Create keys in Developer settings. A free account gets one key for a 7-day evaluation at 100 calls/day; after that the key returns 402 upgrade_required until the account has a plan. Annual accounts share a 2,000 calls/day quota and Lifetime accounts a 5,000 calls/day one. Keys are stored as bcrypt hashes and shown once.

Authorization: Bearer zlai_xxxxxxxxxxxxxxxxxxxxxxxx
Keep the key server-side. Never ship it in a browser bundle, a mobile app or a public repository — rotate it from the dashboard if it leaks.

Endpoints

POST /chat/completions

Send a conversation, get a completion. /chat is the same handler under a shorter path.

Request body

ParameterTypeDescription
messagesrequiredarray{ role, content } objects; role is "system", "user" or "assistant".
modelstringDefault "auto": ZeroOptimize™ picks the best free model for this request. Pass an id from GET /models to try that model first, with the rest of the chain as failover. Any other id — an OpenAI or Anthropic model name, one we retired — is routed by ZeroOptimize instead of failing, so an existing app works by changing base_url alone. It is never silent: the response's model field reports which model actually answered and X-ZeroOptimize-Substituted-From carries the id you asked for.
streambooleanDefault false. When true, the response is text/event-stream with OpenAI chat.completion.chunk events, a final chunk with finish_reason ("stop", or "length" when max_tokens cut it), then data: [DONE].
agentIdstringOptional. Id of one of your ZeroLimitAI agents. Its system prompt is prepended unless your messages already start with a system message. Agents are created in the app.

Sampling: temperature (0–2), top_p (0–1), stop (string or up to 4), seed, presence_penalty and frequency_penalty (−2–2) are passed to the model's provider. max_tokens (or max_completion_tokens, 1–32,768) caps the visible answer and sets finish_reason: "length" when it cuts. Out-of-range values return 400 invalid_param.

Function calling

Send OpenAI tools (and, if you want, tool_choice and parallel_tool_calls). The request goes to the best free model that supports tools, with the same failover, and tool_calls come back in the OpenAI shape, streaming included. Return results as role: "tool" messages with the matching tool_call_id. Pinning a model without tool support returns 400 invalid_param; max_tokens is not applied to tool requests.

from openai import OpenAI
import json

client = OpenAI(base_url="https://www.zerolimitai.com/api/v1", api_key="zlai_xxxxxxxxxxxxxxxxxxxxxxxx")
tools = [{
    "type": "function",
    "function": {
        "name": "get_weather",
        "description": "Current weather for a city",
        "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]},
    },
}]
messages = [{"role": "user", "content": "What's the weather in Madrid?"}]
first = client.chat.completions.create(model="auto", messages=messages, tools=tools)
call = first.choices[0].message.tool_calls[0]
args = json.loads(call.function.arguments)          # {"city": "Madrid"}

messages += [first.choices[0].message,
             {"role": "tool", "tool_call_id": call.id, "content": json.dumps({"temp_c": 21})}]
final = client.chat.completions.create(model="auto", messages=messages, tools=tools)
print(final.choices[0].message.content)

Example request

curl https://www.zerolimitai.com/api/v1/chat/completions \
  -H "Authorization: Bearer zlai_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "messages": [
      { "role": "user", "content": "What is the capital of France?" }
    ]
  }'

Example response

{
  "id": "chatcmpl-9d2f6c1e-…",
  "object": "chat.completion",
  "created": 1758300000,
  "model": "qwen/qwen3.8-27b:free",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "The capital of France is Paris." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 14, "completion_tokens": 9, "total_tokens": 23 }
}

# Response headers
X-Request-Id: chatcmpl-9d2f6c1e-…
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 9987
X-RateLimit-Reset: 1758326400

model is whatever the router used — it changes with the daily ranking and with failover. Do not hardcode it.

Streaming (Python)

from openai import OpenAI

client = OpenAI(
    base_url="https://www.zerolimitai.com/api/v1",
    api_key="zlai_xxxxxxxxxxxxxxxxxxxxxxxx",
)

stream = client.chat.completions.create(
    model="auto",
    messages=[{"role": "user", "content": "Tell me a joke."}],
    stream=True,
)

for chunk in stream:
    print(chunk.choices[0].delta.content or "", end="", flush=True)

With an agent

curl https://www.zerolimitai.com/api/v1/chat \
  -H "Authorization: Bearer zlai_xxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "agentId": "YOUR_AGENT_ID",
    "messages": [{ "role": "user", "content": "Summarise what you know about my project." }]
  }'

GET /models

"auto" plus the live chain, in the OpenAI /v1/models format. Ids are provider ids (for example qwen/qwen3.8-27b:free) and change as the ranking does — read them here rather than hardcoding.

Example request

curl https://www.zerolimitai.com/api/v1/models \
  -H "Authorization: Bearer zlai_xxxxxxxxxxxxxxxxxxxxxxxx"

Example response

{
  "object": "list",
  "data": [
    { "id": "auto", "object": "model", "created": 1758300000, "owned_by": "zerolimitai" },
    { "id": "qwen/qwen3.8-27b:free", "object": "model", "created": 1758300000, "owned_by": "openrouter" },
    { "id": "inclusionai/ling-3.0-flash-fin:free", "object": "model", "created": 1758300000, "owned_by": "openrouter" },
    { "id": "openai/gpt-oss-120b", "object": "model", "created": 1758300000, "owned_by": "groq" }
  ]
}

GET /usage

API calls today against your daily quota (UTC day) and this month's requests and tokens. Only API calls count — chat in the app is separate. The same numbers arrive on every completion in the X-RateLimit-* headers.

Example request

curl https://www.zerolimitai.com/api/v1/usage \
  -H "Authorization: Bearer zlai_xxxxxxxxxxxxxxxxxxxxxxxx"

Example response

{
  "today": { "used": 42, "limit": 5000, "remaining": 4958, "resets_at": "2026-09-20T00:00:00.000Z" },
  "month": { "requests": 1204, "tokens_in": 892400, "tokens_out": 412100 },
  "plan": "LIFETIMEPRO"
}

Errors

Errors use the OpenAI shape, so the official SDKs surface error.message and error.code directly:

{
  "error": {
    "message": "temperature must be a number between 0 and 2.",
    "type": "invalid_request_error",
    "code": "invalid_param",
    "param": "temperature"
  }
}
StatuscodeMeaning
400invalid_jsonBody is not valid JSON.
400missing_messagesmessages is missing or empty.
400invalid_paramA sampling field is out of range or the wrong type (temperature, top_p, stop, seed, penalties, max_tokens). The error's param names it.
401invalid_keyMissing or invalid API key.
403upgrade_requiredYour plan does not include API access.
403account_suspendedThe account behind the key is suspended.
404agent_not_foundagentId unknown or not owned by your account.
413request_too_largeFree accounts only: the request is over about 16,000 input tokens. Send a shorter conversation, or use Annual or Lifetime.
429rate_limitedMore than 60 requests/min on this key (or the IP burst limit). Retry-After header in seconds.
429daily_limitDaily API quota used. X-RateLimit-Reset says when it resets (midnight UTC).
502upstream_errorEvery model in the chain failed. Rare: the chain has several free models plus a safety net. Retry.

type is one of invalid_request_error, authentication_error, permission_error, rate_limit_error, api_error.

Rate limits & quota

Burst
60 requests / minute per key
Free week
25 calls / day for 7 days
Annual
2,000 calls / day
Lifetime
5,000 calls / day

Daily quotas are per account (all keys share it) and reset at midnight UTC. Every successful completion returns X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (unix time). A 429 carries Retry-After in seconds. Need more than 5,000/day? Write to us.

Your own provider keys (Annual and Lifetime)

Add a Groq and/or OpenRouter key in Integrations and the same endpoint keeps answering past your daily calls: once they run out — or if our quota fails — requests go to your own key, with the same ranking, failover and no-training filter, and no limit of ours. Those responses carry X-ZeroLimit-Keys: own instead of the quota headers, and do not count against the daily calls. We only call free models (Groq's free-plan models and OpenRouter's :free ones); free accounts on both providers work, and an account with a card attached may be billed by its provider. Requests with tools on your own keys need the OpenRouter key. A rejected key returns 502 upstream_error naming it.

SDKs & tools

Anything that speaks the OpenAI format and lets you set a base URL works unchanged. Change two values and use "auto" as the model.

// Node.js — npm install openai
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://www.zerolimitai.com/api/v1",
  apiKey: "zlai_xxxxxxxxxxxxxxxxxxxxxxxx",
});

const response = await client.chat.completions.create({
  model: "auto",
  messages: [{ role: "user", content: "Hello!" }],
});

console.log(response.choices[0].message.content);
# LangChain (Python) — pip install langchain-openai
from langchain_openai import ChatOpenAI

llm = ChatOpenAI(model="auto", base_url="https://www.zerolimitai.com/api/v1", api_key="zlai_xxxxxxxxxxxxxxxxxxxxxxxx")

Step-by-step guides per tool: /docs/integrations. Editor and tool setups (Cline, Roo Code, Continue, Aider, Open WebUI) are on the developers page. The machine-readable version of this reference is the OpenAPI spec and /llms.txt.

Ready to build?

Free key in a minute, no card. Live service health on /status.

Get API key

Stop paying per token.

One endpoint. $0 inference.

Free 7-day API key in a minute — no card. Then $49 a year or $99 once.