Two ways to start: point your existing AI API at ZeroCredit, or connect your provider API keys in the dashboard. Either way you keep your models, prompts and provider billing.
ZeroCredit is a drop-in AI infrastructure and FinOps layer. It sits underneath your existing AI application: intelligent routing, semantic caching, budget controls, fallback chains and ML-powered cost optimization — with evidence for every dollar saved.
Nothing is applied to your traffic automatically. Optimization recommendations wait for your approval.
curl https://zerocreditai.com/api/public/v1/chat/completions \
-H "Authorization: Bearer $ZEROCREDIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "zerocredit-balanced",
"messages": [
{ "role": "system", "content": "You are concise." },
{ "role": "user", "content": "Summarize our refund policy." }
]
}'from openai import OpenAI
client = OpenAI(
api_key=os.environ["ZEROCREDIT_API_KEY"],
base_url="https://zerocreditai.com/api/public/v1",
)
resp = client.chat.completions.create(
model="zerocredit-balanced",
messages=[{"role": "user", "content": "Summarize our refund policy."}],
)
print(resp.choices[0].message.content)import OpenAI from "openai";
const client = new OpenAI({
apiKey: process.env.ZEROCREDIT_API_KEY,
baseURL: "https://zerocreditai.com/api/public/v1",
});
const resp = await client.chat.completions.create({
model: "zerocredit-balanced",
messages: [{ role: "user", content: "Summarize our refund policy." }],
});from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="zerocredit-balanced",
api_key=os.environ["ZEROCREDIT_API_KEY"],
base_url="https://zerocreditai.com/api/public/v1",
)Every request carries a ZeroCredit API token as a bearer token. Tokens are prefixed zc_.
Authorization: Bearer zc_your_token_here
Everything an AI agent or code generator needs to integrate with ZeroCredit AI is published at predictable URLs and needs no credentials to read.
| Resource | What it is |
|---|---|
| https://zerocreditai.com/openapi.json | OpenAPI 3.1 specification for the ZeroCredit AI API, including security schemes and OAuth scopes. |
| https://zerocreditai.com/api/openapi.yaml | The same specification in YAML. |
| https://zerocreditai.com/agents.md | Agent instructions: when to use ZeroCredit AI, how to call it, endpoints and error handling. |
| https://zerocreditai.com/api/public/v1/status | Service status, endpoints, capabilities, onboarding and rate limits. No authentication. |
| https://zerocreditai.com/api/public/v1/catalog | Public model catalog with providers, context windows and list prices. No authentication. |
| https://zerocreditai.com/api/public/v1/sandbox/chat/completions | Sandbox chat completion returning a deterministic canned response. No authentication, no billing, no provider call. |
| https://zerocreditai.com/llms.txt | Plain-text index of ZeroCredit AI pages and developer resources for LLMs. |
| https://zerocreditai.com/mcp | Model Context Protocol server (OAuth 2.0) exposing usage, spend and provider-key tools. |
| https://zerocreditai.com/.well-known/oauth-authorization-server | RFC 8414 authorization server metadata: issuer, same-origin OAuth endpoints and the scopes an agent can request. |
| https://zerocreditai.com/.well-known/openid-configuration | The same metadata at the OpenID Connect discovery location. |
| https://zerocreditai.com/.well-known/oauth-protected-resource | RFC 9728 protected-resource metadata for the MCP endpoint. |
OAuth 2.0 endpoints
Authorization code flow with PKCE and dynamic client registration, served on this domain at /api/public/oauth/authorize, /token, /register, /userinfo, /revoke and /jwks.json. API tokens (zc_...) remain available and are the simplest option for server-to-server agents.
Rate-limit headers
Every API response carries RateLimit-Policy (120 requests per 60 seconds per authenticated caller). Responses for an identified caller also carry RateLimit, RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset. A 429 includes Retry-After in seconds.
Unknown paths return HTTP 404 with a structured JSON body under /api/, or a Markdown body when the request sends Accept: text/markdown.
ZeroCredit AI CLI
export ZEROCREDIT_API_KEY=zc_your_token_here npx @zerocredit/cli status npx @zerocredit/cli catalog npx @zerocredit/cli models npx @zerocredit/cli chat "Summarise our AI spend policy"
POST https://zerocreditai.com/api/public/v1/chat/completions — standard OpenAI chat-completions wire format.
| Field | Notes |
|---|---|
| model | A provider model ID or a ZeroCredit routing alias (see Models & routing). |
| messages | Full array. system, developer, user, assistant and tool roles; turn structure preserved. |
| content | String, or an array of parts with text, image_url and file (data: URL) parts for multimodal requests. |
| modalities | ["text", "image"] asks for image generation through the chat endpoint; the reply carries the image under zerocredit.images and returns a complete response even when stream is set. Runs on your image-capable provider key. |
| stream | true for a Server-Sent Events response. |
| temperature, top_p, stop, n, seed | Passed through to the provider. |
| max_tokens / max_completion_tokens | Either is accepted. |
| presence_penalty, frequency_penalty | Passed through where the provider supports them. |
| response_format | JSON / structured output where the provider supports it. |
| tools, tool_choice, parallel_tool_calls | Function calling on tool-capable providers. |
| logprobs, top_logprobs | Passed through where supported. |
| metadata | Flat string map. customer_ref and feature are used for cost attribution. |
Responses are OpenAI-shaped, plus a non-standard `zerocredit` block with cost evidence:
{
"id": "chatcmpl-zc-...",
"object": "chat.completion",
"created": 1767225600,
"model": "gemini-2.5-flash",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "..." },
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 218,
"completion_tokens": 96,
"total_tokens": 314
},
"zerocredit": {
"provider": "google",
"cost_usd": 0.00021,
"savings_usd": 0.0017,
"cache_hit": false,
"used_user_key": true,
"latency_ms": 740,
"routing_mode": "balanced",
"plan": { "tier": "free" }
}
}Standard clients ignore the extra block, so it is safe to leave in place. Read it when you want per-request cost and savings evidence inside your own logs.
Both use the same ZeroCredit token and run on your own provider keys — never on a consumer subscription. If no connected key can perform the capability, the error says so and names the credential that would enable it.
POST https://zerocreditai.com/api/public/v1/images/generations — OpenAI-shaped image generation (prompt, optional size; n=1, URL responses). Runs on your OpenAI, Google or xAI key; the reply adds a zerocredit block with provider, model and cost.POST https://zerocreditai.com/api/public/v1/embeddings — OpenAI-shaped embeddings (input string or array, optional model). Runs on your OpenAI or Google key. Embeddings execute on the provider's embeddings endpoint, never through chat.Set "stream": true to receive Server-Sent Events. Chunks are chat.completion.chunk objects and the stream ends with data: [DONE].
data: {"id":"chatcmpl-zc-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant"}}]}
data: {"id":"chatcmpl-zc-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"Hello"}}]}
data: {"id":"chatcmpl-zc-...","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]tool_calls, with finish_reason: "tool_calls" on the final chunk.GET https://zerocreditai.com/api/public/v1/models returns the routing aliases plus the models available to your account, in the standard { object: "list", data: [...] } shape.
curl https://zerocreditai.com/api/public/v1/models -H "Authorization: Bearer $ZEROCREDIT_API_KEY"
Send a provider model ID to pin one model, or a routing alias to let ZeroCredit choose:
| Model value | Behaviour |
|---|---|
| zerocredit-cheapest | Lowest cost model that can handle the request. |
| zerocredit-fastest | Lowest observed latency. |
| zerocredit-balanced | Weighted score across cost, latency and quality. |
| zerocredit-premium | Highest quality model available to you. |
| zerocredit-auto | Same as balanced — the safe default. |
| <provider model id> | Pinned. No cross-model routing; caching, budgets and fallbacks still apply. |
Routing only ever considers models your connected providers can actually serve, and requests with images or tools are routed only to models with those capabilities.
| Header | Meaning |
|---|---|
| X-Request-Id | Unique request ID. Include it in support requests. |
| X-ZC-Model | The model that actually served the request. |
| X-ZC-Cost-USD | Cost attributed to this request. |
| X-ZC-Cache | hit or miss for semantic cache. |
Logging these four values next to your own request IDs gives you a cost dashboard without parsing response bodies.
Tag requests so spend rolls up per end customer and per product feature in the Customer Costs and Finance views.
# headers
x-zerocredit-customer: acct_10482
x-zc-feature: support-inbox
# or in the request body
{
"model": "zerocredit-balanced",
"messages": [ ... ],
"metadata": {
"customer_ref": "acct_10482",
"feature": "support-inbox"
}
}customer_ref — an internal account ID, not an email.Which of these apply to a given request depends on the plan active on the account. Every signed-in account is on Free by default until a paid plan is active, and the applied plan is reported in the zerocredit.plan block.
{
"error": {
"message": "Invalid or revoked token",
"type": "authentication_error",
"code": null,
"param": null
}
}| Status | Meaning and what to do |
|---|---|
| 400 | invalid_request_error — malformed body or unsupported field. Fix and resend; do not retry blindly. |
| 401 | authentication_error — missing, invalid or revoked token. Rotate the token. |
| 402 | insufficient_quota — budget hard-stop or provider credit exhausted. Raise the limit or top up the provider account. |
| 429 | rate_limit_error — provider or account rate limit. Retry with exponential backoff and jitter. |
| 5xx | api_error — transient upstream failure. Retry a couple of times with backoff; fallback chains already retry across providers. |
Errors surface the underlying provider message where one exists, so failures are diagnosable rather than generic.
web_search_options: {} (or a { "type": "web_search" } entry in tools) and the request runs on a provider's own search mechanism using your connected key: Google Search grounding, the OpenAI web_search tool, the Anthropic web_search server tool, or Perplexity Sonar (always search-grounded). Sources come back as OpenAI-style url_citation annotations plus azerocredit.web_search block. Provider limits apply: the searching provider bills each search, grounded answers are returned complete rather than streamed, Google cannot combine grounding with your own function tools in one call, and OpenAI does not report the queries it ran. Requests that need search never fall back to a platform model or to model knowledge — if no connected key can search, the call fails with the credential type that would enable it. Wording alone ("search the web…") never switches search on; the parameter does.No. You can either point your existing OpenAI-compatible client at the ZeroCredit base URL, or connect your provider API keys in the dashboard and use the console, playground and cost tooling. Most teams do both.
Yours. When you connect your own provider keys (BYOK), calls are made with your key and billed by your provider under your existing pricing, discounts and rate limits.
No. Optimization recommendations are surfaced for review and applied only when you choose to apply them. Routing modes and caching are opt-in settings you control.
No. The chat completions endpoint speaks the standard OpenAI wire format, so changing the base URL and API key in your existing SDK is enough.