The Vercel AI SDK ships a first-class OpenAI provider that accepts a custom baseURL. Swap it for OpenDunes and you gain access to the full model catalog while billing stays in Algerian Dinars.
npm install ai @ai-sdk/openai
Create the provider once and reuse it across your app.
import { createOpenAI } from "@ai-sdk/openai";
export const opendunes = createOpenAI({
baseURL: "https://opendunes.com/api/v1",
apiKey: process.env.OPENDUNES_API_KEY,
});
import { generateText } from "ai";
import { opendunes } from "@/lib/opendunes";
const { text } = await generateText({
model: opendunes("anthropic/claude-sonnet-5"),
prompt: "Explain micro-DA in one sentence.",
});
console.log(text);
import { streamText } from "ai";
import { opendunes } from "@/lib/opendunes";
export async function POST(req: Request) {
const { messages } = await req.json();
const result = streamText({
model: opendunes("google/gemini-2.5-pro"),
messages,
});
return result.toDataStreamResponse();
}
Pair the route handler above with the useChat hook on the client:
"use client";
import { useChat } from "ai/react";
export function Chat() {
const { messages, input, handleInputChange, handleSubmit } = useChat({
api: "/api/chat",
});
return (
<div>
{messages.map((m) => (
<p key={m.id}>
<strong>{m.role}:</strong> {m.content}
</p>
))}
<form onSubmit={handleSubmit}>
<input value={input} onChange={handleInputChange} />
<button type="submit">Send</button>
</form>
</div>
);
}
Because opendunes("...") takes a slug string, you can switch models at runtime:
const model = opendunes(
userTier === "pro" ? "anthropic/claude-opus-4.8" : "meta-llama/llama-4-maverick"
);
Browse the full catalog at /models or fetch it programmatically from GET /api/models.
Add to .env.local:
OPENDUNES_API_KEY=sk-your-key-here
Note. OPENDUNES_API_KEY is a server-side variable. Do not prefix it with NEXT_PUBLIC_ — it must never be exposed to the browser.