مستندات درواره
درواره کاملا سازگار با API استاندارد OpenAI است. فقط کافیست base_url را تغییر دهید.
شروع سریع
در سه مرحله ساده با درواره شروع کنید. نیازی به SDK خاصی نیست — از OpenAI SDK استفاده کنید.
نصب SDK
SDK موردنظرتان را نصب کنید
تنظیم Base URL
آدرس API درواره را وارد کنید
ارسال درخواست
مثل OpenAI درخواست بزنید
نصب
pip install openaiاولین درخواست
from openai import OpenAI
client = OpenAI(
base_url="https://api.darvareh.ir/v1",
api_key="sk-darvareh-YOUR_KEY"
)
response = client.chat.completions.create(
model="openai/gpt-4o",
messages=[
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "سلام! خودت رو معرفی کن."}
]
)
print(response.choices[0].message.content)احراز هویت
دو نوع احراز هویت
API Key (برای مدلها)
برای endpointهای /v1/* از کلید API استفاده کنید. فرمت: sk-darvareh-...
JWT Token (برای مدیریت)
برای endpointهای /api/v1/* (مدیریت کلیدها، اعتبار و...) از JWT استفاده کنید.
نحوه استفاده از API Key
Authorization: Bearer sk-darvareh-YOUR_KEYکلید API فقط یکبار هنگام ساخت نمایش داده میشود. آن را در جای امنی ذخیره کنید.
Chat Completions
/v1/chat/completionsارسال درخواست چت و دریافت پاسخپارامترهای درخواست
| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| model | string | الزامی | شناسه مدل (مثلا openai/gpt-4o) |
| messages | array | الزامی | آرایهای از پیامها با role و content |
| temperature | float | اختیاری | دمای نمونهبرداری (0 تا 2) |
| top_p | float | اختیاری | نمونهبرداری nucleus (0 تا 1) |
| max_tokens | integer | اختیاری | حداکثر توکنهای پاسخ |
| stream | boolean | اختیاری | فعالسازی streaming (پیشفرض: false) |
| n | integer | اختیاری | تعداد پاسخهای تولیدشده |
| stop | string | array | اختیاری | رشتههای توقف تولید |
| presence_penalty | float | اختیاری | جریمه حضور (-2 تا 2) |
| frequency_penalty | float | اختیاری | جریمه تکرار (-2 تا 2) |
| tools | array | اختیاری | تعریف ابزارها (Function Calling) |
| tool_choice | string | object | اختیاری | نحوه انتخاب ابزار |
| response_format | object | اختیاری | فرمت پاسخ (مثلا JSON mode) |
| seed | integer | اختیاری | بذر تصادفی برای تکرارپذیری |
نمونه درخواست و پاسخ
response = client.chat.completions.create(
model="anthropic/claude-sonnet-4",
messages=[
{"role": "system", "content": "You are a senior Python developer."},
{"role": "user", "content": "یک تابع فیبوناچی بهینه بنویس."}
],
temperature=0.7,
max_tokens=1024
)
print(response.choices[0].message.content)
print(f"Tokens used: {response.usage.total_tokens}")پاسخ
{
"id": "chatcmpl-abc123...",
"object": "chat.completion",
"created": 1709123456,
"model": "anthropic/claude-sonnet-4",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 156,
"total_tokens": 198
}
}ورودی چندوجهی (Multimodal)
برای مدلهایی که از تصویر، صوت یا ویدیو پشتیبانی میکنند، محتوا را به صورت آرایه ارسال کنید.
# Vision — ارسال تصویر
response = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "این تصویر چیست؟"},
{"type": "image_url", "image_url": {"url": "https://example.com/image.jpg"}}
]
}]
)
# Function Calling — فراخوانی ابزار
response = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "هوای تهران چطوره؟"}],
tools=[{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {"type": "string"}
},
"required": ["city"]
}
}
}]
)Streaming
با فعال کردن stream: true پاسخ به صورت لحظهای (SSE) دریافت میشود.
stream = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "یک داستان کوتاه بنویس."}],
stream=True
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
# Async streaming
import asyncio
from openai import AsyncOpenAI
async_client = AsyncOpenAI(
base_url="https://api.darvareh.ir/v1",
api_key="sk-darvareh-YOUR_KEY"
)
async def stream_response():
stream = await async_client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "یک شعر بنویس."}],
stream=True
)
async for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="", flush=True)
asyncio.run(stream_response())فرمت Chunk
data: {"id":"chatcmpl-abc...","object":"chat.completion.chunk","created":1709123456,"model":"openai/gpt-4o","choices":[{"index":0,"delta":{"content":"سلام"},"finish_reason":null}]}
data: {"id":"chatcmpl-abc...","object":"chat.completion.chunk","created":1709123456,"model":"openai/gpt-4o","choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":{"prompt_tokens":10,"completion_tokens":50,"total_tokens":60}}
data: [DONE]Text CompletionsLegacy
/v1/completionsتکمیل متن (API قدیمی)| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| model | string | الزامی | شناسه مدل |
| prompt | string | array | الزامی | متن ورودی برای تکمیل |
| max_tokens | integer | اختیاری | حداکثر توکن (پیشفرض: 16) |
| temperature | float | اختیاری | دمای نمونهبرداری |
| stream | boolean | اختیاری | فعالسازی streaming |
| stop | string | array | اختیاری | رشتههای توقف |
| suffix | string | اختیاری | پسوند (برای infill) |
response = client.completions.create(
model="openai/gpt-3.5-turbo-instruct",
prompt="def fibonacci(n):",
max_tokens=200,
temperature=0
)
print(response.choices[0].text)Embeddings
/v1/embeddingsتولید بردارهای embedding از متن| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| model | string | الزامی | مدل embedding (مثلا openai/text-embedding-3-small) |
| input | string | array | الزامی | متن یا آرایهای از متنها |
| encoding_format | string | اختیاری | فرمت خروجی: float یا base64 (پیشفرض: float) |
| dimensions | integer | اختیاری | تعداد ابعاد خروجی |
response = client.embeddings.create(
model="openai/text-embedding-3-small",
input="سلام دنیا"
)
embedding = response.data[0].embedding
print(f"Dimensions: {len(embedding)}")
print(f"First 5: {embedding[:5]}")
# Batch embeddings
response = client.embeddings.create(
model="openai/text-embedding-3-small",
input=["متن اول", "متن دوم", "متن سوم"]
)
for item in response.data:
print(f"[{item.index}] {len(item.embedding)} dims")پاسخ
{
"object": "list",
"data": [
{
"object": "embedding",
"embedding": [0.0023, -0.0094, 0.0156, ...],
"index": 0
}
],
"model": "openai/text-embedding-3-small",
"usage": {
"prompt_tokens": 4,
"total_tokens": 4
}
}Image Generation
تولید و ویرایش تصویر با مدلهایی مثل google/gemini-3-pro-image («Nano Banana Pro»)، google/gemini-2.5-flash-image و black-forest-labs/flux.2-pro. پاسخ بهصورت data[0].b64_json برمیگردد. هر دو مسیر /v1/images و /v1/images/generations کار میکنند.
/v1/images/generationsتولید تصویر از متن یا ویرایش تصویر (Image-to-Image)| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| model | string | الزامی | شناسه مدل تصویری (مثلا google/gemini-3-pro-image) |
| prompt | string | الزامی | توصیف تصویر موردنظر |
| input_references | array | اختیاری | تصویر(های) مرجع برای ویرایش/Image-to-Image |
| size | string | اختیاری | اندازه تصویر (مثلا 1024x1024) |
| n | integer | اختیاری | تعداد تصاویر (پیشفرض: 1) |
import base64, requests
r = requests.post("https://api.darvareh.ir/v1/images/generations",
headers={"Authorization": "Bearer sk-darvareh-YOUR_KEY"},
json={
"model": "google/gemini-3-pro-image",
"prompt": "A futuristic city at sunset, cyberpunk style",
"size": "1024x1024",
}).json()
# پاسخ بهصورت base64 برمیگردد
open("output.png", "wb").write(base64.b64decode(r["data"][0]["b64_json"]))ویرایش تصویر (Image-to-Image)
برای ویرایش یا الگوگرفتن از یک تصویر، آن را در فیلد input_references بفرستید. آدرس تصویر میتواند URL عمومی یا data URL با base64 باشد.
⚠️ از متد images/edits یا GenerateImageEditAsync در SDK اوپنایآی استفاده نکنید — API تصویر OpenAI-compatible نیست و فقط input_references پشتیبانی میشود.
import base64, requests
# تصویر ورودی را به data URL تبدیل کنید
with open("input.png", "rb") as f:
b64 = base64.b64encode(f.read()).decode()
r = requests.post("https://api.darvareh.ir/v1/images/generations",
headers={"Authorization": "Bearer sk-darvareh-YOUR_KEY"},
json={
"model": "google/gemini-3-pro-image",
"prompt": "این تصویر را با نورپردازی حرفهای بازسازی کن",
"input_references": [
{"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}}
],
"size": "1024x1024",
}).json()
open("output.png", "wb").write(base64.b64decode(r["data"][0]["b64_json"]))Video Generation
تولید ویدیو ناهمگام (async) است: ابتدا درخواست را به /v1/videos میفرستید و یک شناسهی کار میگیرید، سپس وضعیت را poll میکنید تا completed شود، و در پایان ویدیو را از /v1/videos/{id}/content دانلود میکنید. هزینه بر اساس مصرف واقعی (مدت ویدیو) محاسبه و در پایان از اعتبار شما کسر میشود.
/v1/videosثبت درخواست تولید ویدیو (ناهمگام)| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| model | string | الزامی | شناسه مدل ویدیو (مثلا bytedance/seedance-2.0-fast) |
| prompt | string | الزامی | توصیف ویدیو |
| duration | integer | اختیاری | مدت ویدیو به ثانیه (برخی مدلها حداقل ۴ ثانیه) |
import time, requests
BASE = "https://api.darvareh.ir/v1"
HEAD = {"Authorization": "Bearer sk-darvareh-YOUR_KEY"}
# ۱) ثبت درخواست → دریافت شناسهی کار
job = requests.post(f"{BASE}/videos", headers=HEAD, json={
"model": "bytedance/seedance-2.0-fast",
"prompt": "a cat playing with a ball in a garden",
"duration": 5,
}).json()
job_id = job["id"]
# ۲) poll تا آماده شدن (حدود ۱ تا ۳ دقیقه)
while True:
s = requests.get(f"{BASE}/videos/{job_id}", headers=HEAD).json()
if s["status"] == "completed":
break
if s["status"] == "failed":
raise RuntimeError(s.get("error"))
time.sleep(5)
# ۳) دانلود ویدیو
mp4 = requests.get(f"{BASE}/videos/{job_id}/content", headers=HEAD).content
open("output.mp4", "wb").write(mp4)
print("هزینه:", s.get("cost_toman"), "تومان")مدلهای ویدیو پشتیبانیشده (نمونه)
| مدل | ارائهدهنده |
|---|---|
| bytedance/seedance-2.0-fast | ByteDance |
| google/veo-3.1-fast | |
| kwaivgi/kling-v3.0-pro | Kling |
| openai/sora-2-pro | OpenAI |
لیست کامل و بهروزِ مدلهای ویدیو در صفحهی «مدلها» با فیلتر ویدیو موجود است.
ویرایش/تبدیل تصویر به ویدیو (Image-to-Video)
برای دادن تصویر ورودی، فیلد frame_images را به همان درخواست /v1/videos اضافه کنید. تصویر باید یک URL عمومی و مستقیم باشد. frame_type میتواند first_frame (فریم اول) یا last_frame (فریم آخر) باشد. مدلهایی با مودالیتی text+image→video (مثل seedance) پشتیبانی میکنند. نکته: برای seedance بهتر است generate_audio: false بگذارید.
# بقیهی مراحل (poll و دانلود) مثل نمونهی بالا است؛ فقط بدنهی درخواست فرق دارد
job = requests.post(f"{BASE}/videos", headers=HEAD, json={
"model": "bytedance/seedance-2.0-fast",
"prompt": "the subject gently turns toward warm window light, cinematic",
"duration": 4,
"generate_audio": False,
"frame_images": [
{
"type": "image_url",
"image_url": {"url": "https://example.com/photo.jpg"},
"frame_type": "first_frame"
}
],
}).json()
print(job["id"])Audio Transcription
/v1/audio/transcriptionsتبدیل صوت به متن| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| file | file | الزامی | فایل صوتی (wav, mp3, webm, ogg, flac, aac, m4a) |
| model | string | اختیاری | مدل (پیشفرض: google/gemini-3.5-flash) |
| prompt | string | اختیاری | راهنمای رونوشت |
| language | string | اختیاری | زبان صوت (مثلا fa, en) |
| temperature | float | اختیاری | دمای نمونهبرداری |
حداکثر حجم فایل: ۲۵ مگابایت. فرمتهای پشتیبانیشده: wav, mp3, webm, ogg, flac, aac, m4a
audio_file = open("recording.mp3", "rb")
transcript = client.audio.transcriptions.create(
file=audio_file,
model="google/gemini-3.5-flash",
language="fa"
)
print(transcript.text)Moderations
/v1/moderationsبررسی محتوا از نظر مطابقت با سیاستها| پارامتر | نوع | الزامی | توضیحات |
|---|---|---|---|
| input | string | array | الزامی | متن یا آرایهای از متنها برای بررسی |
| model | string | اختیاری | مدل (پیشفرض: omni-moderation-latest) |
response = client.moderations.create(
input="متن مورد نظر برای بررسی"
)
result = response.results[0]
print(f"Flagged: {result.flagged}")
print(f"Categories: {result.categories}")Models
/v1/modelsلیست تمام مدلهای در دسترسلیست مدلها بر اساس کلید API فیلتر میشود. اگر کلید شما محدود به مدلهای خاصی باشد، فقط همانها نمایش داده میشوند.
models = client.models.list()
for model in models.data:
print(f"{model.id} — {model.owned_by}")پاسخ
{
"object": "list",
"data": [
{
"id": "openai/gpt-4o",
"object": "model",
"owned_by": "openai",
"name": "GPT-4o",
"context_length": 128000,
"capabilities": {
"input_modalities": ["text", "image"],
"output_modalities": ["text"]
},
"pricing": {
"prompt": "0.0000025",
"completion": "0.00001"
},
"max_completion_tokens": 16384
}
]
}سازگاری با فریمورکها
درواره با تمام فریمورکها و کتابخانههایی که از API استاندارد OpenAI پشتیبانی میکنند سازگار است. فقط کافیست base_url را تغییر دهید.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(
model="openai/gpt-4o",
base_url="https://api.darvareh.ir/v1",
api_key="sk-darvareh-YOUR_KEY",
temperature=0.7
)
response = llm.invoke("سلام! خودت رو معرفی کن.")
print(response.content)
# With streaming
for chunk in llm.stream("یک داستان کوتاه بنویس."):
print(chunk.content, end="")
# Embeddings
from langchain_openai import OpenAIEmbeddings
embeddings = OpenAIEmbeddings(
model="openai/text-embedding-3-small",
base_url="https://api.darvareh.ir/v1",
api_key="sk-darvareh-YOUR_KEY"
)
result = embeddings.embed_query("سلام دنیا")
print(f"Dimensions: {len(result)}")محدودیت نرخ
محدودیت نرخ بر اساس هر کلید API اعمال میشود. میتوانید هنگام ساخت کلید، محدودیتهای RPM و TPM را تنظیم کنید.
| محدودیت | توضیحات | قابل تنظیم |
|---|---|---|
| RPM | تعداد درخواست در دقیقه | بله — هنگام ساخت کلید API |
| TPM | تعداد توکن در دقیقه | بله — هنگام ساخت کلید API |
در صورت رسیدن به محدودیت، خطای 429 دریافت خواهید کرد. صبر کنید و دوباره تلاش کنید یا محدودیت کلید را افزایش دهید.
خطاها
تمام خطاها در فرمت استاندارد OpenAI برگردانده میشوند:
{
"error": {
"message": "توضیح خطا",
"type": "invalid_request_error",
"code": "invalid_api_key"
}
}کدهای وضعیت HTTP
| کد | نوع | توضیحات |
|---|---|---|
| 400 | invalid_request_error | درخواست نامعتبر — پارامترهای ارسالی اشتباه است |
| 401 | authentication_error | احراز هویت ناموفق — کلید API نامعتبر یا منقضی شده |
| 402 | insufficient_funds | اعتبار ناکافی — حساب خود را شارژ کنید |
| 403 | permission_error | مدل برای این کلید مجاز نیست |
| 413 | file_too_large | حجم فایل بیش از حد مجاز |
| 429 | rate_limit_error | محدودیت نرخ — تعداد درخواستها بیش از حد مجاز |
| 500 | server_error | خطای داخلی سرور |
مدیریت خطا در کد
from openai import OpenAI, APIError, AuthenticationError, RateLimitError
client = OpenAI(
base_url="https://api.darvareh.ir/v1",
api_key="sk-darvareh-YOUR_KEY"
)
try:
response = client.chat.completions.create(
model="openai/gpt-4o",
messages=[{"role": "user", "content": "سلام!"}]
)
except AuthenticationError:
print("کلید API نامعتبر است")
except RateLimitError:
print("محدودیت نرخ — کمی صبر کنید")
except APIError as e:
if e.status_code == 402:
print("اعتبار ناکافی — حساب را شارژ کنید")
elif e.status_code == 403:
print("این مدل برای کلید شما مجاز نیست")
else:
print(f"خطا: {e.message}")API مدیریت
endpointهای مدیریت از احراز هویت JWT استفاده میکنند. ابتدا با /api/v1/auth/login توکن بگیرید.
احراز هویت
| متد | مسیر | توضیحات |
|---|---|---|
| POST | /api/v1/auth/register | ثبتنام کاربر جدید |
| POST | /api/v1/auth/login | ورود و دریافت access/refresh token |
| POST | /api/v1/auth/refresh | تمدید توکن با refresh token |
| POST | /api/v1/auth/logout | خروج و ابطال توکن |
| GET | /api/v1/auth/me | اطلاعات کاربر فعلی |
# ثبتنام
curl -X POST https://api.darvareh.ir/api/v1/auth/register \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "strongpass123"}'
# ورود
curl -X POST https://api.darvareh.ir/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email": "user@example.com", "password": "strongpass123"}'
# پاسخ ورود:
# {
# "access_token": "eyJ...",
# "refresh_token": "eyJ...",
# "token_type": "bearer",
# "expires_in": 1800
# }مدیریت کلیدهای API
| متد | مسیر | توضیحات |
|---|---|---|
| GET | /api/v1/keys | لیست کلیدهای API |
| POST | /api/v1/keys | ساخت کلید جدید |
| DELETE | /api/v1/keys/{id} | حذف کلید |
| GET | /api/v1/keys/{id}/usage | آمار مصرف کلید |
ساخت کلید API
curl -X POST https://api.darvareh.ir/api/v1/keys \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Key",
"rate_limit_rpm": 60,
"rate_limit_tpm": 100000,
"allowed_models": ["openai/gpt-4o", "anthropic/claude-sonnet-4"]
}'
# پاسخ:
# {
# "id": "...",
# "key": "sk-darvareh-abc123...", ← فقط یکبار نمایش داده میشود!
# "key_prefix": "sk-darvareh-abc1",
# "name": "Production Key",
# "rate_limit_rpm": 60,
# "rate_limit_tpm": 100000,
# "allowed_models": {"models": ["openai/gpt-4o", "anthropic/claude-sonnet-4"]},
# "is_active": true,
# "total_requests": 0,
# "total_tokens": 0,
# "total_spent": "0"
# }نکته: اگر allowed_models را خالی بگذارید، کلید به تمام مدلها دسترسی خواهد داشت.
اعتبار و صورتحساب
| متد | مسیر | توضیحات |
|---|---|---|
| GET | /api/v1/billing/balance | موجودی فعلی |
| GET | /api/v1/billing/transactions | تاریخچه تراکنشها |
نکته: تمام مبالغ به تومان نمایش داده میشوند.
curl https://api.darvareh.ir/api/v1/billing/balance \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# پاسخ:
# {
# "user_id": "...",
# "balance": "8,750,000",
# "total_credits_used": "26,250,000"
# }نحوه محاسبه هزینه
- •هزینه بر اساس تعداد توکنهای مصرفی (ورودی + خروجی) محاسبه میشود
- •قیمت هر مدل متفاوت است — از صفحه مدلها قیمتها را ببینید
- •هزینه به صورت اتمیک از موجودی کسر میشود — هیچ درخواستی بدون اعتبار کافی پردازش نمیشود
- •در صورت بروز خطای سرور، هزینه به حساب برگردانده میشود