Integrating
Every AI Gateway endpoint, header, option and error: OpenAI and Anthropic compatible, one key for every model.
https://clikdeploy.com/v1
(https://clikdeploy.com/api/gateway/v1 answers too.) Authenticate with either:
Authorization: Bearer YOUR_API_KEY. Anthropic clients may send it as x-api-key instead. A key can carry its own monthly limit and request rate.meta:write scope, as Authorization: Bearer …. Calls are billed to the user who signed in and show under their usage by your app's name.Calls are paid from your AI credit at each model's listed price; out of credit is a 402.
| Endpoint | What it does |
|---|---|
POST /chat/completions | OpenAI Chat Completions: streaming, tools, images, structured output. |
POST /responses | OpenAI Responses API, stateless (see below): streaming, function tools, reasoning. |
POST /messages | Anthropic Messages: streaming, tools, images, thinking with signatures, cache_control. |
POST /messages/count_tokens | Input tokens for a Messages request. Anthropic's own count for a model Anthropic serves, else an estimate marked estimated: true. Free. |
GET /models | Every model: context window, max output, capabilities, supported parameters, measured speed, price. |
GET /models/{id} | One model. |
POST /embeddings | OpenAI embeddings, with the embedding models on the list. |
GET /generations/{id} | One call's model, tokens, cost, latency and speed, for 30 days (id = X-Generation-Id). |
GET /usage?days=30 | Spend and tokens per model. |
GET, PATCH /credits | Your AI credit; PATCH turns automatic top-up on or off. |
POST /credits/checkout | Buy credit. |
GET, POST /agents | Your agents; create one. /agents/{id} reads, changes (PATCH) or deletes one. |
POST /agents/{id}/chat | One agent turn, streamed as Server-Sent Events. |
GET, POST /agents/{id}/triggers | An agent's schedules and event triggers. |
python
from openai import OpenAI
client = OpenAI(base_url="https://clikdeploy.com/v1", api_key="YOUR_API_KEY")
reply = client.chat.completions.create(
model="glm-5",
messages=[{"role": "user", "content": "Hello"}],
reasoning_effort="low",
extra_headers={"X-Tags": "team=search", "Idempotency-Key": "req-8f3a"},
)
print(reply.choices[0].message.content, reply.usage.cost)json — response
{
"id": "chatcmpl-…", "object": "chat.completion", "model": "glm-5",
"choices": [{ "index": 0, "message": { "role": "assistant", "content": "Hi!" }, "finish_reason": "stop" }],
"usage": { "prompt_tokens": 9, "completion_tokens": 3, "total_tokens": 12,
"prompt_tokens_details": { "cached_tokens": 0 }, "cost": 0.000021 }
}typescript
import OpenAI from 'openai';
const client = new OpenAI({ baseURL: 'https://clikdeploy.com/v1', apiKey: 'YOUR_API_KEY' });
const response = await client.responses.create({
model: 'auto',
instructions: 'Be brief.',
input: [{ role: 'user', content: 'What is in /tmp?' }],
tools: [{ type: 'function', name: 'ls', parameters: { type: 'object', properties: { dir: { type: 'string' } } } }],
store: false,
});
// A function_call item comes back; run it, then send the whole conversation again:
// input: [...previous input, ...response.output, { type: 'function_call_output', call_id, output }]Streaming (stream: true) sends the Responses events: response.created, response.in_progress, per output item response.output_item.added, its deltas (response.output_text.delta, response.reasoning_summary_text.delta, response.function_call_arguments.delta) and .done events, response.output_item.done, then response.completed — or response.incomplete at the output limit, or response.failed carrying the error.
Stateless
input (as store: false clients do); previous_response_id, conversation, item_reference, background and built-in tools (web search, file search) are refused with 400 unsupported_parameter. Reasoning items you send back are skipped.python
import anthropic
client = anthropic.Anthropic(base_url="https://clikdeploy.com", api_key="YOUR_API_KEY")
message = client.messages.create(
model="claude-opus-5",
max_tokens=4096,
thinking={"type": "enabled", "budget_tokens": 8000},
system=[{"type": "text", "text": LONG_RULES, "cache_control": {"type": "ephemeral"}}],
messages=[{"role": "user", "content": "Plan the migration."}],
)Claude Code: ANTHROPIC_BASE_URL=https://clikdeploy.com and ANTHROPIC_API_KEY=YOUR_API_KEY. Any Gateway model can be named on the Anthropic format, not only Claude.
terminal
curl https://clikdeploy.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" -H "Content-Type: application/json" \
-H "X-Timeout-Ms: 60000" \
-d '{"model":"auto","stream":true,"stream_options":{"include_usage":true},
"messages":[{"role":"user","content":"Hello"}]}'model is a name from GET /models (glm-5, claude-opus-5). An org/model spelling (anthropic/claude-opus-5, as OpenRouter writes it) names the same model. auto lets the Gateway choose; GET /models says which model auto serves right now. Each model is listed once and served by its cheapest available provider. models: [...] (up to 5) names fallbacks tried in order.
| To get | Send |
|---|---|
model:fast | The fastest measured provider, not the cheapest. Also accepted: :nitro, "speed": "fast", "service_tier": "priority". |
model:floor | The cheapest provider first (the same as provider.sort: "price"). |
model:free | Free providers only. |
reasoning_effort | How hard a reasoning model thinks: none, minimal, low, medium, high, xhigh. On /responses it is reasoning.effort; on /messages Anthropic's thinking (a budget maps to low/medium/high; disabled is none). Also accepted: OpenRouter's reasoning: { effort } and reasoning: { enabled: false }. |
Effort is sent only to models known to reason, and how closely one follows it is its provider's call. none cannot turn reasoning off on every OpenAI-compatible provider: some reason anyway.
Every format takes OpenRouter's provider object. order tries the named providers first; only / ignore filter by provider id; allow_fallbacks: false uses only those; sort is price, throughput or latency (measured); require_parameters: true skips providers known not to take a setting you sent; max_price: { prompt, completion } (USD per million tokens) skips pricier ones. data_collection: "deny" and zdr: true are refused: the Gateway has no record of providers' retention policies.
json
{ "model": "glm-5", "messages": [...],
"provider": { "order": ["groq", "together"], "allow_fallbacks": false, "max_price": { "prompt": 1, "completion": 3 } } }temperature, top_p, top_k, stop (stop_sequences), seed, the penalties, response_format / text.format and parallel_tool_calls (Anthropic: tool_choice.disable_parallel_tool_use) are honoured where the serving model takes them. Never silently: a setting you sent that the model did not take is named in the X-Dropped-Params response header (or dropped_params on a stream's last frame). Add provider.require_parameters: true to be served only by providers that take what you send. Settings the Gateway cannot honour at all (n above 1, logprobs, audio and file input) are a 400.
On /messages, thinking blocks carry the provider's real signature (and redacted_thinking its data). Send them back unchanged: they are replayed to Anthropic, which requires them before a thinking turn's tool use, and left out for any other provider. Your cache_control breakpoints (system blocks, tools, message blocks, ttl 5m or 1h) go to Anthropic where you put them; without any, the Gateway places its own. Providers that cache on their own need none. Cache use is reported as cache_read_input_tokens / cache_creation_input_tokens (Anthropic) and prompt_tokens_details.cached_tokens / cache_write_tokens (OpenAI). Send X-Session-Id to keep a conversation on one provider, where its cache is warm.
Caching is on by default. Send X-Prompt-Cache: off on any request to opt that request out: the Gateway then sends no cache breakpoint (it also removes any cache_control you placed) and no cache key. To opt out for the whole account, switch off Let AI providers cache my prompts in Settings (or PUT /api/user/preferences with { "aiPromptCaching": false }); a request header of on never overrides it. Providers that cache on their own (OpenAI, DeepSeek, xAI, Gemini) take no request parameter to refuse it, so for them "off" means the Gateway asks for nothing and extends nothing; it cannot make a provider forget what it caches by itself.
metadata (OpenAI, Responses, Anthropic — string values) and the X-Tags header (X-Tags: team=search, env=prod) are stored on the call and filter your usage. The body wins a key both name. At most 16 tags, keys up to 64 characters, values up to 512; past that the request is a 400.
Send Idempotency-Key: <your unique key> on /chat/completions, /responses or /messages to make a retry safe. For 24 hours, the same key with the same body returns the first answer again (header Idempotent-Replayed: true, same X-Generation-Id) and is not charged again; while the first is still running it is a 409 idempotency_key_in_use with Retry-After; with a different body, 422 idempotency_key_reused. A streamed request is replayed as a stream. A request that produced no answer frees its key. The answer to a keyed request is held for those 24 hours to replay it (an answer over 512 KB cannot be replayed: 409 idempotent_result_unavailable).
X-Timeout-Ms limits how long the Gateway works on a request, every provider attempt included, from 1 second up to the 300-second ceiling every request has. Past it the answer is 408 request_timeout.
| Header | Meaning |
|---|---|
X-Generation-Id | Response: the call's id (the body's id too), for GET /generations/{id}. Not X-Request-Id, which is the platform's own trace id. |
X-RateLimit-Limit-Requests | Response: your request budget per window (the tighter of the account and the key). |
X-RateLimit-Remaining-Requests | Response: requests left in the window. |
X-RateLimit-Reset-Requests | Response: Unix seconds when the window has room again. |
Retry-After | Response, on 429 and 409: seconds to wait. |
X-Dropped-Params | Response: settings you sent that the serving model did not take. |
Idempotent-Replayed | Response: true when the answer is a replay of an earlier one. |
X-Token-Count-Source | count_tokens response: provider or estimate. |
X-Session-Id | Request: keep a conversation on one provider (prompt caching). |
X-Prompt-Cache | Request: off = no provider caching for this request (default on). |
X-Tags | Request: key=value tags, comma separated. |
X-Timeout-Ms | Request: the Gateway time limit, 1000 – 300000. |
Idempotency-Key | Request: make a retry safe (above). |
Cost: every answer's usage.cost (Anthropic: usage.cost_usd) is what the call cost you in USD.
Every /v1 error is { "error": { "message", "type", "code", "param" } } (on /messages, Anthropic's { "type": "error", "error": { "type", "message" } }). Branch on code: it is stable. A failure mid-stream is one error frame (response.failed on /responses). Model failures are 500, never 502.
| code (status) | Meaning |
|---|---|
invalid_request (400) | The body is malformed; `param` names where. |
unsupported_parameter (400) | A setting the Gateway cannot honour; `param` names it. |
rate_limit_exceeded (429) | Your own request budget; retry_after. |
insufficient_credits (402) | AI credit ran out; top up. |
key_limit_reached (402) | The API key's own monthly limit is spent. |
budget_reached (402) | The account's monthly AI budget is spent and its hard stop is on. |
model_not_found (404) | The model is not available to you. |
no_provider_matches (404) | No provider passes your `provider` settings; the message says which. |
provider_key_rejected (400) | The provider refused your OWN provider key (never moved to paid). |
context_length_exceeded (400) | The conversation does not fit the model; compact it. |
model_rejected_request (400) | The provider refused the request's shape. |
model_rate_limited (429) | The model's providers are throttling; retry_after. |
request_timeout (408) | X-Timeout-Ms ran out first. |
idempotency_key_in_use (409) | A request with this Idempotency-Key is still running. |
idempotency_key_reused (422) | The key was used with another body. |
idempotent_result_unavailable (409) | The first answer was too large to replay. |
no_model_available (503) | Nothing can serve a step right now. |
gateway_disabled (503) | An administrator switched the Gateway off. |
external_ai_disabled (503) | Paid AI is not sold right now. |
external_ai_unfunded (503) | Paid AI is sold, but no provider is funded yet. |
upstream_error (500) | Every provider failed; retry. |
internal_error (500) | The Gateway failed; retry. |