Introduction
CanalAPI is a unified gateway over 600+ LLM, image, and audio models. Use any OpenAI-compatible client — point base_url at https://api.canalapi.com/v1, pass your key, and ship.
Quickstart
You need two things: an API key (from the console) and a model slug. Here's the simplest possible request:
# Any OpenAI-compatible client works — just swap the base URL
curl https://api.canalapi.com/v1/chat/completions \
-H "Authorization: Bearer $CANAL_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "claude-4-sonnet",
"messages": [{"role":"user","content":"Hello"}]
}'Response
{
"id": "chatcmpl_8K2m3",
"object": "chat.completion",
"created": 1745078400,
"model": "claude-4-sonnet",
"choices": [{
"index": 0,
"message": { "role": "assistant", "content": "Hi there!" },
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 8, "completion_tokens": 3, "total_tokens": 11 }
}Authentication
Authenticated endpoints accept either Authorization: Bearer <key> (OpenAI-style) or x-api-key: <key> (Anthropic SDK style); Authorization wins when both are present. Keys are prefixed with ca_sk_live_ — create separate keys per environment (dev / staging / prod) from the console.
Chat completionsPOST/v1/chat/completions
Create a chat completion. Compatible with OpenAI's chat/completions — same parameters, same response shape, with automatic upstream-channel selection.
Request body
| Field | Type | Description |
|---|---|---|
| modelrequired | string | Model slug. Call /v1/models for the live list, or browse the pricing page. |
| messagesrequired | array | Conversation as an array of { role, content } objects. Roles: system, user, assistant. |
| streamoptional | boolean | If true, tokens are streamed via SSE. Default false. |
| temperatureoptional | number | 0–2. Higher = more random. Default is model-dependent. |
| max_tokensoptional | integer | Cap on completion tokens. Model-dependent default. |
| toolsoptional | array | Function-calling tool definitions. Request schema follows OpenAI / Anthropic native shapes. |
Streaming example
stream = client.chat.completions.create(
model="claude-4-sonnet",
messages=[{"role": "user", "content": "Write a haiku."}],
stream=True,
)
for chunk in stream:
print(chunk.choices[0].delta.content or "", end="")Endpoints at a glance
All endpoints share the same key and auth scheme. The table below lists the OpenAI-compatible and vendor-native endpoints currently live:
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/embeddings | Text embeddings (OpenAI Embeddings compatible) |
| POST | /v1/images/generations | Image generation (DALL·E compatible; /edits and /variations also live) |
| POST | /v1/audio/transcriptions | Speech-to-text (Whisper compatible; /audio/translations also live) |
| POST | /v1/audio/speech | Text-to-speech (TTS) |
| POST | /v1/moderations | Content moderation (typically free) |
| POST | /v1/responses | OpenAI Responses API compatible endpoint |
| POST | /v1/messages | Anthropic Messages API — native endpoint for the Claude SDK; the count_tokens sub-route is free |
| GET | /v1/models | List available models (public, no auth required) |
| GET | /v1/dashboard/billing/credit_grants | OpenAI-compatible account balance summary |
Request parameters and vendor-specific fields follow the upstream API spec; CanalAPI forwards all standard fields.
Errors & retries
CanalAPI uses conventional HTTP status codes; errors follow the OpenAI shape { error: { message, type, code } }. On 5xx upstream failures we auto-retry across healthy channels — you only see an error after the routing pool is exhausted.
| Code | Meaning | What to do |
|---|---|---|
| 400 | bad_request | Check request body — likely a bad model or malformed messages. |
| 401 | unauthenticated | Missing, invalid, or revoked key. Create a new one in the console. |
| 402 | insufficient_balance | Insufficient balance — top up and retry. |
| 429 | rate_limited | Rate limit exceeded. Back off using the Retry-After and X-RateLimit-* headers. |
| 502/503 | upstream_error | All upstreams unavailable and already retried. Open a support ticket if it persists. |
SDK integration
CanalAPI ships no proprietary SDK — it's a drop-in replacement for the major vendor SDKs. Swap the base URL and your existing code keeps working.
pip install openai • npm i openaipip install anthropic • npm i @anthropic-ai/sdk