Models and routing
Discover aliases and capabilities, choose a route, and inspect optimization receipts.
Frontier models through Kendr Cloud
The model gateway accepts Authorization: Bearer kndr_live_... and exposes the model aliases currently available to your Kendr account. Existing desktop clients can keep using /api/v1/llm/*; new integrations can use the standard /v1/* routes.
| Route | Purpose |
|---|---|
| GET /api/public/models | Public, unauthenticated catalog for crawlable model pages and pre-login discovery. It omits private routes and account-specific aliases. |
| GET /v1/models | List currently available Kendr model aliases. |
| POST /v1/responses | Generate with the OpenAI Responses shape, including streaming, tools, and optional web search. |
| POST /v1/chat/completions | Use OpenAI-compatible chat clients, SSE chunks, and optional web search. |
| POST /v1/messages | Use the Anthropic Messages request and response shape, including optional streaming. |
| POST /v1/messages/count_tokens | Free Anthropic-compatible token estimate for a message request. |
| POST /v1/video/analyses | Queue an account-scoped asynchronous video analysis. |
| GET /v1/video/analyses/{id} | Poll video analysis state and result. |
| GET /api/v1/openapi.json | Download the model-only OpenAPI contract. |
| GET|POST /api/me/ai/preferences | Read or save default and mode-specific aliases after Kendr login. |
Discover public models without a key
curl https://api.kendr.org/api/public/models
{
"object": "list",
"version": "sha256:<content-digest>",
"last_updated": "<RFC3339 timestamp>",
"pricing_policy": {
"currency": "credits",
"markup_percent": 5,
"normal_markup_percent": 5,
"intelligent_markup_percent": 5,
"quote_basis": "default_available_route"
},
"data": [
{
"id": "<public alias>",
"slug": "<public alias>",
"display_name": "<display name>",
"family": "<model family>",
"mode": "normal",
"context_window": 0,
"latency_tier": "<tier>",
"capabilities": [],
"available": true,
"availability": "available",
"status_reason": "Available for API requests.",
"pricing": {
"currency": "credits",
"credits_per_million_input": 0,
"credits_per_million_cached_input": 0,
"credits_per_million_output": 0,
"tiers": []
}
}
]
}
The values above illustrate the response shape, not a quoted model or price. Read the live payload, retain its version with generated pages or cached records, and refresh when that content digest changes. Use GET /v1/models after authentication because account-specific availability can differ.
curl https://api.kendr.org/v1/chat/completions \
-H "Authorization: Bearer kndr_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: my-request-001" \
-d '{
"model": "kendr-intelligent",
"web_search": true,
"messages": [{"role": "user", "content": "Summarize this decision."}]
}'
Text model aliases can stream responses and can use web search when the route and account configuration support it. Omit web_search to let Kendr decide from the current request, set it to true to request current context, or set it to false to prohibit search. Idempotency-Key is optional on /v1/* requests — one is generated per request when absent, and supplying your own stable key makes retries replay the settled result instead of charging again. Successful responses include the final Kendr usage record.
Choose a Kendr Route through the API
Kendr Routes bundle model selection and context behavior into the model alias. Choose an optimized alias when Kendr Optimizer should prepare eligible context before the provider call, or choose the matching Direct alias when the provider must receive the original context. Do not add a client-selected optimization policy to a managed-route request.
| Product | Alias | Routing pool | Context behavior |
|---|---|---|---|
| Kendr Intelligent | kendr-intelligent | General | Optimized |
| Kendr Intelligent Direct | kendr-intelligent-direct | General | Original context |
| Kendr Coder | kendr-coder | Coding-focused | Optimized |
| Kendr Coder Direct | kendr-coder-direct | Coding-focused | Original context |
An optimized managed route always uses its server-controlled Kendr Optimizer policy. A Direct route always preserves original context. The legacy optimization request object is a compatibility control for non-managed routes only and cannot contradict a managed product's behavior; new integrations should select one of the four aliases above.
Optimized coding request
curl https://api.kendr.org/v1/responses \
-H "Authorization: Bearer $KENDR_API_KEY" \
-H "Idempotency-Key: coder-request-001" \
-H "Content-Type: application/json" \
-d '{
"model": "kendr-coder",
"input": "Review the implementation and propose a safe patch."
}'
JavaScript: general routing with original context
const response = await fetch("https://api.kendr.org/v1/responses", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KENDR_API_KEY}`,
"Idempotency-Key": crypto.randomUUID(),
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "kendr-intelligent-direct",
input: "Summarize the relevant decisions in this project context."
})
});
if (!response.ok) throw new Error(`Kendr request failed: ${response.status}`);
const result = await response.json();
console.log(result.output_text);
console.log(result.kendr_usage.credits_charged_micros);
Python: coding routing with original context
import os
import uuid
import requests
response = requests.post(
"https://api.kendr.org/v1/responses",
headers={
"Authorization": f"Bearer {os.environ['KENDR_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"model": "kendr-coder-direct",
"input": "Review the implementation and propose a safe patch.",
},
timeout=180,
)
response.raise_for_status()
result = response.json()
print(result["output_text"])
Read the optimization receipt
{
"kendr_usage": {
"input_tokens": 1200,
"output_tokens": 180,
"credits_charged_micros": 180000
},
"kendr_optimization": {
"enabled": true,
"requested_mode": "balanced",
"resolved_mode": "balanced",
"engine": "kendr_optimizer",
"original_input_tokens_estimated": 1800,
"optimized_input_tokens_estimated": 1200,
"estimated_input_tokens_avoided": 600,
"estimated_credits_saved_micros": 40000,
"estimated_credits_without_optimization_micros": 220000,
"quality_guard": {"passed": true, "checks": ["latest_user_request_preserved"], "violations": []},
"shadow": false
}
}
- kendr_usage.credits_charged_micros is the authoritative settled charge. Divide microcredits by 1,000,000 to display Kendr credits.
- estimated_credits_saved_micros is the rate-card-priced counterfactual saving from estimated avoided input tokens. Do not subtract it again; the settled charge already uses the optimized provider request.
- estimated_credits_without_optimization_micros is the comparable estimated charge without that input reduction.
- shadow: true means the deployment is running a preview-only evaluation. The provider received the original request, so no saving was applied.
- A zero saving is valid for short requests, protected content, structured-output/tool contracts, rejected quality checks, or unavailable semantic engines. Check fallback_reason, skipped_strategies, and quality_guard.violations.
Optimized managed routes can return kendr_optimization with the server-selected engine, estimated input reduction, quality checks, and fallback state. Direct routes preserve original context and must not be presented as optimized.
Streaming
Set stream: true on the same alias-based request. The final done event contains settled usage and, for optimized routes, the complete kendr_optimization receipt; token deltas do not contain billing information. Use /api/v1/llm/responses when you need Kendr-native named SSE events. Safe routes relay provider deltas live. Tool combinations that cannot preserve a provider-owned trace safely return one complete JSON response on the Kendr-native endpoint, with X-Kendr-Stream-Mode: buffered and X-Kendr-Buffered-Reason; compatibility endpoints retain their vendor SSE wire format.
Model request fields
Use the same fields across /v1/responses, /v1/chat/completions, /v1/messages, and /api/v1/llm/responses where the compatibility format allows them.
| Field | Required | Use |
|---|---|---|
| model | Yes | Kendr alias such as kendr-intelligent or a Normal text model alias from GET /v1/models. |
| input or messages | Yes | Prompt text or role-based chat messages, depending on the route format. |
| instructions | No | System-level guidance for Responses-compatible requests. |
| max_output_tokens or max_tokens | No | Caps generated tokens for the selected route. |
| stream | No | Set true to receive server-sent events. |
| web_search | No | Tri-state control: omit for automatic selection from the current request, use true to request search, or false to prohibit it. |
| tools | No | Tool declarations executed on the server side. Use {"type": "kendr_app", "selection": "auto"} to let Kendr discover and relevance-filter OAuth apps linked to the signed-in account. Use the separate {"type": "kendr_mcp", "server_id": "mcp_..."} contract to activate one registered, trusted custom MCP server (see Call remote MCP tools). Credentials remain server-side, and pending tool calls are never returned to the client. |
| conversation_id | No | Stable identifier for a conversation. Kendr managed routing stores the selected model per conversation and reuses it on later turns (kendr_routing.source: "sticky"), skipping router latency and cost. Omit it and every request routes from scratch. Not accepted on /v1/messages. |
| request_id | No | Body-level alternative to the Idempotency-Key header; idempotency_key is also accepted. All three are optional — a request ID is generated when none is supplied. |
| response_format | No | Structured-output preference for routes that support it. |
| metadata | No | Application metadata. metadata.require_web_search makes search mandatory; metadata.intelligent_reroute selects a model again instead of reusing a compatible conversation route. |