The OpenDunes API is OpenAI-compatible, so your existing OpenAI SDK work unchanged — just swap the base URL and key. Below is everything you need to go from zero to a working streaming chat in under five minutes.
A small script that sends a user message to a model, streams the response token-by-token, and prints it to the terminal. You can extend this into a web app by piping the same SSE stream to a browser client.
- An OpenDunes account at opendunes.com.
- A positive DA balance (deposit via your dashboard).
- An API key from your dashboard — stored as
OPENDUNES_API_KEY in your environment.
If this is your first time, the default key is already waiting in Dashboard → Keys. Copy it and export it:
export OPENDUNES_API_KEY="sk-0a1b2c3d..."
curl https://opendunes.com/api/v1/chat/completions \
-H "Authorization: Bearer $OPENDUNES_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "anthropic/claude-sonnet-5",
"messages": [{ "role": "user", "content": "Marhba! Say hello in one line." }]
}'
Set stream: true and iterate over the delta chunks. Each chunk carries a partial content string; the stream ends with a [DONE] sentinel.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://opendunes.com/api/v1",
api_key=os.environ["OPENDUNES_API_KEY"],
)
stream = client.chat.completions.create(
model="anthropic/claude-sonnet-5",
messages=[{"role": "user", "content": "Write a one-paragraph story set in the Sahara."}],
stream=True,
)
for chunk in stream:
delta = chunk.choices[0].delta.content or ""
print(delta, end="", flush=True)
print()
Pass the full conversation history in messages on each request. The model has no memory between calls — you own the history array.
import OpenAI from "openai";
import * as readline from "readline";
const client = new OpenAI({
baseURL: "https://opendunes.com/api/v1",
apiKey: process.env.OPENDUNES_API_KEY,
});
const history = [
{ role: "system", content: "You are a helpful assistant that answers in Algerian Darja when possible." },
];
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
function ask() {
rl.question("You: ", async (input) => {
if (!input.trim()) return ask();
history.push({ role: "user", content: input });
const stream = await client.chat.completions.create({
model: "google/gemini-2.5-pro",
messages: history,
stream: true,
});
process.stdout.write("Assistant: ");
let reply = "";
for await (const chunk of stream) {
const piece = chunk.choices[0]?.delta?.content ?? "";
reply += piece;
process.stdout.write(piece);
}
console.log();
history.push({ role: "assistant", content: reply });
ask();
});
}
ask();
After each request, the response header X-Balance-Available contains your remaining balance in micro-DA (1 DA = 1,000,000 micro-DA). You can also read your live balance from Dashboard → Billing.
- Streaming in depth — SSE event format, error chunks, usage in the final chunk.
- Models catalog — Browse all available models with DA pricing.
- Migrate an existing OpenAI app — One-line switch from OpenAI to OpenDunes.