Quickstart
Create an API key in the portal and make your first chat completion with curl, Python, or JavaScript, including streaming.
1. Create an API key
Open AI in the portal
(/dashboard/ai) and click
New API key.
Name the key after the app or environment that will use it (for example
production-backend), optionally set an expiry (1-365 days), and click
Create key.
Copy the full sk-alwd-… key now: it is shown exactly once. We store
only its hash; if you lose it, revoke it and mint a new one.
Store the key in an environment variable, never in code:
export ALAWADI_AI_KEY="sk-alwd-..."2. Make your first request
The API is OpenAI-compatible: keep your existing code and SDK, swap only the base URL and the key.
curl https://ai.alawadi.cloud/v1/chat/completions \
-H "Authorization: Bearer $ALAWADI_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-7b-instruct",
"messages": [
{"role": "user", "content": "مرحبا! عرّف عن نفسك بجملة واحدة."}
]
}'# pip install openai
import os
from openai import OpenAI
client = OpenAI(
base_url="https://ai.alawadi.cloud/v1",
api_key=os.environ["ALAWADI_AI_KEY"],
)
resp = client.chat.completions.create(
model="qwen2.5-7b-instruct",
messages=[
{"role": "user", "content": "مرحبا! عرّف عن نفسك بجملة واحدة."}
],
)
print(resp.choices[0].message.content)// npm install openai
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://ai.alawadi.cloud/v1",
apiKey: process.env.ALAWADI_AI_KEY,
});
const resp = await client.chat.completions.create({
model: "qwen2.5-7b-instruct",
messages: [
{ role: "user", content: "مرحبا! عرّف عن نفسك بجملة واحدة." },
],
});
console.log(resp.choices[0].message.content);Every response carries a usage object with exact server-side token counts,
which is what you are billed on:
"usage": {
"prompt_tokens": 21,
"completion_tokens": 38,
"total_tokens": 59
}3. Stream the response
Set "stream": true to receive tokens as they are generated. Streaming is
the recommended mode for anything user-facing, because non-streaming requests
have a 90-second server-side timeout. The final stream chunk always includes
the usage object (the gateway forces this on), so you still get exact counts.
curl -N https://ai.alawadi.cloud/v1/chat/completions \
-H "Authorization: Bearer $ALAWADI_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-7b-instruct",
"stream": true,
"messages": [
{"role": "user", "content": "مرحبا! عرّف عن نفسك بجملة واحدة."}
]
}'stream = client.chat.completions.create(
model="qwen2.5-7b-instruct",
stream=True,
messages=[
{"role": "user", "content": "مرحبا! عرّف عن نفسك بجملة واحدة."}
],
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)
if chunk.usage: # final chunk, exact token counts
print(f"\n-- {chunk.usage.total_tokens} tokens")const stream = await client.chat.completions.create({
model: "qwen2.5-7b-instruct",
stream: true,
messages: [
{ role: "user", content: "مرحبا! عرّف عن نفسك بجملة واحدة." },
],
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
if (chunk.usage) console.log(`\n-- ${chunk.usage.total_tokens} tokens`);
}Prefer streaming for long generations
Non-streaming requests time out server-side after 90 seconds. For long
prompts or long answers, always set "stream": true.
Call a tool
The model supports OpenAI-style tool (function) calling: pass a tools
array and, when the model decides to use one, the response comes back with
tool_calls for your code to execute. Use it non-streaming ("stream": false) — that is the supported, reliable path.
curl https://ai.alawadi.cloud/v1/chat/completions \
-H "Authorization: Bearer $ALAWADI_AI_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "qwen2.5-7b-instruct",
"stream": false,
"messages": [
{"role": "user", "content": "ما حالة الطقس في دمشق؟"}
],
"tools": [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"]
}
}
}]
}'tools = [{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {"city": {"type": "string"}},
"required": ["city"],
},
},
}]
resp = client.chat.completions.create(
model="qwen2.5-7b-instruct",
stream=False,
messages=[{"role": "user", "content": "ما حالة الطقس في دمشق؟"}],
tools=tools,
)
call = resp.choices[0].message.tool_calls[0]
print(call.function.name) # get_weather
print(call.function.arguments) # {"city": "Damascus"}
# Run the function yourself, then send the result back as a
# {"role": "tool", "tool_call_id": call.id, "content": "..."} message.Use non-streaming for tools
Tool calling is supported and tested in non-streaming mode. Stream normal
chat for user-facing text, but set "stream": false when you pass tools so
you reliably get structured tool_calls back.
Next: models and pricing · billing and usage · limits and errors.