# API reference
Base URL: `https://api.keln.ai/v1` · Auth: `Authorization: Bearer sk-keln-…`
Keln is OpenAI-wire-compatible, an OpenAI SDK works by changing the base URL. Behind the
endpoint, Keln normalizes across providers, so whichever one serves your request, your parameters
behave the same way and the response has the same shape.
## Endpoints
| Endpoint | What it does |
|---|---|
| [`POST /v1/chat/completions`](chat-completions.md) | Chat completions, streaming and non-streaming, tools, structured output, reasoning control. Needs an API key. |
| [`POST /v1/responses`](responses.md) | The OpenAI Responses schema, for agents and [Codex](../codex.md). Same key, models, and prices as chat completions. |
| [`POST https://anthropic.keln.ai/v1/messages`](anthropic.md) | The Anthropic Messages schema, for Claude Code and Anthropic SDKs. Same key, models, and prices. |
| [`GET /v1/models`](models.md) | The servable catalog: context windows, live pricing, input modalities (text / image), and current routing performance figures. No key needed, CORS-open. |
| `GET /healthz` | Liveness check, for uptime monitoring. No key needed. |
There is no legacy `/v1/completions` text endpoint.
Model ids are lowercase (`deepseek-ai/deepseek-v4-flash`) and matched case-insensitively.
## Authentication
Every `POST /v1/chat/completions` requires an API key, created in the
[portal](https://app.keln.ai) (**Keys** page):
```
Authorization: Bearer sk-keln-…
```
Keln shows each key once and stores only a hash, and you can revoke a key at any time. A key
belongs to a workspace. Usage bills to that workspace's balance, and you can cap it with
[per-key budgets](../platform/authentication.md).
[`GET /v1/models`](models.md) requires no key and is served CORS-open
(`Access-Control-Allow-Origin: *`).
## SDKs
Any OpenAI-compatible client works:
=== "Python"
```python
from openai import OpenAI
client = OpenAI(base_url="https://api.keln.ai/v1", api_key="sk-keln-…")
```
=== "TypeScript"
```typescript
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://api.keln.ai/v1", apiKey: "sk-keln-…" });
```
Migrating from OpenAI or OpenRouter: [Migration guide ↗](../migrate.md)
## Reading order
- [Chat completions](chat-completions.md), the full parameter contract
- [Responses API](responses.md), the OpenAI Responses schema, and [Codex](../codex.md) setup
- [Anthropic-compatible](anthropic.md), the Anthropic Messages schema, Claude Code setup, and [Claude Desktop](../claude-desktop.md)
- [Streaming](streaming.md), SSE semantics, usage in the final chunk
- [Models](models.md), catalog, context windows, pricing block
- [Errors & limits](errors.md), the envelope, status codes, retry guidance
API reference
Base URL: https://api.keln.ai/v1 · Auth: Authorization: Bearer sk-keln-…
Keln is OpenAI-wire-compatible, an OpenAI SDK works by changing the base URL. Behind the
endpoint, Keln normalizes across providers, so whichever one serves your request, your parameters
behave the same way and the response has the same shape.
The servable catalog: context windows, live pricing, input modalities (text / image), and current routing performance figures. No key needed, CORS-open.
GET /healthz
Liveness check, for uptime monitoring. No key needed.
There is no legacy /v1/completions text endpoint.
Model ids are lowercase (deepseek-ai/deepseek-v4-flash) and matched case-insensitively.
Authentication
Every POST /v1/chat/completions requires an API key, created in the
portal (Keys page):
Authorization: Bearer sk-keln-…
Keln shows each key once and stores only a hash, and you can revoke a key at any time. A key
belongs to a workspace. Usage bills to that workspace's balance, and you can cap it with
per-key budgets.
GET /v1/models requires no key and is served CORS-open
(Access-Control-Allow-Origin: *).