Documentation

Developers: five minutes to your first token

Our gateway is a drop-in replacement for the OpenAI API. Keep your SDK, your prompt templates and your evaluation suite — change two lines and you are running.

Quickstart

Three steps: create a key in your console, set it as an environment variable, call the model.

Create an API key

In your console, open API keys → New key. Give it a name, a rate limit, an IP whitelist and a spending cap.

Export it

Never hard-code a key in source control. Use an environment variable.

.env
# Any OpenAI-compatible SDK works. Two values change.
export IAALGERIE_API_KEY="iaa_live_xxxxxxxxxxxxxxxxxxxx"
export OPENAI_BASE_URL="https://api.iaalgerie.com/v1"

# default model
export DEFAULT_MODEL="qwen3.7-plus"

Call a model

Point the OpenAI SDK at our base URL and pick a model ID from the catalog.

Python
# pip install openai
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://api.iaalgerie.com/v1",
    api_key=os.environ["IAALGERIE_API_KEY"],
)

response = client.chat.completions.create(
    model="qwen3.7-plus",
    messages=[
        {"role": "system", "content": "Reponds toujours en francais."},
        {"role": "user", "content": "Resume ce contrat en 5 points."},
    ],
    temperature=0.3,
)

print(response.choices[0].message.content)
print("tokens:", response.usage.total_tokens)
Node.js
// npm install openai
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.iaalgerie.com/v1",
  apiKey: process.env.IAALGERIE_API_KEY,
});

const response = await client.chat.completions.create({
  model: "qwen3.7-plus",
  messages: [
    { role: "system", content: "Reponds toujours en francais." },
    { role: "user", content: "Resume ce contrat en 5 points." },
  ],
});

console.log(response.choices[0].message.content);
cURL
curl https://api.iaalgerie.com/v1/chat/completions \
  -H "Authorization: Bearer $IAALGERIE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.7-plus",
    "messages": [
      {"role": "system", "content": "Reponds toujours en francais."},
      {"role": "user", "content": "Resume ce contrat en 5 points."}
    ],
    "temperature": 0.3
  }'

Base URL & regions

One URL for every model. Our gateway picks the upstream region based on the model you ask for.

Endpoints
OpenAI-compatible  https://api.iaalgerie.com/v1
Anthropic format   https://api.iaalgerie.com/anthropic
Native DashScope   https://api.iaalgerie.com/api/v1

One URL for every model. Our gateway selects the upstream region
for you (Singapore, US Virginia or Beijing) — nothing to configure
on your side.

Nothing to configure on the region side: that is our job. If you need a specific region for compliance reasons, tell us.

Authentication

Send your key in the Authorization header, exactly like OpenAI.

HTTP
Authorization: Bearer iaa_live_xxxxxxxxxxxxxxxxxxxx
Content-Type: application/json

Rotate keys from your console at any time. The old key stops working immediately.

Chat completions

The standard OpenAI chat payload works untouched.

cURL
curl https://api.iaalgerie.com/v1/chat/completions \
  -H "Authorization: Bearer $IAALGERIE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen3.7-plus",
    "messages": [
      {"role": "system", "content": "Reponds toujours en francais."},
      {"role": "user", "content": "Resume ce contrat en 5 points."}
    ],
    "temperature": 0.3
  }'

Use qwen3.8-flash for drafts and classification, qwen3.7-plus for user-facing answers, qwen3.8-max only when the task genuinely needs it.

Streaming

Set stream to true and consume server-sent events: the user sees the first word in a few hundred milliseconds.

Python
stream = client.chat.completions.create(
    model="qwen3.7-plus",
    messages=[{"role": "user", "content": "Ecris un devis pour 3 sites web."}],
    stream=True,
)

for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

Function calling

Declare your tools the usual way and let the model decide when to call them.

Python
tools = [{
    "type": "function",
    "function": {
        "name": "get_order_status",
        "description": "Retourne le statut d'une commande algerienne.",
        "parameters": {
            "type": "object",
            "properties": {
                "order_id": {"type": "string"},
                "wilaya": {"type": "string"}
            },
            "required": ["order_id"]
        }
    }
}]

messages = [{"role": "user", "content": "Ou est ma commande CMD-4821 ?"}]

while True:
    reply = client.chat.completions.create(
        model="qwen3.7-plus", messages=messages, tools=tools
    ).choices[0].message

    if not reply.tool_calls:
        print(reply.content)
        break

    messages.append(reply)
    for call in reply.tool_calls:
        args = json.loads(call.function.arguments)
        messages.append({
            "role": "tool",
            "tool_call_id": call.id,
            "content": json.dumps({"status": "en livraison", "wilaya": "Bejaia"}),
        })

Structured output

Ask for JSON and validate it against a schema. Ideal for extracting fields from invoices or forms.

Python
from pydantic import BaseModel

class Invoice(BaseModel):
    supplier: str
    nif: str | None
    total_da: float
    currency: str
    due_date: str | None

raw = "FACTURE SARL Exemple, NIF 0998...1620, total 145 000,00 DA, echeance 30/11/2026"

parsed = client.beta.chat.completions.parse(
    model="qwen3.8-flash",
    messages=[
        {"role": "system", "content": "Extract the invoice fields."},
        {"role": "user", "content": raw},
    ],
    response_format=Invoice,
)

invoice = parsed.choices[0].message.parsed
print(invoice.total_da, invoice.currency)   # 145000.0 DA

Image, video & speech

Media models are asynchronous: you submit a task, then poll it. Billing happens once the task completes successfully.

cURL
# Images — synchronous, billed per image
curl -X POST https://api.iaalgerie.com/v1/images/generations \
  -H "Authorization: Bearer $IAALGERIE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "qwen-image-3.0-pro",
       "prompt": "Photo produit d une bouteille d huile d olive",
       "size": "1024x1024", "n": 2}'

# Video — asynchronous: submit, then poll the task
curl -X POST https://api.iaalgerie.com/v1/services/aigc/video-generation/video-synthesis \
  -H "Authorization: Bearer $IAALGERIE_API_KEY" \
  -H "X-DashScope-Async: enable" \
  -H "Content-Type: application/json" \
  -d '{"model": "wan3.0-video",
       "input": {"prompt": "Tramway d Alger au coucher du soleil"},
       "parameters": {"duration": 5, "size": "1280*720"}}'

# -> {"output": {"task_id": "..."}}  then:
curl https://api.iaalgerie.com/v1/tasks/<task_id> \
  -H "Authorization: Bearer $IAALGERIE_API_KEY"

# Speech to text
curl -X POST https://api.iaalgerie.com/v1/audio/transcriptions \
  -H "Authorization: Bearer $IAALGERIE_API_KEY" \
  -F model="qwen-audio-3.1-asr-flash-filetrans" \
  -F file="@reunion.m4a"

Media prices are per image, per second of video or per minute of audio — see the pricing page.

Embeddings & rerank

Build a retrieval pipeline for Arabic, French and English documents.

Python
# Embeddings: turn your knowledge base into vectors
emb = client.embeddings.create(
    model="text-embedding-v4",
    input=["Politique de retour sous 7 jours", "Frais de livraison Yalidine"],
)
vectors = [d.embedding for d in emb.data]

# Rerank: best candidates first, before the chat call
import dashscope   # pip install dashscope

ranked = dashscope.TextReRank.call(
    model="qwen3-rerank",
    query="Quel est le delai de retour ?",
    documents=["Politique de retour sous 7 jours",
               "Nos horaires d ouverture",
               "Frais de livraison Yalidine"],
    top_n=2,
    return_documents=True,
    api_key=os.environ["IAALGERIE_API_KEY"],
)
print(ranked.output.results[0].document.text)

Errors & rate limits

StatusMeaningWhat to do
400Malformed requestCheck the model ID against the catalog.
401Invalid or revoked keyRegenerate the key in your console.
402Insufficient balanceTop up, or lower the key cap.
429Rate limit reachedRetry with exponential backoff.
500Upstream errorRetry once, then contact support with the request ID.
503Model temporarily unavailableFail over to a sibling model in the same family.

Every response carries your remaining quota and the request ID. Log the request ID — support cannot investigate without it.

Python
import time
from openai import APIStatusError

def ask(messages, model="qwen3.7-plus"):
    for attempt in range(5):
        try:
            r = client.chat.completions.create(model=model, messages=messages)
            print("request_id:", r._request_id, "tokens:", r.usage.total_tokens)
            return r
        except APIStatusError as e:
            if e.status_code == 429:      # rate limit
                time.sleep(2 ** attempt)
                continue
            if e.status_code == 402:      # insufficient balance
                raise SystemExit("Top up your IA Algerie balance.")
            if e.status_code >= 500:      # upstream hiccup
                time.sleep(1)
                continue
            raise
    raise RuntimeError("rate limited after 5 attempts")

Cost best practices

Five habits that reliably cut an AI bill by half or more.

Right-size the model

Route simple intents to Flash. Reserve Max-class models for tasks where a wrong answer costs more than the tokens.

Cap every key

A monthly cap per key turns a runaway loop into a harmless error.

Trim your prompts

Output tokens usually cost four times input tokens.

Cache the stable part

Context caching bills repeated prefixes at a reduced rate.

Use batch where latency allows

Nightly classification, summarising or embedding jobs do not need real-time responses.

Developer FAQ

Can I use the official OpenAI library?

Yes. Set base_url to our endpoint and api_key to your IA Algérie key. Nothing else changes.

Do you support the Anthropic format?

Yes, on a separate path. Useful for Claude Code-style tools.

Which model IDs should I pin in production?

Pin an exact version ID rather than a moving alias so an upstream update never changes your output silently.

Is there a free sandbox?

Every new account receives a small trial balance so you can validate the integration before paying.

How do I report a bad response?

Send the request ID plus the model ID to support. We can replay the call and escalate.

Get a key and test it tonight

Early accounts get the trial balance, the onboarding call and a direct Telegram line.

Launch phase — spots left for the 100-user beta