Not yet available. Automatic free-model routing rules are tracked to be built — today, use the manual router pattern below with the live catalog's ?free=true filter (Models).
Several models in the OpenDunes catalog are available at no cost. You can build a lightweight router that sends requests to a free model by default and falls back to a paid one only when the task genuinely needs it. This is useful for development, testing, and cost-sensitive production pipelines.
Query the catalog with ?free=true to get only models that carry zero DA token cost:
curl "https://opendunes.com/api/models?free=true&sort=popularity"
Each result includes the model's slug, context window, and capabilities. Pick the ones that fit your use case.
The pattern is straightforward: try a free model first, escalate to a capable paid model if the task requires it.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://opendunes.com/api/v1",
api_key=os.environ["OPENDUNES_API_KEY"],
)
FREE_MODEL = "cohere/north-mini-code:free"
PAID_MODEL = "anthropic/claude-sonnet-5"
def complete(messages: list, needs_premium: bool = False) -> str:
model = PAID_MODEL if needs_premium else FREE_MODEL
resp = client.chat.completions.create(
model=model,
messages=messages,
)
return resp.choices[0].message.content
classify_prompt = [
{"role": "system", "content": "Classify the user request as 'simple' or 'complex'. Reply with one word only."},
{"role": "user", "content": "What is the capital of Algeria?"},
]
tier = complete(classify_prompt)
user_messages = [{"role": "user", "content": "What is the capital of Algeria?"}]
answer = complete(user_messages, needs_premium=(tier.strip().lower() == "complex"))
print(answer)
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://opendunes.com/api/v1",
apiKey: process.env.OPENDUNES_API_KEY,
});
const FREE_MODEL = "cohere/north-mini-code:free";
const PAID_MODEL = "anthropic/claude-sonnet-5";
async function complete(messages, model = FREE_MODEL) {
const resp = await client.chat.completions.create({ model, messages });
return resp.choices[0].message.content;
}
const userMessage = "Explain quantum entanglement in one paragraph.";
const tier = await complete([
{ role: "system", content: "Reply with 'simple' or 'complex' only." },
{ role: "user", content: userMessage },
]);
const model = tier.trim().toLowerCase() === "complex" ? PAID_MODEL : FREE_MODEL;
const answer = await complete([{ role: "user", content: userMessage }], model);
console.log(answer);
Free-tier availability can change. Poll the catalog periodically and cache the result rather than hard-coding slugs:
import httpx
import time
_free_models_cache = {"models": [], "fetched_at": 0}
def get_free_models(ttl: int = 3600) -> list[str]:
now = time.time()
if now - _free_models_cache["fetched_at"] < ttl:
return _free_models_cache["models"]
resp = httpx.get("https://opendunes.com/api/models", params={"free": "true", "sort": "popularity"})
resp.raise_for_status()
slugs = [m["slug"] for m in resp.json().get("data", [])]
_free_models_cache.update({"models": slugs, "fetched_at": now})
return slugs
The automatic routing rules feature will let you declare routing policies in your dashboard — for example, "use a free model unless the request exceeds 2,000 tokens" — without writing any routing code. Until then, the manual approach above gives you full control.
- Models catalog — filter by
free=true to see current free models with context sizes.
- Build a Chat App — end-to-end streaming example.
- Migrate to OpenDunes — switch an existing app in two lines.