Multi-provider LLM gateway
One API for every model
you build with
Chat, vision, image, audio, embeddings and realtime — across the big providers and your own local models. One OpenAI-compatible endpoint, a queue that handles the rate limits, and usage tracking per key.
No key yet? Email contact@canarycoders.es.
Reach every backend through the same API
Everything behind one key
Swap a model or a provider without touching your code. Pricing, limits and logging travel with the request.
Chat & reasoning
Completions and streaming across OpenAI, Anthropic, Gemini, xAI and Perplexity — same request shape for all of them.
Vision
Object and zero-shot detection, face detection and blur, plus image understanding through the same gateway.
Image & video
Generate images and video with Imagen, Veo, gpt-image and Grok, billed per image and per second.
Audio
Text-to-speech, transcription, sound effects and music through ElevenLabs and local MLX voices.
Embeddings & RAG
Transient embeddings on EU-local models. You keep the vectors — the gateway never stores your documents.
Realtime & voice agents
Ephemeral-token brokers for OpenAI Realtime and ElevenLabs agents. The client opens WebRTC straight to the source — lowest latency, no audio through us.
OpenAI-compatible
Point an existing OpenAI client at the gateway and change the base URL. /v1/chat/completions and /v1/embeddings work unchanged.
Queue & usage tracking
A concurrency-managed queue absorbs provider rate limits. Every request is metered, priced and billable per API key.
Drop-in, not a rewrite
Keep the OpenAI SDK you already use. Change the base URL and prefix the model with its provider. Streaming, tools and usage accounting come along for free.
- ✓
provider/modelnaming, so one client reaches every backend - ✓ Async jobs for long media work — enqueue, poll, collect
- ✓ Per-key usage and cost in the customer portal
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://api.ai.canarycoders.es/v1",
apiKey: process.env.CANARY_API_KEY,
});
// Same call for any provider — switch the model string.
const res = await client.chat.completions.create({
model: "anthropic/claude-sonnet-4-5",
messages: [{ role: "user", content: "Summarise this in one line." }],
}); Ship your first request
Read the quick start, or email us for an API key and a model that fits your data.