اتصال ابزارها، مرجع API و رفع خطا در یکجا. راهنمای مورد نظر را از فهرست انتخاب کنید؛ پیوند هر راهنما قابل اشتراک است.
نمای کلی و شروع سریع
جارویس یک درگاه API است: با یک کلید، از ابزارهای کدنویسی و از کد خودتان به مدلهای کاتالوگ دسترسی دارید. درگاه دو قالب را میپذیرد — API سازگار با OpenAI و API پیامهای Anthropic — پس بیشتر ابزارها فقط با تنظیم آدرس پایه و کلید وصل میشوند.
مراحل
۱
در کنسول ثبتنام کنید و پلن تهیه کنید. مدلهایی که میتوانید استفاده کنید به پلن فعال شما بستگی دارد.
۲
در صفحهٔ کلیدهای API کلید بسازید. کلید با pmai_ شروع میشود و فقط یکبار کامل نمایش داده میشود.
۳
ابزار خود را از فهرست زیر انتخاب کنید و راهنمایش را دنبال کنید، یا با نمونهٔ درخواست اولین فراخوانی را بفرستید.
Claude Code و Claude Desktop (API پیامهای Anthropic)
https://api.jarvis.you
بدون /v1 — خود ابزار آن را اضافه میکند
کلید API
کلیدها با pmai_ شروع میشوند و در کنسول ساخته، نامگذاری، محدود یا باطل میشوند. مقدار کامل فقط یکبار هنگام ساخت نمایش داده میشود؛ آن را در مخزن کد یا اسکرینشات منتشر نکنید.
هدر احراز هویت
کلید را در یکی از این دو هدر بفرستید؛ درگاه هر دو را میپذیرد: Authorization: Bearer pmai_… یا x-api-key: pmai_…
متغیرهای محیطی برای SDKها و ابزارهای سازگار با OpenAI
SDKهای رسمی OpenAI این دو متغیر را بهطور پیشفرض میخوانند. Claude Code متغیرهای خودش را دارد (راهنمای Claude Code) و Codex آدرس را از فایل پیکربندی میخواند (راهنمای Codex).
هر مدل در کاتالوگ یک Model ID دارد، مثل GPT_5_6_SOL. همین مقدار را در فیلد model درخواستها و تنظیمات ابزارها وارد کنید. Model ID و بقیهٔ مشخصات هر مدل را در کاتالوگ مدلها ببینید.
پشتیبانیشده
Model ID همان مقداری است که درگاه اول با آن مدل را پیدا میکند؛ بزرگی و کوچکی حروف در آن مهم نیست.
نام مستعار Claude (مثل claude-…) برای ابزارهایی است که فقط شناسههای همشکل Claude را میپذیرند. به همان مدل میرسد و مصرف روی همان مدل ثبت میشود؛ مدل دیگری نیست.
محدودیتها و نکتهها
همهٔ مدلها در همهٔ پلنها نیستند. هر پلن فهرست مدلهای مجاز خودش را دارد و درخواست برای مدلی بیرون از آن با خطای ۴۰۳ رد میشود.
در پاسخ GET /v1/models، مدلی که نام مستعار دارد دو بار میآید — یک بار با Model ID و یک بار با نام مستعار. هر دو یک مدلاند؛ این تکرار برای سازگاری با ابزارهاست.
بررسی اتصال
فهرست مدلهایی که کلید شما مجاز به استفاده از آنهاست (رایگان؛ درخواست مدل اجرا نمیشود):
Claude Code مستقیماً با API پیامهای Anthropic (POST /v1/messages) کار میکند و درگاه جارویس همین API را ارائه میدهد. کافی است آدرس پایه، کلید و مدلها را تنظیم کنید.
پشتیبانیشده
کدنویسی و گفتوگو در ترمینال با مدلهای Anthropic کاتالوگ
شمارش توکن پیش از ارسال (/v1/messages/count_tokens) — بدون کسر اعتبار
محدودیتها و نکتهها
احراز هویت فقط با کلید جارویس است؛ ورود با حساب Claude لازم نیست و از طریق درگاه استفاده نمیشود.
کار با مدلهای غیر Anthropic از طریق نام مستعار Claude به مسیر بالادستی آن مدل بستگی دارد و تضمین نمیشود. برای این مدلها ابزارهای سازگار با OpenAI (Codex، Cline…) مطمئنترند.
پیشنیازها
Claude Code نصبشده (طبق مستندات Anthropic)
یک کلید pmai_ و پلنی که مدلهای انتخابی شما را شامل شود
مراحل
۱
ANTHROPIC_BASE_URL را روی https://api.jarvis.you بگذارید — بدون/v1؛ Claude Code خودش /v1/messages را اضافه میکند.
۲
ANTHROPIC_AUTH_TOKEN (بهصورت Authorization: Bearer فرستاده میشود) و ANTHROPIC_API_KEY (بهصورت x-api-key) را برابر همان کلید بگذارید. درگاه هر دو را میپذیرد؛ تنظیم هر دو، روش پیشنهادی جارویس است. اگر ANTHROPIC_API_KEY تنظیم باشد، Claude Code در حالت تعاملی یکبار تأیید کلید را میپرسد.
۳
مدلها را به Model IDهای کاتالوگ پین کنید: ANTHROPIC_MODEL برای مدل اصلی و ANTHROPIC_DEFAULT_HAIKU_MODEL برای کارهای پسزمینه (ANTHROPIC_SMALL_FAST_MODEL نام قدیمی همین متغیر است و برای نسخههای قدیمیتر در نمونه آمده). مدلی که پین نشود با نام پیشفرض خود Claude Code فرستاده میشود و درگاه آن را نمیشناسد.
۴
Claude Code را اجرا کنید. برای تنظیم دائمی بهجای متغیرهای جلسه، همین مقادیر را در بلوک env فایل settings.json بگذارید (نمونهٔ کامل).
نمونه با مدلهای CLAUDE_OPUS_4_8 و CLAUDE_HAIKU_4_5؛ Model IDهای دلخواه خود را از کاتالوگ جایگزین کنید.
بدون مصرف توکن: این درخواست کلید و مجاز بودن مدل را مثل یک درخواست واقعی بررسی میکند، ولی مدل را اجرا نمیکند. پاسخی مثل {"input_tokens": 9} یعنی اتصال درست است.
افزونهٔ رسمی Claude Code تنظیمات Claude Code را میخواند؛ سادهترین روش دائمی، بلوک env در فایل settings.json است. متغیرها و دلیل هرکدام همانهایی است که در راهنمای Claude Code آمده.
پیشنیازها
افزونهٔ Claude Code ساخت Anthropic از بخش Extensions (Ctrl+Shift+X)
یک کلید pmai_
مراحل
۱
بلوک زیر را در settings.json Claude Code قرار دهید و کلید خود را جایگزین مقدار نمونه کنید.
۲
مسیر فایل برای هر سیستمعامل در تبهای زیر آمده است.
۳
روش جایگزین طبق مستندات Anthropic: همین متغیرها را در تنظیم VS Code با نام claudeCode.environmentVariables وارد کنید؛ افزونه پیش از اجرا آن را میخواند.
۴
VS Code را دوباره باز کنید تا تنظیمات جدید خوانده شود.
اپ دسکتاپ Claude میتواند بهجای سرویس Anthropic از یک درگاه شخص ثالث استفاده کند. برای مدلهای غیر Claude، نام مستعار Claude همان مدل را انتخاب کنید؛ مصرف روی همان مدل اصلی ثبت میشود.
پشتیبانیشده
گفتوگو با مدلهای Anthropic کاتالوگ با شناسهٔ خودشان
مدلهای غیر Claude از راه نام مستعار Claude
محدودیتها و نکتهها
طبق مستندات Anthropic، وقتی درگاه فعال است فقط محیط محلی در دسترس است و Remote Control کار نمیکند.
به تجربهٔ تیم جارویس، اپ فقط شناسههای همشکل Claude را در انتخاب مدل میپذیرد؛ این رفتار در مستندات Anthropic ذکر نشده، برای همین مدلهای غیر Claude نام مستعار دارند.
پیشنیازها
آخرین نسخهٔ Claude Desktop
یک کلید pmai_
مراحل
۱
از منوی Help → Troubleshooting گزینهٔ Enable Developer Mode را فعال کنید.
۲
از منوی Developer گزینهٔ Configure Third-Party Inference را باز کنید. اگر سازمان شما پیکربندی را مدیریت کند، این فرم فقطخواندنی است.
۳
آدرس درگاه را https://api.jarvis.you — بدون /v1 — و کلید را کلید جارویس خود وارد کنید.
۴
مدل را انتخاب کنید: مدلهای Anthropic با Model ID خودشان و بقیه با نام مستعار Claude (جدول زیر).
Claude Desktop · Third-Party Inference
Gateway base URL: https://api.jarvis.you
API key: pmai_xxxxxxxxxxxxxxxxxxxx
نامهای مستعار Claude
از کاتالوگ عمومی جارویس. مدلهای خانوادهٔ Claude نام مستعار ندارند؛ شناسهٔ خودشان مستقیماً کار میکند.
Codex از Responses API استفاده میکند و درگاه جارویس /v1/responses را ارائه میدهد. درگاه را بهعنوان یک ارائهدهندهٔ سفارشی در ~/.codex/config.toml تعریف کنید.
پشتیبانیشده
کدنویسی و گفتوگو با Model IDهای کاتالوگ از طریق Responses API
محدودیتها و نکتهها
Codex فقط wire_api = "responses" را میپذیرد؛ مقدار قدیمی "chat" در نسخههای فعلی خطا میدهد.
Codex دیگر OPENAI_BASE_URL را نمیخواند؛ آدرس درگاه باید در base_url فایل پیکربندی باشد.
شناسهٔ openai برای ارائهدهنده رزرو شده است؛ از شناسهٔ دیگری مثل jarvis استفاده کنید.
پشتیبانی Responses API برای هر مدل به مسیر بالادستی همان مدل بستگی دارد.
پیشنیازها
Codex CLI نصبشده
یک کلید pmai_
مراحل
۱
فایل ~/.codex/config.toml را با بلوک زیر بسازید یا کامل کنید؛ model را Model ID دلخواه از کاتالوگ بگذارید.
۲
متغیر محیطی OPENAI_API_KEY را برابر کلید خود قرار دهید — env_key در پیکربندی به همین متغیر اشاره میکند.
۳
Codex را اجرا کنید.
~/.codex/config.toml
model = "GPT_5_6_SOL"
model_provider = "jarvis"
[model_providers.jarvis]
name = "Jarvis"
base_url = "https://api.jarvis.you/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
Windows (PowerShell)
$env:OPENAI_API_KEY="pmai_xxxxxxxxxxxxxxxxxxxx"
بررسی اتصال
در Codex یک درخواست کوتاه بفرستید. پاسخ عادی یعنی اتصال برقرار است.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
wire_api
اگر خطای «wire_api = "chat" is no longer supported» گرفتید، مقدار را "responses" کنید.
افزونهٔ Codex همان ~/.codex/config.toml مربوط به Codex CLI را میخواند؛ یک پیکربندی برای هر دو کافی است.
پیشنیازها
افزونهٔ Codex ساخت OpenAI از بخش Extensions
یک کلید pmai_
مراحل
۱
فایل ~/.codex/config.toml را با بلوک زیر بسازید — بین CLI و افزونه مشترک است.
۲
متغیر OPENAI_API_KEY را برابر کلید خود قرار دهید؛ اگر افزونه ورود با کلید API را پیشنهاد داد، همان کلید را وارد کنید.
۳
VS Code را دوباره باز کنید.
~/.codex/config.toml
model = "GPT_5_6_SOL"
model_provider = "jarvis"
[model_providers.jarvis]
name = "Jarvis"
base_url = "https://api.jarvis.you/v1"
env_key = "OPENAI_API_KEY"
wire_api = "responses"
بررسی اتصال
در پنل Codex یک درخواست کوتاه بفرستید.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
Cursor اجازه میدهد کلید و آدرس سفارشی OpenAI را برای مدلهای گفتوگو استفاده کنید.
پشتیبانیشده
گفتوگو با مدلهای کاتالوگ که بهصورت دستی به Cursor اضافه میکنید
محدودیتها و نکتهها
طبق مستندات Cursor، کلیدهای سفارشی فقط برای مدلهای گفتوگو کار میکنند؛ تکمیل خودکار (Tab) همچنان از مدلهای خود Cursor استفاده میکند.
درخواستها از سرورهای Cursor عبور میکنند، پس آدرس درگاه باید از اینترنت در دسترس باشد (آدرس عمومی جارویس هست).
گزینهٔ بازنویسی آدرس پایه در مستندات رسمی Cursor شرح داده نشده و فقط در انجمن Cursor آمده است؛ این اتصال را «بهترین تلاش» بدانید. به گفتهٔ همان منبع، این تنظیم روی همهٔ مدلها اثر میگذارد و برخی مدلهای اختصاصی Cursor با کلید سفارشی کار نمیکنند.
پیشنیازها
Cursor نصبشده
یک کلید pmai_
مراحل
۱
در Cursor Settings → Models کلید OpenAI را کلید جارویس خود بگذارید و گزینهٔ Override OpenAI Base URL را روی https://api.jarvis.you/v1 تنظیم کنید.
۲
Model ID دلخواه (مثلاً GPT_5_6_SOL) را بهعنوان مدل سفارشی اضافه و انتخاب کنید.
بررسی اتصال
در گفتوگوی Cursor همان مدل را انتخاب و پیام کوتاهی بفرستید.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
Cline با ارائهدهندهٔ «OpenAI Compatible» به درگاه وصل میشود.
پیشنیازها
افزونهٔ Cline در VS Code
یک کلید pmai_
مراحل
۱
در تنظیمات Cline، API Provider را OpenAI Compatible انتخاب کنید.
۲
Base URL را https://api.jarvis.you/v1، API Key را کلید خود و Model ID را Model ID مدل از کاتالوگ بگذارید.
۳
در صورت نیاز، بخش Model Configuration (پنجرهٔ متن، پشتیبانی تصویر) را مطابق مدل تنظیم کنید.
OpenAI Compatible
API Provider: OpenAI Compatible
Base URL: https://api.jarvis.you/v1
API Key: pmai_xxxxxxxxxxxxxxxxxxxx
Model ID: GPT_5_6_SOL
بررسی اتصال
در Cline یک کار کوچک بخواهید؛ پاسخ عادی یعنی اتصال برقرار است.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
Roo Code هم ارائهدهندهٔ «OpenAI Compatible» را با همان سه مقدار میپذیرد.
محدودیتها و نکتهها
مخزن رسمی Roo Code از اردیبهشت ۱۴۰۵ بایگانی شده و آخرین نسخهاش v3.54.0 است؛ بهروزرسانی تازهای از سازنده انتظار نمیرود.
طبق مستندات Roo Code، فقط مدلهایی که فراخوانی ابزار بومی دارند با آن کار میکنند.
پیشنیازها
افزونهٔ Roo Code در VS Code
یک کلید pmai_
مراحل
۱
ارائهدهنده را OpenAI Compatible انتخاب کنید.
۲
Base URL را https://api.jarvis.you/v1، کلید را کلید خود و Model را Model ID مدل بگذارید.
OpenAI Compatible
API Provider: OpenAI Compatible
Base URL: https://api.jarvis.you/v1
API Key: pmai_xxxxxxxxxxxxxxxxxxxx
Model ID: GPT_5_6_SOL
بررسی اتصال
یک درخواست کوتاه بفرستید.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
Continue مدلها را در ~/.continue/config.yaml تعریف میکند (فایل config.json قدیمی منسوخ شده است). درگاه را با ارائهدهندهٔ openai و apiBase معرفی کنید.
محدودیتها و نکتهها
Continue برای برخی نامهای مدل ممکن است بهجای Chat Completions از /responses استفاده کند؛ درگاه هر دو را ارائه میدهد. اگر خطا دیدید، useResponsesApi: false را به مدل اضافه کنید تا Chat Completions استفاده شود.
پیشنیازها
افزونهٔ Continue در VS Code یا JetBrains
یک کلید pmai_
مراحل
۱
بلوک زیر را در ~/.continue/config.yaml قرار دهید و کلید خود را جایگزین مقدار نمونه کنید.
۲
برای هر مدل دیگر یک مورد جدید در فهرست models با Model ID همان مدل اضافه کنید.
مدل «GPT_5_6_SOL» را در Continue انتخاب و پیام کوتاهی بفرستید.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
مدلهای Gemini کاتالوگ از مسیر سازگار با OpenAI در دسترساند: هر ابزار یا SDK سازگار با OpenAI را به درگاه وصل کنید و Model ID یک مدل Gemini (مثلاً GEMINI_3_1_PRO) را انتخاب کنید.
محدودیتها و نکتهها
ابزار خط فرمان رسمی Gemini (Gemini CLI) قالب بومی Google را میفرستد و نمیتواند به درگاه سازگار با OpenAI وصل شود؛ GOOGLE_GEMINI_BASE_URL فقط میزبان را عوض میکند، نه قالب را.
فهرست مدلهای مجاز کلید را بگیرید و مطمئن شوید مدل Gemini مورد نظر در آن هست (فهرست مدلها).
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
SDKهای رسمی OpenAI برای Node.js و Python فقط با تغییر آدرس پایه و کلید به درگاه وصل میشوند.
پشتیبانیشده
Chat Completions (client.chat.completions.create)
Responses API (client.responses.create) — پشتیبانی هر مدل به مسیر بالادستی آن بستگی دارد
تولید و ویرایش تصویر با مدلهای تصویری (نقاط پایانی)
پیشنیازها
بستهٔ openai برای Node.js یا Python
یک کلید pmai_
مراحل
۱
در ساخت کلاینت، baseURL (Node.js) یا base_url (Python) را https://api.jarvis.you/v1 بگذارید؛ هر دو SDK در نبود این مقدار، متغیر OPENAI_BASE_URL را میخوانند.
۲
کلید را در apiKey / api_key یا متغیر OPENAI_API_KEY قرار دهید.
نمونهٔ زیر را اجرا کنید؛ این درخواست مقدار کمی توکن مصرف میکند.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
همهٔ مسیرها زیر https://api.jarvis.you/v1 هستند و با کلید جارویس (Authorization: Bearer یا x-api-key) احراز هویت میشوند. سازگاری قالب به معنای کار کردن همهٔ قابلیتهای هر ابزار نیست؛ هر ابزار را با راهنمای خودش بسنجید.
روش و مسیر
قالب
کاربرد
POST/v1/chat/completions
OpenAI
تکمیل گفتوگو
POST/v1/responses
OpenAI
Responses API (برای Codex و SDKها)
POST/v1/completions
OpenAI
تکمیل متن (سازگاری قدیمی)
POST/v1/messages
Anthropic
پیامها (برای Claude Code و Claude Desktop)
POST/v1/messages/count_tokens
Anthropic
شمارش توکن؛ مدل اجرا و مصرفی ثبت نمیشود
GET/v1/models
OpenAI
مدلهای مجاز کلید شما
POST/v1/images/generations
OpenAI
تولید تصویر (JSON)
POST/v1/images/edits
OpenAI
ویرایش تصویر (multipart یا data URI)
POST/v1/embeddings
OpenAI
تبدیل متن به بردار (Embedding)؛ هزینه بهازای توکن ورودی
POST/v1/videos
OpenAI
ساخت ویدیو (JSON یا multipart)؛ هزینهٔ ثابت بهازای مدل و طول
GET/v1/videos
OpenAI
فهرست ویدیوهای همین کلید (افزونهٔ جارویس، مثل فهرست OpenAI)
GET/v1/videos/{id}
OpenAI
وضعیت ویدیو برای پیگیری
GET/v1/videos/{id}/content
OpenAI
دانلود MP4 با پشتیبانی از Range
DELETE/v1/videos/{id}
OpenAI
لغو ویدیوی در صف، یا حذف نسخهٔ ذخیرهشدهٔ ویدیوی پایانیافته
POST/v1/files
OpenAI
بارگذاری فایل JSONL پردازش دستهای (multipart با purpose=batch)؛ خطبهخط بررسی میشود
GET/v1/files
OpenAI
فهرست فایلهای حساب شما، شامل فایلهای نتیجه (purpose: batch، batch_output، batch_error)
GET/v1/files/{id}
OpenAI
مشخصات یک فایل
GET/v1/files/{id}/content
OpenAI
دانلود فایل یا فایل نتیجه؛ همیشه کل فایل، بدون Range
DELETE/v1/files/{id}
OpenAI
حذف فایل (فایل ورودی دستهٔ ناتمام حذف نمیشود)
POST/v1/batches
OpenAI
ساخت دسته از روی فایل بارگذاریشده؛ برآورد حداکثر هزینه نگه داشته میشود
GET/v1/batches
OpenAI
فهرست دستههای حساب شما
GET/v1/batches/{id}
OpenAI
وضعیت دسته برای پیگیری
POST/v1/batches/{id}/cancel
OpenAI
لغو دسته؛ خطهایی که اجرا شدهاند حساب میشوند
تصویر
مسیرهای تصویر فقط با مدلهای تصویری کاتالوگ کار میکنند و هر درخواست یک تصویر میسازد (n فقط ۱). هزینه برای هر درخواست موفق ثابت است و در پروفایل همان مدل در کاتالوگ آمده؛ درخواست ناموفق هزینهای ندارد. ویرایش، فایلها را بهصورت multipart/form-data یا data URI در JSON میپذیرد و ماسک پشتیبانی نمیشود. حداکثر حجم درخواست ۳۲ مگابایت است.
اولین درخواست با cURL، Node.js یا Python. کلید نمونه ساختگی است؛ کلید خود را از کنسول جایگزین کنید. مدل نمونه GPT_5_6_SOL است؛ Model ID دلخواه را از کاتالوگ بردارید.
پاسخ موفق شامل choices[0].message.content است. این درخواست مقدار کمی توکن مصرف میکند.
خطاهای رایج
۴۰۱
کلید اشتباه، باطلشده یا ارسالنشده است. کلید باید با pmai_ شروع شود.
۴۰۳
مدل در پلن فعال این کلید مجاز نیست، اشتراک فعالی ندارید، یا نام مدل در کاتالوگ نیست. فهرست مدلهای مجاز کلید را با GET https://api.jarvis.you/v1/models ببینید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف همین کلید تمام شده است؛ وضعیت را در کنسول ببینید.
۴۰۴ یا خطای مسیر
آدرس پایه باید دقیقاً https://api.jarvis.you/v1 باشد — با /v1 و بدون اسلش اضافه در انتها.
تبدیل متن به بردار (Embedding)
Embedding (امبدینگ) متن را به فهرستی از عددها، یعنی یک بردار، تبدیل میکند؛ متنهایی که معنای نزدیک دارند بردارهای نزدیک به هم میگیرند. با آن جستوجوی معنایی، RAG (پرسش و پاسخ روی اسناد خودتان)، خوشهبندی و پیشنهاد محتوا میسازید. جارویس این کار را با POST /v1/embeddings و در قالب API سازگار با OpenAI ارائه میدهد؛ SDKهای OpenAI و LangChain فقط با تنظیم آدرس پایه و کلید کار میکنند.
پشتیبانیشده
یک متن یا آرایهای تا ۲٬۰۴۸ متن در هر درخواست؛ پاسخ برای هر متن یک بردار دارد، به همان ترتیب ورودی.
خروجی بهصورت آرایهٔ عددها (float، پیشفرض) یا رشتهٔ base64 با حجمی حدود یکسوم.
OpenAI SDK برای Python و Node.js، LangChain و هر کلاینت HTTP.
مدلهای Embedding مجاز هر کلید در GET /v1/models فهرست میشوند (فقط مدلهای دارای قیمت).
محدودیتها و نکتهها
حداکثر ۲٬۰۴۸ متن در هر درخواست، و هیچ متنی خالی یا فقط فاصله نباشد. بدنهٔ JSON حداکثر ۸ مگابایت (۸٬۰۰۰٬۰۰۰ بایت) است؛ بزرگتر از آن ۴۱۳ میگیرد.
آرایهٔ توکن پذیرفته نمیشود (مثل [101, 2023])؛ فقط متن بفرستید. LangChain بهطور پیشفرض توکن میفرستد — بخش «LangChain» را ببینید.
پاسخ حداکثر ۴۰ مگابایت است. با float درخواستهای بزرگ روی مدلهای ۳٬۰۷۲ بعدی ممکن است از این سقف بگذرند (۵۰۲، بدون هزینه). encoding_format: "base64" حجم را حدود یکسوم میکند؛ یا تعداد متنها را کمتر کنید (با float، حدود ۵۰۰ متن در هر درخواست یک راهنمای سرانگشتی است).
هر مدل سقف طول متن خودش را دارد؛ متنی که بلندتر باشد ۴۱۳ میگیرد. اسناد بلند را به تکههای کوتاهتر تقسیم کنید.
فقط model، input، encoding_format، dimensions و user پذیرفته میشوند. user فقط برای سازگاری با SDKها پذیرفته و دور ریخته میشود؛ فیلد دیگر ۴۰۰ میدهد و نامش را در param میگوید. dimensions بدون تغییر به مدل میرسد و مدل ممکن است آن را نادیده بگیرد یا رد کند (رد شدن ۴۰۰ یا ۴۲۲ است و هزینه ندارد).
پیشنیازها
یک کلید pmai_
پلنی که یکی از مدلهای Embedding را شامل شود — کلید شما کدامها را میتواند استفاده کند را با GET /v1/models ببینید
بستهٔ openai (Python یا Node.js)، langchain-openai برای LangChain، و numpy و requests برای نمونههای base64 و کسینوسی
مراحل
۱
کلید و آدرس پایه را در متغیرهای محیطی بگذارید (نمونه برای Windows PowerShell، macOS و Linux در پایین آمده است).
۲
مدل را از جدول «مدلها و هزینه» انتخاب کنید و شناسهٔ آن را در فیلد model بگذارید.
۳
متن یا آرایهای از متنها را در input بفرستید. بردار هر متن در data[i].embedding است، به ترتیب ورودی.
۴
بردارها را در پایگاه برداری یا فایل خودتان نگه دارید: جارویس آنها را ذخیره نمیکند و بعداً دوباره نمیفرستد.
۵
برای جستوجو، پرسش را با همان مدل Embedding کنید و با شباهت کسینوسی با بردارهای نگهداشتهشده مقایسه کنید.
متغیرهای محیطی
SDKهای رسمی OpenAI و نمونهٔ PowerShell این دو متغیر را میخوانند. هر جلسهٔ ترمینال تازه باید دوباره آنها را داشته باشد، مگر در تنظیمات سیستمعامل یا فایل پروفایل شل ثبتشان کنید.
نمونهٔ cURL برای bash و zsh (macOS و Linux) است. در Windows PowerShell دستور curl نام مستعار Invoke-WebRequest است و \ خط را ادامه نمیدهد؛ از تب PowerShell (که متغیرهای بالا را میخواند) یا نمونهٔ Python استفاده کنید. پاسخ برای هر متن چند هزار عدد دارد؛ در ترمینال آن را به فایل یا ابزاری مثل jq بدهید.
شکل پاسخ، با عددهای نمونه (بردار واقعی همهٔ ابعاد مدل را دارد):
usage.prompt_tokens تعداد توکن ورودی کل درخواست است و هزینه از روی همین عدد حساب میشود. فیلد model همان نامی است که فرستادهاید.
LangChain: چرا check_embedding_ctx_length=False؟
LangChain بهطور پیشفرض (check_embedding_ctx_length=True) متن را خودش به توکن تبدیل میکند و بهجای متن، آرایههایی از عدد میفرستد. جارویس آرایهٔ توکن را نمیپذیرد و با خطای ۴۰۰ و param: "input" رد میکند؛ پیام خطا خودش همین راهحل را مینویسد (نمونهاش در بخش «قالب خطاها» است). با check_embedding_ctx_length=False متن ساده فرستاده میشود، و نمونهٔ LangChain بالا همین را دارد.
نتیجهٔ خاموش کردن این بررسی: LangChain دیگر متنهای خیلی بلند را خودش تکهتکه نمیکند، پس طول هر متن را خودتان کنترل کنید.
قالب base64
با "encoding_format": "base64" هر بردار بهجای آرایهٔ عدد یک رشته است: مقدارهای float32 با ترتیب بایت little-endian که base64 شدهاند. حجم پاسخ حدود یکسوم میشود و برای مدلهای ۳٬۰۷۲ بعدی راه اصلی دور ماندن از سقف ۴۰ مگابایتی پاسخ است. SDKهای رسمی OpenAI معمولاً خودشان base64 میخواهند و رمزگشایی میکنند؛ فقط وقتی مستقیم با HTTP کار میکنید باید خودتان رمزگشایی کنید:
Python · base64 + numpy
import base64
import numpy as np
import requests
res = requests.post(
"https://api.jarvis.you/v1/embeddings",
headers={"Authorization": "Bearer pmai_xxxxxxxxxxxxxxxxxxxx"},
json={
"model": "text-embedding-3-small",
"input": [
"پایتخت ایران کجاست؟",
"تهران پایتخت ایران است",
],
"encoding_format": "base64",
},
timeout=150,
)
res.raise_for_status()
vectors = [
np.frombuffer(base64.b64decode(item["embedding"]), dtype="<f4")
for item in res.json()["data"]
]
print(vectors[0].shape, vectors[0].dtype)
شباهت کسینوسی
نزدیکی دو بردار را با شباهت کسینوسی میسنجند: عددی بین ۱- و ۱ که هرچه به ۱ نزدیکتر باشد، معنا نزدیکتر است. نمونهٔ زیر یک پرسش را با چند سند مقایسه و مرتب میکند — هستهٔ جستوجوی معنایی. پرسش و سندها باید با یک مدل (و یک مقدار dimensions) ساخته شده باشند.
Python · cosine similarity
import numpy as np
from openai import OpenAI
client = OpenAI(
base_url="https://api.jarvis.you/v1",
api_key="pmai_xxxxxxxxxxxxxxxxxxxx",
)
def cosine_similarity(a, b):
a = np.asarray(a, dtype=np.float32)
b = np.asarray(b, dtype=np.float32)
return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
query = "پایتخت ایران کجاست؟"
documents = [
"تهران پایتخت ایران است",
"قیمت دلار امروز",
"اصفهان شهر تاریخی است",
]
res = client.embeddings.create(model="text-embedding-3-small", input=[query, *documents])
query_vector, *document_vectors = [item.embedding for item in res.data]
scores = [cosine_similarity(query_vector, v) for v in document_vectors]
for score, text in sorted(zip(scores, documents), reverse=True):
print(f"{score:.3f} {text}")
مدلها و هزینه
مدلهای Embedding جارویس از این شناسهها هستند: text-embedding-3-small، text-embedding-3-large، gemini-embedding و gemini-embedding-2 (پیشنمایش؛ رفتارش ممکن است تغییر کند). هر مدل پس از انتشار قیمت و فعالشدن در کاتالوگ، در جدول زیر میآید.
مدلهای Embedding، شناسهٔ مدل در درخواست، ابعاد بردار و هزینه بهازای هر ۱٬۰۰۰ توکن ورودی
هزینه از کاتالوگ عمومی جارویس خوانده میشود و فقط مدلهای دارای قیمت در جدول هستند؛ مدلهای در دسترس کلید شما به پلن آن بستگی دارد. ابعاد بردار مقدار اعلامشدهٔ مدل است — مقدار واقعی را از طول بردار پاسخ بخوانید. پروفایل کامل هر مدل و فهرست همهٔ مدلهای Embedding در کاتالوگ مدلها است.
هزینه چطور حساب میشود؟
هزینه بر اساس توکنهای ورودی است و پس از برگشتن بردارها کسر میشود: max(1, ceil(prompt_tokens × rate / 1000)) توکن جارویس. اینجا prompt_tokens همان usage.prompt_tokens پاسخ و rate نرخ مدل در جدول بالاست. درخواست ناموفق، با هر خطایی، هزینهای ندارد.
مثال با نرخ فرضی ۲۰ توکن بهازای هر ۱٬۰۰۰ توکن ورودی: درخواستی با ۱٬۲۳۴ توکن ورودی (ceil(1234 × 20 / 1000) = ceil(24.68) = 25) ۲۵ توکن جارویس هزینه دارد، و درخواستی بسیار کوتاه هم دستکم ۱ توکن.
پیش از ارسال، مقداری برآوردی از موجودی کنار گذاشته میشود و پس از پاسخ فقط هزینهٔ واقعی کسر و بقیه آزاد میشود. اگر ارائهدهنده تعداد توکن را نفرستد یا عدد قابلاستفادهای ندهد، جارویس آن را از طول متنها (حدود یک توکن برای هر ۴ نویسه) برآورد میکند. متن فارسی معمولاً بهازای هر نویسه توکن بیشتری از انگلیسی میگیرد؛ توکنها را ارائهدهندهٔ مدل میشمارد.
شناسهٔ یکتای درخواست (Idempotency-Key)
هدر اختیاری Idempotency-Key (یک بار در درخواست، ۱ تا ۱۲۰ نویسه) جلوی حساب شدن دوبارهٔ یک درخواست تکراری را میگیرد: اگر همان کلید هنوز در حال اجراست یا قبلاً انجام شده، پاسخ ۴۰۹ میگیرید. بردارها ذخیره نمیشوند، پس هرگز دوباره پخش یا دوباره محاسبه نمیشوند؛ برای گرفتن دوبارهٔ بردارها درخواست تازهای با شناسهٔ تازه بفرستید (و هزینهٔ آن حساب میشود). این شناسه فقط برای Embedding است و با شناسههای درخواستهای دیگر (چت، تصویر، گفتار) تداخل ندارد.
بردار مدلهای مختلف قابل مقایسه نیست
هر مدل فضای برداری خودش را دارد؛ شباهت کسینوسی میان بردارهای دو مدل مختلف بیمعناست. پرسشها و اسناد را با یک مدل (و یک مقدار dimensions) بسازید. اگر مدل را عوض کردید، همهٔ دادههایتان را دوباره Embedding کنید.
چطور مدل را انتخاب کنم؟
با text-embedding-3-small شروع کنید: بردارش کوچکتر است (طبق ابعاد اعلامشده ۱٬۵۳۶ عدد در برابر ۳٬۰۷۲ عدد)، پس در پایگاه برداری نصف فضا میگیرد و مقایسهاش سبکتر است. اگر کیفیت جستوجو کافی نبود، مدلهای بزرگتر یا Gemini را امتحان کنید، اما با دادههای خودتان بسنجید: چند پرسش واقعی با پاسخ درست آماده کنید و ببینید کدام مدل مورد درست را بالاتر میآورد؛ بهخصوص برای متن فارسی، هیچ جایگزینی برای این آزمایش نیست. هزینهٔ هر مدل در جدول بالا آمده و gemini-embedding-2 پیشنمایش است؛ برای سیستم پایدار با احتیاط انتخابش کنید.
قالب خطاها
خطاهای این مسیر قالب OpenAI دارند: error.message، error.type، error.code و error.param (نام فیلد مشکلدار). پیامها متن ثابت جارویساند و نه متن درخواست شما را تکرار میکنند و نه متن خطای ارائهدهنده را. کد وضعیت HTTP واقعی است؛ جدول «خطاهای رایج» پایین همین صفحه علت هر کدام را میگوید. نمونه، همان خطای آرایهٔ توکن در LangChain:
JSON · خطای ۴۰۰
{
"error": {
"message": "Token arrays are not supported: 'input' must be a string or an array of strings. If you use LangChain, create OpenAIEmbeddings with check_embedding_ctx_length=False so it sends text instead of token arrays.",
"type": "invalid_request_error",
"code": "Gateway.InvalidRequest",
"param": "input"
}
}
بررسی اتصال
رایگان: فهرست مدلهای مجاز کلید را بگیرید و ببینید مدل Embedding مورد نظر در آن هست. سپس یک درخواست کوچک (مثلاً یک جمله) بفرستید؛ دستکم ۱ توکن جارویس هزینه دارد.
درخواست نامعتبر. error.param فیلد مشکلدار را میگوید: input (خالی، بیش از ۲٬۰۴۸ متن، آرایهٔ توکن)، model (مدل Embedding نیست یا نامش با چند مدل منطبق است)، encoding_format، dimensions یا فیلدی که این مسیر نمیشناسد. هزینهای ثبت نمیشود.
۴۰۱
کلید ارسال نشده یا نامعتبر است؛ آن را در Authorization: Bearer یا x-api-key بفرستید.
۴۰۲
موجودی توکن یا سقف مصرف همین کلید برای مبلغی که پیش از ارسال کنار گذاشته میشود کافی نیست. این مبلغ از طول متنها برآورد میشود و میتواند از هزینهٔ نهایی بیشتر باشد؛ پس از پاسخ فقط هزینهٔ واقعی کسر میشود.
۴۰۳
مدل در پلن این کلید مجاز نیست (param: model)، اشتراک فعال ندارید، یا حساب یا تیم غیرفعال است.
۴۰۹
همین Idempotency-Key هنوز در حال اجراست یا قبلاً انجام و حساب شده است (بخش «شناسهٔ یکتای درخواست»).
۴۱۳
بدنهٔ درخواست از ۸ مگابایت بیشتر است (Gateway.RequestTooLarge)، یا مدل گزارش کرده یکی از متنها از سقف طولش بلندتر است (param: input). متنها را کوتاهتر یا درخواست را کوچکتر کنید.
۴۱۵
فقط application/json پذیرفته میشود.
۴۲۹
سرور موقتاً پرمشغله است (Gateway.Busy، همراه Retry-After: 2) یا ارائهدهندهٔ مدل درخواستها را محدود کرده است (Gateway.UpstreamRateLimited؛ Retry-After فقط وقتی میآید که ارائهدهنده بفرستد، بین ۱ تا ۶۰ ثانیه). مقدار Retry-After را رعایت کنید و با تأخیر فزاینده دوباره بفرستید. هزینهای ثبت نمیشود.
۵۰۰ / ۵۰۲ / ۵۰۳ / ۵۰۴
۵۰۴: پردازش بیش از حدود ۲ دقیقه طول کشید. ۵۰۳: ارائهدهنده یا این مسیر اکنون در دسترس نیست. ۵۰۲: پاسخ ارائهدهنده قابلاستفاده نبود یا از سقف ۴۰ مگابایت بزرگتر بود. ۵۰۰: خطای غیرمنتظره. هیچکدام هزینه ندارد؛ کمی بعد دوباره تلاش کنید، و برای درخواست بزرگ تعداد متنها را کمتر یا base64 را فعال کنید. مشکل کلید یا موجودی خودتان همیشه با ۴۰۱ و ۴۰۲ میآید، نه ۵۰۳.
ساخت ویدیو
با POST /v1/videos از روی یک توصیف متنی، و در صورت دلخواه یک یا چند تصویر، ویدیو میسازید. جارویس این مسیر را در قالب API ویدیوی OpenAI ارائه میدهد؛ SDK رسمی OpenAI فقط با تنظیم آدرس پایه و کلید کار میکند. ساخت ویدیو معمولاً چند دقیقه طول میکشد، پس پاسخ درخواست خود ویدیو نیست: درخواست را میفرستید، شناسه میگیرید، وضعیت را پیگیری میکنید و وقتی completed شد، فایل MP4 را دانلود میکنید.
پشتیبانیشده
ویدیو از روی توصیف متنی؛ با یک تصویر بهعنوان فریم اول، چند تصویر مرجع، و در مدلهایی که پشتیبانی میکنند فریم پایانی (last_frame).
طول، نسبت تصویر (مثل 16:9 یا 9:16)، اندازه و در بعضی مدلها کیفیت 1080p؛ هر مدل مقدارهای مجاز خودش را دارد.
SDK رسمی OpenAI برای Python و Node.js (create_and_poll، download_content، delete) و هر کلاینت HTTP.
دانلود با هدر Range (ادامهٔ دانلود نیمهکاره، پخشکننده).
مدلهای ویدیوی مجاز هر کلید در GET /v1/models فهرست میشوند (فقط مدلهای دارای قیمت).
محدودیتها و نکتهها
قیمت هر ویدیو ثابت است و به مدل و طول آن بستگی دارد. فقط طولهایی که در جدول قیمت آمده پذیرفته میشود؛ طول دیگر ۴۰۰ با param: seconds میگیرد و پیامش طولهای مجاز را میگوید. مدلی که قیمت ندارد عرضه نمیشود.
تصویر فقط بهصورت data: URL یا فایل multipart پذیرفته میشود؛ نشانی https ۴۰۰ میدهد (دلیلش در بخش «تصویر اول و آخر» آمده). فرمتها JPEG، PNG و WebP است و جارویس فرمت را از محتوای فایل تشخیص میدهد، نه از نام یا نوعی که اعلام کردهاید.
حجم تصویرهای یک درخواست روی هم (خود تصویرها، نه متن base64 آنها) حداکثر ۲۲٬۰۰۰٬۰۰۰ بایت است؛ بیشتر از آن ۴۱۳ میگیرد. تعداد تصویر مرجع هم سقف هر مدل را دارد (param: input_reference).
فقط این فیلدها پذیرفته میشود: model، prompt، seconds، size، aspect_ratio، resolution، input_reference و last_frame. user و metadata فقط برای سازگاری با SDK پذیرفته و دور ریخته میشوند؛ هر فیلد دیگر، از جمله input_video (تبدیل ویدیو به ویدیو)، ۴۰۰ میدهد و نامش را در param میگوید. file_id پشتیبانی نمیشود.
هر کلید بهطور پیشفرض حداکثر ۵ ویدیوی همزمان در حال ساخت دارد؛ ششمی ۴۲۹ با Retry-After میگیرد. هر کلید فقط ویدیوهای خودش را میبیند.
ویدیو در فضای ذخیرهسازی خصوصی شما نگه داشته میشود و از سهمیهٔ فضای شما کم میشود؛ اگر پر باشد، ساخت تازه ۴۰۹ با Video.StorageQuotaExceeded میگیرد، پیش از آنکه چیزی کسر شود.
نسخهٔ ذخیرهشده همیشگی نیست. زمان حذف آن در expires_at میآید (بهطور پیشفرض ۷ روز؛ این مدت قابل تنظیم است). پس از آن دانلود ۴۰۴ با video_expired میدهد؛ ویدیو را زودتر ذخیره کنید.
پیشنیازها
یک کلید pmai_
پلنی که یکی از مدلهای ویدیو را شامل شود، و موجودی و سقف کلید کافی برای قیمت ثابت ویدیو؛ وگرنه ۴۰۲ میگیرید و چیزی کنار گذاشته نمیشود
بستهٔ openai (Python یا Node.js) با نسخهای که client.videos دارد، یا بستهٔ requests برای نمونهٔ بدون SDK
مراحل
۱
کلید و آدرس پایه را در متغیرهای محیطی بگذارید (نمونه برای Windows PowerShell، macOS و Linux در پایین آمده است).
۲
مدل را از جدول «مدلها و قیمت» انتخاب کنید و کد آن را در model و یکی از طولهای قیمتدار همان مدل را در seconds بگذارید.
۳
POST /v1/videos را بفرستید. پاسخ ویدیویی با status: "queued" و یک id است.
۴
GET /v1/videos/{id} را تکرار کنید تا status به completed یا failed برسد (create_and_poll همین را انجام میدهد).
۵
وقتی completed شد، GET /v1/videos/{id}/content فایل MP4 را میدهد؛ پیش از expires_at ذخیرهاش کنید.
متغیرهای محیطی
SDKهای رسمی OpenAI و نمونهٔ PowerShell این دو متغیر را میخوانند. هر جلسهٔ ترمینال تازه باید دوباره آنها را داشته باشد، مگر در تنظیمات سیستمعامل یا فایل پروفایل شل ثبتشان کنید.
نمونهها یک ویدیوی ۸ ثانیهای با نسبت ۱۶:۹ میسازند و تا دانلود پیش میروند. کلید نمونه ساختگی است؛ کلید خود را از کنسول جایگزین کنید. VEO_3_1 فقط نمونه است: کد مدل را از جدول «مدلها و قیمت» بردارید. seconds رشته است ("8")، نه عدد.
cURL
# 1) create: the answer is the video object, "status": "queued", with its id
curl https://api.jarvis.you/v1/videos \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"model": "VEO_3_1",
"prompt": "ویدیوی سینمایی از دریاچهای آرام در سپیدهدم، با مه نازکی روی آب",
"seconds": "8",
"size": "1280x720"
}'
# 2) poll with that id until "status" is "completed" or "failed"
curl https://api.jarvis.you/v1/videos/video_0a1b2c3d4e5f60718293a4b5c6d7e8f9 \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx"
# 3) download the MP4
curl https://api.jarvis.you/v1/videos/video_0a1b2c3d4e5f60718293a4b5c6d7e8f9/content \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx" \
-o video.mp4
نمونهٔ cURL برای bash و zsh (macOS و Linux) است. در Windows PowerShell دستور curl نام مستعار Invoke-WebRequest است و \ خط را ادامه نمیدهد؛ از تب PowerShell (که متغیرهای بالا را میخواند) یا نمونهٔ Python استفاده کنید. نمونهٔ PowerShell توصیف را انگلیسی میفرستد، چون فارسی در یک خط چسباندهشده به کنسول سادهترین جا برای خراب شدن است؛ در فایل UTF-8 یا کد برنامه فارسی مشکلی ندارد.
پاسخ ساخت، بیدرنگ، ویدیو را در صف نشان میدهد (شناسه و زمانها ساختگیاند):
الزامی. توصیف ویدیو؛ سقف طول آن به مدل بستگی دارد (در پروفایل مدل آمده؛ پیشفرض ۲٬۰۰۰ نویسه).
seconds
طول به ثانیه، بهصورت رشته. باید یکی از طولهای قیمتدار مدل باشد. اگر ندهید، طول پیشفرض مدل (در صورت قیمتدار بودن) یا کوتاهترین طول قیمتدار بهکار میرود.
size
اندازهٔ تصویر به شکل 1280x720. اگر هم aspect_ratio بدهید، هر دو باید یک شکل را بگویند (وگرنه ۴۰۰ با Video.ShapeMismatch).
aspect_ratio
یکی از 9:16، 16:9، 1:1، 3:4، 4:3، 21:9، تا جایی که مدل پشتیبانی کند. اگر نه اندازه بدهید نه نسبت، مدل نسبت پیشفرض خودش را میگیرد؛ در مدلهایی که 9:16 دارند، آن (ویدیوی عمودی) است.
resolution
720p یا 1080p، فقط در مدلهایی که کیفیت ۱۰۸۰ دارند (وگرنه ۴۰۰ با Video.ResolutionNotSupported).
input_reference
یک تصویر: فریم اول. چند تصویر: تصویر مرجع (تا سقف مدل). بخش «تصویر اول و آخر».
last_frame
فریم پایانی؛ فقط در مدلهایی که پشتیبانی میکنند و فقط همراه دقیقاً یک input_reference.
وضعیت و پیگیری
ساخت ویدیو چند دقیقه طول میکشد؛ GET /v1/videos/{id} را تکرار کنید تا status یکی از دو حالت پایانی شود. مقدار progress فقط وقتی هست که سرویس ویدیو پیشرفت واقعی گزارش کرده باشد؛ هیچ درصدی از خودمان نمیسازیم.
مقدارهای status ویدیو، معنی هرکدام و کاری که باید بکنید
status
معنی
کار شما
queued
ثبت شده و در صف است؛ ساخت هنوز شروع نشده.
منتظر بمانید. در این وضعیت میتوانید لغو کنید.
in_progress
در حال ساخت، یا آمادهسازی نسخهٔ ذخیرهشده.
منتظر بمانید. دیگر لغو نمیشود.
completed
ساخته و ذخیره شد.
دانلود کنید.
failed
ساخته نشد، یا ساخته شد ولی ذخیره نشد.
علت را از error.code بخوانید (جدول پایین).
در پاسخهای queued و in_progress سرور هدر openai-poll-after-ms (معمولاً ۵۰۰۰) را میفرستد؛ به همان اندازه صبر کنید و دوباره بپرسید. پاسخ ویدیوی تمامشده این هدر را ندارد و حلقهٔ شما باید همینجا تمام شود. create_and_poll در SDK همین کار را میکند. هر پیگیری رایگان است و مصرف توکن ندارد.
ساخت گاهی از حد معمول طولانیتر میشود. جارویس تا وقتی سرویس ویدیو ممکن است ساخت را تمام کند، آن را ناموفق اعلام نمیکند؛ پس تا failed نشده منتظر بمانید. اگر مهلتی برای خودتان گذاشتهاید، تمامشدن مهلت به معنای شکست نیست: بعداً دوباره GET /v1/videos/{id} بزنید. شناسه را گم کردید (مثلاً اتصال بعد از ارسال قطع شد)؟ GET /v1/videos آخرین ویدیوهای همین کلید را میدهد (limit بین ۱ تا ۱۰۰، order، و after با یک شناسه).
ویدیوی تمامشده؛ completed_at و expires_at فقط در این وضعیت مقدار دارند:
در ویدیوی failed، فیلد error یک code و یک message ثابت (انگلیسی) دارد. پیام همیشه میگوید هزینه کسر شده یا نه و هرگز متن خطای سرویس ویدیو را تکرار نمیکند؛ اگر بین جدول و پیام اختلافی دیدید، پیام ملاک است.
مقدارهای error.code ویدیوی failed، معنی هرکدام و اینکه هزینه کسر میشود یا نه
error.code
معنی
هزینه
moderation
سرویس ویدیو درخواست را در حین ساخت بهدلیل قوانین محتوا رد کرد.
کسر میشود
storage_failed
ویدیو ساخته شد ولی ذخیره نشد.
کسر شده و دوباره کسر نمیشود؛ با پشتیبانی تماس بگیرید.
provider_refused
سرویس ویدیو درخواست را نپذیرفت.
کسر نمیشود
provider_busy
سرویس ویدیو شلوغ بود و درخواست را نگرفت؛ دوباره بفرستید.
کسر نمیشود
cancelled
پیش از شروع ساخت لغو شد.
کسر نمیشود
outcome_unknown
معلوم نشد ویدیو ساخته شده یا نه.
کسر نمیشود؛ اگر ساخته شده باشد، پشتیبانی پیگیری میکند.
video_failed
خطای دیگر در ساخت.
در حالت عادی کسر نمیشود؛ پیام خطا صریح میگوید.
تصویر اول و آخر
یک input_reference فریم اول ویدیوست؛ چند تصویر (تا سقف مدل) تصویر مرجعاند. last_frame فقط در مدلهایی است که «فریم پایانی» را در پروفایلشان دارند و فقط همراه دقیقاً یک input_reference. در JSON هر تصویر یک شیء {"image_url": "data:image/png;base64,…"} است؛ بهجای JSON میتوانید فایل را با multipart/form-data هم بفرستید (SDK رسمی همین کار را میکند). نمونهها تصویر را از دیسک میخوانند و data: URL میسازند.
جارویس نشانیای را که شما بدهید از طرف خودش باز نمیکند و تصویر را از اینترنت نمیگیرد. دلیلش حریم خصوصی و ایمنی است: دریافت فایل از نشانی دلخواه، هم شما را در معرض فرستادن نشانیها و محتوایی به جایی میگذارد که نمیخواهید، هم امنیت سرورها را. پس تصویر را خودتان بفرستید؛ نشانی https این پاسخ را میگیرد (هزینهای ثبت نمیشود):
JSON · خطای ۴۰۰
{
"error": {
"message": "image_url must be a data:image/png|jpeg|webp;base64,... URL. https URLs are not fetched by Jarvis (privacy and safety); send the picture itself.",
"type": "invalid_request_error",
"param": "input_reference",
"code": "Video.InvalidRequest"
}
}
دانلود و Range
GET /v1/videos/{id}/content فایل MP4 را میدهد (?variant=video پیشفرض است؛ مقدار دیگر ۴۰۰ میدهد). فقط با کلید API کار میکند. تا وقتی ویدیو completed نشده ۴۰۴ میگیرید، و پس از مدت نگهداری ۴۰۴ با video_expired. هدرهای پاسخ Content-Type: video/mp4، Accept-Ranges: bytes و ETag دارند و نام فایل پیشنهادی از شناسهٔ ویدیو ساخته میشود، نه از توصیف.
یک بازه (bytes=a-b، a- یا -n) ۲۰۶ با Content-Range میدهد؛ بازهٔ نامعتبر ۴۱۶؛ چند بازه یا واحد دیگر نادیده گرفته میشود و کل فایل (۲۰۰) برمیگردد. If-Range با ETag و HEAD هم کار میکنند. برای پخش در پخشکننده یا ادامهٔ دانلود نیمهکاره از همین استفاده کنید.
DELETE /v1/videos/{id} بسته به وضعیت ویدیو دو کار متفاوت میکند، و پاسخ موفقش همیشه {"id": …, "object": "video.deleted", "deleted": true} است:
نتیجهٔ DELETE برای هر وضعیت ویدیو
وضعیت ویدیو
نتیجه
queued
ساخت لغو میشود و هزینهای کسر نمیشود. GET بعدی failed با error.code: cancelled نشان میدهد.
in_progress
۴۰۹ با not_cancellable؛ هیچ چیز عوض نمیشود و ساخت ادامه دارد. هزینه وقتی کسر میشود که ویدیو ساخته شود یا بهدلیل قوانین محتوا رد شود.
completed / failed
نسخهٔ ذخیرهشده و توصیف ویدیو پاک میشود (فقط سابقهٔ هزینه و فراداده، بدون محتوا میماند). از آن پس GET و دانلود ۴۰۴ video_not_found میدهند. حذف، هزینهٔ کسرشده را برنمیگرداند.
حذف ویدیوی پایانیافته مثل API ویدیوی OpenAI نسخهٔ ذخیرهشده را پاک میکند. لغوِ بدون هزینهٔ ویدیوی در صف و ۴۰۹ برای ویدیوی در حال ساخت رفتارهای ویژهٔ جارویساند: سرویس ویدیو فقط پیش از شروع ساخت میتواند آن را لغو کند.
مدلها و قیمت
مدلها با کد جارویس در فیلد model میروند. قیمت به مدل و طول بستگی دارد و برای هر درخواست ثابت است. هر مدل پس از انتشار قیمت و فعالشدن در کاتالوگ، در جدول زیر میآید؛ مدلهایی که کلید شما میتواند استفاده کند به پلن آن بستگی دارد و در GET /v1/models است.
قیمت هر ویدیو به توکن جارویس، برای هر مدل و هر طول ویدیو؛ خانهٔ خالی یعنی آن طول برای آن مدل عرضه نمیشود
قیمتها به توکن جارویس است و از کاتالوگ عمومی جارویس خوانده میشود؛ فقط مدلهای دارای قیمت در جدول هستند و «—» یعنی آن طول برای آن مدل عرضه نمیشود. مدلهای در دسترس کلید شما به پلن آن بستگی دارد. نسبت تصویر، تعداد تصویر مرجع، فریم پایانی و بقیهٔ مشخصات هر مدل در پروفایلش در کاتالوگ مدلها آمده است.
هزینه چطور حساب میشود؟
قیمت هر ویدیو ثابت است و وقتی کسر میشود که سرویس ویدیو آن را بسازد، یا اگر درخواست را بهدلیل قوانین محتوا رد کند. قیمت همان است که در جدول «مدلها و قیمت» برای مدل و طولِ درخواستشده آمده و هنگام ثبت درخواست تثبیت میشود.
پیش از ارسال، موجودی و سقف کلید با همین قیمت سنجیده میشود (ناکافی: ۴۰۲، بدون کنار گذاشتن چیزی). از آن لحظه تا روشن شدن نتیجه، قیمت ویدیو از موجودی شما کنار گذاشته میشود؛ فقط در یکی از دو حالت زیر کسر میشود و در غیر این صورت آزاد میشود.
کسر میشود وقتی سرویس ویدیو ویدیو را بسازد (completed)، یا درخواست را در حین ساخت بهدلیل قوانین محتوا رد کند (failed با error.code: moderation): طبق قوانین سرویس، هزینهٔ آن ساخت کسر میشود و پیام خطا هم همین را میگوید. ساخت دوباره، با توصیف اصلاحشده، یک درخواست تازه با هزینهٔ تازه است.
کسر نمیشود وقتی درخواست پیش از ساخت رد شود (۴۰۰، ۴۰۲، ۴۰۹، ۴۲۹...)، سرویس ویدیو همان لحظه آن را نپذیرد (۴۲۲) یا شلوغ باشد، خطای سامانه یا مهلت خود سرویس ویدیو پیش بیاید، ویدیوی در صف را خودتان لغو کنید (cancelled) یا نتیجه معلوم نشود (outcome_unknown).
یک مشکل بعد از ساخته شدن ویدیو، مثل ذخیره نشدن، کسر هزینه را برنمیگرداند؛ جعبهٔ بعد را ببینید.
ویدیو ساخته شد، ولی ذخیره نشد
در حالتی نادر، ویدیو ساخته و هزینهاش کسر شده، اما جارویس نتوانسته آن را نزد خود ذخیره کند. API در این حالت status: "failed" و error.code: "storage_failed" برمیگرداند (و عمداً completed نمیگوید، چون ویدیویی برای دانلود نیست؛ حلقهٔ پیگیری هم همینجا تمام میشود). این مشکل از سمت جارویس است، نه از شما: هزینه کسر شده و دوباره کسر نمیشود.
JSON · ذخیره نشد
{
"id": "video_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"object": "video",
"model": "VEO_3_1",
"status": "failed",
"created_at": 1790000000,
"completed_at": null,
"expires_at": null,
"seconds": "8",
"size": "1280x720",
"error": {
"code": "storage_failed",
"message": "The video was made and charged, but it could not be stored. Contact support with this video id; you will not be charged again."
}
}
شناسهٔ ویدیو (id) را برای پشتیبانی بفرستید تا پیگیری شود؛ نتیجهٔ پیگیری را پشتیبانی اعلام میکند. تا آن زمان همان درخواست را دوباره نفرستید، چون درخواست تازه هزینهٔ تازه دارد.
قالبهای ویدیو
نمونههایی از ایدههای آمادهٔ ویدیو، هرکدام با شکل و طول پیشنهادی خودش. پیشنمایش فقط یک نمونه است و نتیجهٔ ساخت به توصیف و مدل شما بستگی دارد. در API ویدیو را با prompt، seconds و aspect_ratio خودتان میسازید؛ طول پیشنهادی یک قالب لزوماً طول قیمتدار هر مدل نیست، پس طولهای مجاز را از جدول «مدلها و قیمت» بردارید.
محصول
معرفی محصول روی سکوی استودیو
چرخش آرام و سینمایی دوربین دور محصول شما روی یک سکوی استودیویی با نور نرم؛ مناسب معرفی محصول و ویدیوهای تبلیغاتی.
۸ ثانیهافقی۱۶:۹
محصول
ریل عمودی محصول
عکس محصول شما را به یک ریل عمودی و پرانرژی برای اینستاگرام و شبکههای اجتماعی تبدیل میکند: محصول آرام میچرخد و نور روی آن میلغزد. فقط از عکسی استفاده کنید که حق استفاده از آن را دارید.
۵ ثانیهعمودی۹:۱۶
غذا
نمای نزدیک غذا
نمای بسیار نزدیک و اشتهاآور از غذا یا نوشیدنی شما با بخار و نور گرم رستوران؛ مناسب منو و تبلیغ رستوران و کافه.
۵ ثانیهعمودی۹:۱۶
املاک
تور ملک
یک تور روان و آرام در فضای داخلی ملک با پنجرههای بزرگ و نور طلایی غروب؛ مناسب معرفی ملک و آگهیهای املاک.
۸ ثانیهافقی۱۶:۹
سفر
طبیعت سینمایی
نمای هوایی سینمایی از طبیعت در طلوع آفتاب با مه ملایم؛ مناسب گردشگری، اقامتگاهها و محتوای سفر.
۸ ثانیهافقی۱۶:۹
جانبخشی به عکس
جانبخشی به عکس
به عکس شما با حرکتی ظریف و طبیعی و نزدیکشدن آرام دوربین جان میبخشد؛ سوژه و سبک اصلی عکس تا حد امکان حفظ میشود. فقط از عکسی استفاده کنید که حق استفاده از آن را دارید.
۵ ثانیهافقی۱۶:۹
سایر
قبل و بعد
گذار نرم از تصویر «قبل» به تصویر «بعد» با دوربین ثابت؛ مناسب پروژههای بازسازی و دکوراسیون، آرایش و تغییر استایل. هر دو تصویر را از یک زاویه و با قاب مشابه بگیرید و فقط از عکسهایی استفاده کنید که حق استفاده از آنها را دارید.
۸ ثانیهافقی۱۶:۹
آموزش
انیمیشن آموزشی ساده
انیمیشن سهبعدی ساده با اشکال هندسی و رنگهای ملایم برای نمایش تصویری یک موضوع آموزشی. ویدیو بدون نوشته ساخته میشود؛ برای توضیح کامل، متن یا موسیقی را در بخش تدوین اضافه کنید.
۸ ثانیهافقی۱۶:۹
مد
لوکبوک مد
یک مدل (ساختهشده با هوش مصنوعی) با لباس شما روی یک رانوی مینیمال به سمت دوربین قدم میزند؛ مناسب لوکبوک و معرفی کالکشن. لباس را روی زمینهای ساده و با نور یکنواخت عکس بگیرید و فقط از عکسی استفاده کنید که حق استفاده از آن را دارید.
۵ ثانیهعمودی۹:۱۶
سفر
تایملپس شهر
تایملپس افق شهر دلخواه شما از عصر تا شب، با روشن شدن چراغها و حرکت سریع ابرها.
۸ ثانیهافقی۱۶:۹
شناسهٔ یکتای درخواست (Idempotency-Key)
هدر اختیاری Idempotency-Key (یک بار در درخواست، ۱ تا ۱۲۰ نویسهٔ قابلنمایش ASCII، بدون فاصله) جلوی ساخت و حساب شدن دوبارهٔ یک درخواست تکراری را میگیرد: اگر همان کلید را با همان درخواست دوباره بفرستید، همان ویدیوی ساختهشده برمیگردد و چیزی دوباره ساخته یا کسر نمیشود؛ همان کلید با درخواست متفاوت ۴۰۹ با Video.IdempotencyKeyReused میگیرد. بدون کلید تکرار تشخیص داده نمیشود و درخواست تکراری یک ویدیوی پولی دیگر میسازد. SDKهای رسمی OpenAI خودشان کلید میفرستند و در تکرارهای خودکارشان همان را نگه میدارند؛ برای کلاینت HTTP خودتان یک کلید تصادفی (مثلاً UUID) بسازید و فقط برای تکرار همان درخواست از آن استفاده کنید.
چطور توصیف بنویسم؟
توصیف فارسی پذیرفته میشود، اما مدلهای ویدیو معمولاً توصیف انگلیسی را دقیقتر دنبال میکنند؛ اگر نتیجه آنطور که میخواستید نبود، همان توصیف را انگلیسی بنویسید. این توصیه است، نه الزام. سقف طول توصیف هر مدل در پروفایلش آمده؛ بلندتر از آن ۴۰۰ با Video.PromptTooLong میگیرد.
از مدل نخواهید متنی روی تصویر بنویسد. مدلهای ویدیو متن فارسی را معمولاً درست نمینویسند و جارویس هم هرگز از مدل نمیخواهد متنی روی ویدیو بنویسد؛ کپشن، شعار و نام برند را بعد از ساخت روی ویدیو بگذارید. افزودن کپشن فارسی در ویرایشگر استودیوی جارویس («تدوین») بهزودی اضافه میشود؛ تا آن زمان آن را با ابزار تدوین خودتان اضافه کنید.
تفاوت با API ویدیوی OpenAI
image_url فقط data: URL است؛ نشانی https گرفته نمیشود.
GET /v1/videos فقط ویدیوهای همین کلید را میدهد؛ ویدیوی کلید دیگر هرگز نمیآید.
status چهار مقدار دارد؛ ویدیوی لغوشده، نتیجهٔ نامعلوم و خطای ذخیرهسازی هم failed با error.code خودشان میآیند.
DELETE ویدیوی در صف را لغو میکند، ویدیوی در حال ساخت را ۴۰۹ میدهد و ویدیوی پایانیافته را حذف میکند.
نسخهٔ ذخیرهشده تا مدت نگهداری در دسترس است (پیشفرض ۷ روز) و بعد 404 video_expired میدهد.
model کد مدل جارویس است و قیمت بهازای مدل و طول ثابت است.
user و metadata دور ریخته میشوند. remix، extend، thumbnail، spritesheet، file_id و تبدیل ویدیو به ویدیو (input_video) در دسترس نیست و رویداد (webhook) پایان ساخت هم نداریم؛ پیگیری با درخواست مکرر انجام میشود.
چه چیزی نگه داشته میشود؟
توصیف و تصویرهایی که میفرستید برای ساخت ویدیو به سرویس ویدیو میرسد؛ نتیجه در فضای ذخیرهسازی خصوصی و رمزگذاریشدهٔ جارویس میماند تا مدت نگهداری تمام شود یا شما DELETE کنید. مدت نگهداری قابل تنظیم است و زمان دقیق هر ویدیو در expires_at آمده است. جزئیات در سیاست حریم خصوصی آمده است.
قالب خطاها و مدیریت آنها
خطاهای این مسیر قالب OpenAI دارند: error.message، error.type، error.param و error.code. پیامها متن ثابت جارویساند و نه متن درخواست شما را تکرار میکنند و نه متن خطای سرویس ویدیو را. کد وضعیت HTTP واقعی است؛ جدول «خطاهای رایج» پایین همین صفحه علت هر کدام را میگوید. با SDK، یک ساخت ردشده استثنا میاندازد (۴۰۰ با e.param، ۴۲۹ با Retry-After)، ولی ویدیویی که پذیرفته شد و به پایان نرسید با status: "failed" برمیگردد:
Python · openai
import time
import openai
from openai import OpenAI
client = OpenAI(
base_url="https://api.jarvis.you/v1",
api_key="pmai_xxxxxxxxxxxxxxxxxxxx",
)
try:
video = client.videos.create_and_poll(
model="VEO_3_1",
prompt="ویدیوی سینمایی از دریاچهای آرام در سپیدهدم، با مه نازکی روی آب",
seconds="8",
)
except openai.BadRequestError as e:
# 400: e.param names the field, e.code the reason (Video.DurationNotAvailable, Video.PromptTooLong, ...)
raise SystemExit(f"fix the request: {e.param} ({e.code})")
except openai.RateLimitError as e:
# 429: too many videos in progress, or the video service is busy; wait as long as Retry-After says
time.sleep(int(e.response.headers.get("retry-after", "15")))
raise
except openai.APIStatusError as e:
if e.status_code == 402:
raise SystemExit("not enough balance for this video")
raise
if video.status == "completed":
client.videos.download_content(video.id).write_to_file("video.mp4")
elif video.error and video.error.code == "storage_failed":
# made and charged, but not stored: send this id to support
print("contact support with", video.id)
elif video.error and video.error.code == "moderation":
# refused for content rules, and charged: change the prompt before trying again
print(video.error.message)
else:
print(video.error)
بررسی اتصال
رایگان: GET /v1/videos فهرست ویدیوهای همین کلید را میدهد (برای کلید تازه خالی است) و هزینه ندارد؛ پس هم کلید را میآزماید هم آدرس پایه را. ساخت واقعی قیمت ثابت دارد (جدول «مدلها و قیمت»)؛ برای آزمایش، کوتاهترین طول قیمتدار را بفرستید.
درخواست نامعتبر. error.param فیلد مشکلدار را میگوید و error.code دلیل را: Video.InvalidRequest (فیلد ناقص یا تکراری، تصویر نامعتبر، نشانی https بهجای تصویر)، Video.UnsupportedParameter (فیلدی که این مسیر نمیشناسد)، Video.DurationNotAvailable (طولی که قیمت ندارد؛ پیام طولهای مجاز را میگوید)، Video.PromptTooLong، Video.ModelNotAvailable (مدل ناشناخته است، ویدیو نیست، در پلن شما نیست یا قیمت ندارد) و ناسازگاری نسبت تصویر، اندازه، تعداد تصویر مرجع، فریم پایانی یا کیفیت با مدل. هزینهای ثبت نمیشود.
۴۰۱
کلید ارسال نشده یا نامعتبر است؛ آن را در Authorization: Bearer یا x-api-key بفرستید. توکن ورود به کنسول جای کلید API را نمیگیرد.
۴۰۲
موجودی توکن، سقف یا بودجهٔ همین کلید برای قیمت ثابت این ویدیو کافی نیست (Video.InsufficientFunds). چیزی کنار گذاشته نمیشود.
۴۰۳
مدل در پلن این کلید مجاز نیست (param: model)، اشتراک فعال ندارید، یا حساب یا تیم غیرفعال است.
۴۰۴
video_not_found: چنین ویدیویی نیست، شناسه نادرست است، ویدیو حذف شده، یا ویدیوی کلید دیگری است؛ ویدیوی کلید دیگر، حتی از همان حساب، عمداً مثل شناسهٔ ناموجود جواب میدهد. Video.ContentNotFound: ویدیو هنوز completed نشده و چیزی برای دانلود نیست. video_expired: نسخهٔ ذخیرهشده پس از مدت نگهداری حذف شده است.
۴۰۸ / ۴۱۳ / ۴۱۵
۴۰۸: ارسال درخواست بیش از حد طول کشید (معمولاً تصویر زیاد روی اتصال کند). ۴۱۳: مجموع تصویرها (Video.ReferencesTooLarge) یا کل درخواست (Gateway.RequestTooLarge) از سقف بزرگتر است؛ تصویر کمتر یا کوچکتر بفرستید. ۴۱۵: فقط application/json و multipart/form-data پذیرفته میشود.
۴۰۹
Video.StorageQuotaExceeded: فضای ذخیرهسازی شما پر است؛ ویدیوهای قدیمی را حذف و دوباره بفرستید (پیش از آن چیزی کسر نشده است). Video.IdempotencyKeyReused: همین Idempotency-Key با درخواست دیگری آمده بود. not_cancellable: ویدیو در حال ساخت یا ذخیره است و دیگر لغو نمیشود.
۴۲۲
Video.ProviderRefused: سرویس ویدیو همان لحظهٔ ارسال، درخواست را نپذیرفت. چیزی ساخته نشد و هزینهای کسر نمیشود؛ درخواست را اصلاح کنید.
۴۲۹
Video.TooManyInFlight: ویدیوهای در حال ساخت همین کلید به سقف رسیدهاند (Retry-After: 15). Video.Busy: سرویس ویدیو اکنون ظرفیت ندارد (Retry-After: 10). Video.UpstreamBusy: سرویس ویدیو درخواستها را محدود کرده است (Retry-After: 15). مقدار Retry-After را رعایت کنید؛ هزینهای کسر نمیشود، ولی ارسال دوباره یک درخواست تازه است.
۵۰۰ / ۵۰۲ / ۵۰۳ / ۵۰۴
۵۰۲ (Video.ProviderUnavailable): مسیر جارویس به سرویس ویدیو اکنون در دسترس نیست؛ هرگز به معنای مشکل کلید یا موجودی شما نیست. ۵۰۳: Video.NotSent (چیزی فرستاده نشد؛ Retry-After: 5)، یا Video.ApiDisabled (ساخت ویدیو با API در این محیط فعال نیست). ۵۰۴ (Video.OutcomeUnknown): سرویس ویدیو پاسخ نداد و معلوم نیست ویدیو ساخته شده یا نه؛ هزینهای کسر نمیشود، جارویس هرگز آن را خودکار دوباره نمیفرستد و شما هم خودکار دوباره نفرستید. اگر ویدیو ساخته شده باشد، پشتیبانی پیگیری میکند. ۵۰۰: خطای غیرمنتظره. هیچکدام از اینها هزینه ندارد.
پردازش دستهای
با پردازش دستهای تا ۵۰٬۰۰۰ درخواست را در یک فایل میفرستید و نتیجه را بعداً میگیرید. جارویس API دستهٔ OpenAI را ارائه میدهد (/v1/files و /v1/batches)؛ SDK رسمی OpenAI فقط با تنظیم آدرس پایه و کلید کار میکند. درخواستها را در یک فایل JSONL مینویسید، فایل را بارگذاری میکنید، دسته میسازید، وضعیتش را پیگیری میکنید و وقتی completed شد، فایل نتیجه را دانلود میکنید. این روش برای کارهای بزرگی است که پاسخ فوری نمیخواهند، مثل خلاصهسازی، ترجمه، دستهبندی یا ساخت Embedding برای مجموعهای از سندها. تخفیف ندارد: بدون تخفیف؛ هر خط با قیمت عادی.
پشتیبانیشده
چهار مسیر: /v1/chat/completions، /v1/responses، /v1/embeddings و /v1/messages. هر دسته یک مسیر دارد و همان url همهٔ خطهای فایل است.
SDK رسمی OpenAI برای Python و Node.js (files.create، batches.create، batches.retrieve، files.content، batches.cancel) و هر کلاینت HTTP.
چند مدل در یک فایل (تا ۶۴ نوشتار مختلف از نام مدل)، به شرط آنکه همه از یک خانواده باشند: یا همه Claude یا هیچکدام.
بررسی خطبهخط هنگام بارگذاری: خط نامعتبر همان لحظه ۴۰۰ با شمارهٔ خط میگیرد، نه دستهای که ساعتی بعد ناموفق شود.
هزینهٔ هر خط جدا و از روی مصرف واقعی خودش در سوابق مصرف ثبت میشود.
محدودیتها و نکتهها
بدون تخفیف؛ هر خط با قیمت عادی. برآورد حداکثر هزینه هنگام ساخت دسته نگه داشته میشود و پس از پایان، فقط مصرف واقعی کسر میشود (بخش «هزینه چطور حساب میشود؟»).
ظرفیت پردازش دستهای بین همهٔ کاربران مشترک است؛ ممکن است در صف بمانید. دسته ممکن است پیش از شروع منتظر بماند و فایل بزرگ ممکن است در ۲۴ ساعت تمام نشود (بخش «ظرفیت مشترک و صف»).
همهٔ مدلها در پردازش دستهای کار نمیکنند. مدلی که پشتیبانی نشود ۴۰۰ با Batch.ModelNotSupported و شمارهٔ خط میگیرد، پیش از آنکه چیزی ذخیره یا حساب شود.
مهلت اجرا ۲۴ ساعت است و فایلها و نتیجهها ۷ روز نگه داشته میشوند؛ پس از آن ۴۰۴ میدهند، پس نتیجه را بهموقع دانلود کنید.
بارگذاری موجودی مثبت میخواهد، ولی ساخت دسته باید کل برآورد حداکثر را بتواند نگه دارد؛ این از شرط «موجودی مثبت» سختگیرانهتر است.
پیشنیازها
یک کلید pmai_
پلنی که مدلهای فایل را شامل شود، موجودی مثبت برای بارگذاری و موجودی و سقف کلید کافی برای برآورد حداکثر هنگام ساخت دسته
بستهٔ openai (Python یا Node.js) برای نمونههای SDK؛ برای بقیه فقط cURL یا PowerShell
مراحل
۱
کلید و آدرس پایه را در متغیرهای محیطی بگذارید (نمونه برای Windows PowerShell، macOS و Linux در پایین آمده است).
۲
درخواستها را در فایل requests.jsonl بنویسید، هر درخواست در یک خط و همه با یک url.
۳
POST /v1/files را با purpose=batch بفرستید. پاسخ شیء فایل است و id آن را میگیرید.
۴
POST /v1/batches را با input_file_id و endpoint (برابر url خطها) بفرستید و id دسته را بگیرید.
۵
GET /v1/batches/{id} را تکرار کنید تا status به completed (یا failed، expired، cancelled) برسد.
۶
فایلهای output_file_id و error_file_id را با GET /v1/files/{id}/content پیش از ۷ روز دانلود کنید.
متغیرهای محیطی
SDKهای رسمی OpenAI و نمونههای PowerShell این دو متغیر را میخوانند. هر جلسهٔ ترمینال تازه باید دوباره آنها را داشته باشد، مگر در تنظیمات سیستمعامل یا فایل پروفایل شل ثبتشان کنید.
فایل ورودی متن UTF-8 است و هر خط آن یک شیء JSON، یعنی یک درخواست. خط خالی نادیده گرفته میشود، ولی در شمارش خطها میآید؛ پس شمارهٔ خطی که در یک خطا میخوانید همان شمارهٔ خط ویرایشگر شماست. هر خط با \n یا \r\n تمام میشود.
اعضای هر خط فایل JSONL و قاعدهٔ هر کدام
عضو
قاعده
custom_id
الزامی. رشتهٔ غیرخالی تا ۵۱۲ نویسه که در همان فایل یکتاست. نتیجهها را با آن به درخواستهایتان برمیگردانید.
method
الزامی. همیشه "POST".
url
الزامی. یکی از /v1/chat/completions، /v1/responses، /v1/embeddings و /v1/messages. باید با endpoint هنگام ساخت دسته یکی باشد؛ پس همهٔ خطهای یک فایل یک url دارند.
body
الزامی. بدنهٔ درخواست، همانطور که مستقیم به آن مسیر میفرستادید. model الزامی است.
JSONL · requests.jsonl
{"custom_id": "review-1", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "GPT_5_6_SOL", "messages": [{"role": "system", "content": "نظر مشتری را فقط با یکی از برچسبهای مثبت، منفی یا خنثی دستهبندی کن"}, {"role": "user", "content": "ارسال سریع بود و بستهبندی عالی"}], "max_tokens": 20}}
{"custom_id": "review-2", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "GPT_5_6_SOL", "messages": [{"role": "system", "content": "نظر مشتری را فقط با یکی از برچسبهای مثبت، منفی یا خنثی دستهبندی کن"}, {"role": "user", "content": "کالا با توضیحات فروشنده تفاوت داشت"}], "max_tokens": 20}}
{"custom_id": "review-3", "method": "POST", "url": "/v1/chat/completions", "body": {"model": "GPT_5_6_SOL", "messages": [{"role": "system", "content": "نظر مشتری را فقط با یکی از برچسبهای مثبت، منفی یا خنثی دستهبندی کن"}, {"role": "user", "content": "هنوز فرصت نکردهام از آن استفاده کنم"}], "max_tokens": 20}}
نمونهٔ اول سه نظر مشتری را دستهبندی میکند؛ دومی فایل Embedding است، که در آن input یک رشته (یا آرایهای از رشتهها) است و آرایهٔ توکن، مثل POST /v1/embeddings، ۴۰۰ میگیرد. GPT_5_6_SOL فقط نمونه است: کد مدل را از GET /v1/models بردارید (بخش «مدلها در پردازش دستهای»). عضو دیگری در خط پذیرفته نمیشود، هر عضو فقط یکبار میآید و نام عضوها به حروف بزرگ و کوچک حساس است؛ مثلاً Model ۴۰۰ میگیرد و املای درست را میگوید.
جارویس در خطهای شما فقط اینها را عوض میکند: body.model را به نام مدل نزد ارائهدهنده، body.stream را به false (دسته جریانی نیست) و، اگر نوشته باشید، saveToHistory: false را برمیدارد. باقی بدنه بایتبهبایت میرود.
مدلها در پردازش دستهای
کد مدل را در body.model مینویسید، مثل درخواست مستقیم؛ مدلهای مجاز کلید در GET /v1/models است. هر خط با همان قواعد درخواست مستقیم بررسی میشود (پلن کلید، توانایی مسیر خط، موجودی مثبت و برای Embedding قیمت مدل) و بعد از آن باید مدل برای پردازش دستهای هم عرضه شده باشد. سه قید دارد:
همهٔ مدلهای کاتالوگ در پردازش دستهای نیستند. مدلی که نیست Batch.ModelNotSupported با param: body.model و شمارهٔ خط میگیرد و چیزی ذخیره یا حساب نمیشود. فهرست جداگانهای از مدلهای دستهای منتشر نمیشود؛ سادهترین راه آزمایش بارگذاری یک فایل کوچک است، که هزینه ندارد.
در هر فایل یک خانوادهٔ مدل. یا همهٔ مدلهای فایل Claude باشند یا هیچکدام. خط اول تصمیم میگیرد و خطی از خانوادهٔ دیگر ۴۰۰ با Batch.MixedKeyFamilies و شمارهٔ هر دو خط میگیرد. برای مدلهای Claude و غیر Claude دو فایل و دو دسته بسازید. یک فایل تا ۶۴ نوشتار مختلف از نام مدل میپذیرد (هر املا یک نوشتار است).
همهٔ مدلهای یک دسته با یک اشتراک پرداخت میشوند. اگر دو مدل فایل به دو اشتراک مختلف کلید بخورند، ساخت دسته ۴۰۳ میگیرد و میگوید فایل را بهتفکیک مدل جدا کنید.
ساخت فایل از CSV
اگر دادهتان در CSV است، یک اسکریپت کوتاه فایل JSONL را میسازد. نمونه فرض میکند فایل reviews.csv (UTF-8؛ فارسی مشکلی ندارد) ستونهای id و review را دارد. id همان custom_id میشود، پس باید در فایل یکتا باشد.
Python · CSV → JSONL
import csv
import json
# reviews.csv is UTF-8 with the columns id and review
SYSTEM = "نظر مشتری را فقط با یکی از برچسبهای مثبت، منفی یا خنثی دستهبندی کن"
with open("reviews.csv", newline="", encoding="utf-8-sig") as src, open(
"requests.jsonl", "w", encoding="utf-8"
) as out:
for row in csv.DictReader(src):
request = {
"custom_id": row["id"], # unique in the file, up to 512 characters
"method": "POST",
"url": "/v1/chat/completions",
"body": {
"model": "GPT_5_6_SOL",
"messages": [
{"role": "system", "content": SYSTEM},
{"role": "user", "content": row["review"]},
],
"max_tokens": 20,
},
}
out.write(json.dumps(request, ensure_ascii=False) + "\n")
ensure_ascii=False متن فارسی را همانطور که هست مینویسد؛ بدون آن هر نویسه بهصورت \uXXXX میآید و فایل بزرگتر میشود. utf-8-sig نویسهٔ BOM را که Excel در ابتدای فایل CSV میگذارد حذف میکند.
بارگذاری فایل
POST /v1/files یک فرم multipart/form-data میگیرد: purpose با مقدار batch و یک file. فایل هنگام رسیدن خطبهخط بررسی میشود؛ پس خط نامعتبر همان لحظه ۴۰۰ میگیرد و هیچچیز ذخیره نمیشود. بارگذاری هزینه ندارد، ولی موجودی مثبت میخواهد.
نمونهٔ cURL برای bash و zsh (macOS و Linux) است. در Windows PowerShell دستور curl نام مستعار Invoke-WebRequest است و \ خط را ادامه نمیدهد؛ تب PowerShell از curl.exe (همان curl واقعی که با ویندوز میآید) استفاده میکند، چون Invoke-RestMethod -Form فقط در PowerShell 7 هست.
bytes اندازهٔ فایل ذخیرهشده است و ممکن است با فایل شما فرق کند، چون نام مدلها بازنویسی میشود. status همیشه processed است، چون بررسی هنگام بارگذاری انجام شد. نام فایل شما (آخرین بخش مسیر، تا ۲۰۰ نویسه) نگه داشته میشود و فایل تا expires_at، یعنی ۷ روز، میماند.
اگر خطی نامعتبر باشد، پاسخ ۴۰۰ است و line شمارهٔ همان خط در فایل شماست. نمونه برای فایلی که در آن خط سوم همان custom_id خط اول را دارد:
JSON · خطای ۴۰۰
{
"error": {
"message": "Line 3: custom_id is already used by line 1. Every custom_id must be unique within the file.",
"type": "invalid_request_error",
"param": "custom_id",
"code": "Batch.InvalidRequestLine",
"line": 3
}
}
خطا را در فایل اصلاح کنید و کل فایل را دوباره بفرستید؛ از بارگذاری ردشده چیزی نمیماند.
ساخت دسته
POST /v1/batches یک بدنهٔ JSON میگیرد. هنگام ساخت، برآورد حداکثر هزینهٔ فایل کنار گذاشته میشود (بخش «هزینه چطور حساب میشود؟»)؛ پس موجودی و سقف کلید باید آن را بپوشاند.
cURL
# keep the Idempotency-Key and send it again to retry this exact request: a retry never makes a second batch
curl https://api.jarvis.you/v1/batches \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: reviews-october-1" \
-d '{
"input_file_id": "file-0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"endpoint": "/v1/chat/completions",
"completion_window": "24h",
"metadata": {"job": "reviews-october"}
}'
فیلدهای بدنهٔ POST /v1/batches، هدر Idempotency-Key و قاعدهٔ هر کدام
فیلد
قاعده
input_file_id
الزامی. شناسهٔ فایلی که با purpose=batch بارگذاری کردهاید؛ فایل نتیجه نمیشود.
endpoint
الزامی. یکی از چهار مسیر و برابر url همهٔ خطهای فایل؛ وگرنه ۴۰۰ با Batch.EndpointMismatch که urlهای فایل را میگوید.
completion_window
اختیاری. فقط "24h".
metadata
اختیاری. تا ۱۶ جفت رشته؛ کلید ۱ تا ۶۴ نویسه و بدون شروع با $، مقدار تا ۵۱۲ نویسه. جارویس آن را رمزگذاریشده نگه میدارد، فقط برای شما برمیگرداند و هرگز برای ارائهدهنده نمیفرستد.
Idempotency-Key
هدر اختیاری، ولی بهتر است همیشه بدهید (جعبهٔ پایین).
ساخت دسته این مراحل را به ترتیب میگذراند؛ هر مرحلهای که رد شود، مراحل بعد اجرا نمیشود و چیزی کنار گذاشته یا حساب نمیشود:
Idempotency-Key، اگر داده باشید: همان کلید با همان درخواست، همان دستهٔ اول را برمیگرداند.
فایل مال شماست، از نوع فایل ورودی است و هنوز موجود است (وگرنه ۴۰۴ یا ۴۰۰).
endpoint با url فایل یکی است.
پلن کلیدی که دسته را میسازد همهٔ مدلهای فایل را شامل میشود. فایل پیشتر با کلید بارگذارنده سنجیده شده بود، ولی دو کلید یک حساب ممکن است پلنهای متفاوت داشته باشند (۴۰۳).
از سقف دستههای ناتمام نگذشتهاید: بهطور پیشفرض ۵ دستهٔ ناتمام برای هر حساب (یا تیم)، روی هم از همهٔ کلیدها (۴۲۹ با Retry-After: 60).
موجودی و سقف کلید برآورد حداکثر را میپوشاند و کنار گذاشته میشود (۴۰۲ در غیر این صورت).
دسته ثبت میشود و جارویس همان لحظه تلاش میکند آن را به ارائهدهنده بسپارد. پاسخ همیشه شیء دسته است: validating، چه سپرده شده باشد چه در صف جارویس منتظر ظرفیت بماند.
نمونهٔ پاسخ برای دستهای که در صف جارویس منتظر مانده است (شناسه و زمانها ساختگیاند):
هدر اختیاری Idempotency-Key (یک بار در درخواست، ۱ تا ۱۲۰ نویسهٔ قابلنمایش ASCII) جلوی ساخته و نگهداشته شدن دوبارهٔ یک دسته را میگیرد: همان کلید با همان درخواست (فایل، مسیر و metadata) همان دستهای را برمیگرداند که بار اول ساخته شد، حتی اگر در این فاصله فایل حذف شده یا موجودی خرج شده باشد؛ همان کلید با درخواست دیگر ۴۰۹ با Batch.IdempotencyKeyReused میگیرد. کلیدها برای هر حساب جدایند. بدون کلید تکرار تشخیص داده نمیشود: اگر پاسخ ساخت گم شود و دوباره بفرستید، دستهٔ دیگری با برآورد نگهداشتهشدهٔ دیگری ساخته میشود. برای هر دستهای که میخواهید بسازید یک کلید بنویسید و فقط برای تکرار همان درخواست از همان استفاده کنید. SDKهای رسمی OpenAI خودشان کلید میفرستند و در تکرارهای خودکارشان همان را نگه میدارند؛ برای تکرار از طرف برنامهٔ خودتان کلید خودتان را بدهید.
وضعیت و پیگیری
GET /v1/batches/{id} را تکرار کنید تا status به یکی از چهار حالت پایانی برسد: completed، failed، expired یا cancelled. شمارش request_counts را ارائهدهنده میدهد و حدود هر ۳۰ ثانیه تازه میشود؛ پس پرسیدن هر ۳۰ تا ۶۰ ثانیه کافی است و پرسیدن بیشتر فقط همان پاسخ را تکرار میکند. هر پیگیری رایگان است و مصرف توکن ندارد.
مقدارهای status دسته، معنی هرکدام و کاری که باید بکنید
status
معنی
کار شما
validating
در صف جارویس منتظر ظرفیت است (آنگاه عضو jarvis_queue را دارد)، یا به ارائهدهنده سپرده میشود و او آن را بررسی میکند.
منتظر بمانید. در این وضعیت میتوانید لغو کنید.
in_progress
ارائهدهنده خطها را اجرا میکند.
منتظر بمانید؛ request_counts پیشرفت را نشان میدهد.
finalizing
ارائهدهنده نتیجه را مینویسد، یا کارش را تمام کرده و جارویس هزینهٔ خطها را ثبت میکند و فایلهای نتیجه را میسازد.
منتظر بمانید. هنوز فایل نتیجهای در دسترس نیست.
completed
تمام شد؛ هزینهٔ خطها ثبت شده و فایلهای نتیجه ساخته شدهاند.
فایلها را دانلود کنید.
failed
دسته شروع نشد (فایل برای آن مسیر درست نیست، ارائهدهنده آن را نپذیرفت، یا بیش از حد در صف ماند). علت در errors است. هزینهای کسر نمیشود.
علت را بخوانید، فایل را اصلاح و دوباره بارگذاری کنید و دستهٔ تازه بسازید.
expired
مهلت ۲۴ ساعت تمام شد و همهٔ خطها نوبتشان نرسید. ممکن است نتیجهٔ خطهایی که اجرا شدند در فایل نتیجه باشد.
نتیجه را دانلود کنید و باقیمانده را در دستهٔ تازه بفرستید.
cancelling
لغو درخواست شده و خطهای در حال اجرا تمام میشوند.
منتظر بمانید.
cancelled
لغو شد. خطهایی که اجرا شده بودند حساب میشوند و ممکن است نتیجهشان در فایل نتیجه باشد.
در صورت نیاز نتیجه را دانلود کنید.
cURL
# repeat about once a minute until "status" is completed, failed, expired or cancelled
curl https://api.jarvis.you/v1/batches/batch_0a1b2c3d4e5f60718293a4b5c6d7e8f9 \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx"
completed فقط وقتی میآید که هزینهٔ خطها ثبت شده و فایلهای نتیجه ساخته شده باشند؛ تا آن وقت finalizing میبینید. حلقهای که با completed سراغ فایل میرود، فایل را پیدا میکند. دستهٔ تمامشده (فایل خطا فقط وقتی هست که دستکم یک خط شکست خورده باشد):
output_file_id خطهایی را میدهد که موفق شدند و error_file_id خطهایی را که شکست خوردند (اگر خطی شکست نخورده باشد null است). هر دو فایل با GET /v1/files/{id}/content دانلود میشوند و در GET /v1/files با purpose برابر batch_output و batch_error فهرست میشوند. ترتیب خطهای نتیجه را فرض نکنید: هر نتیجه را با custom_id به درخواستش وصل کنید.
cURL
# the lines that succeeded
curl https://api.jarvis.you/v1/files/file-aaaabbbbccccddddeeeeffff00001111/content \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx" \
-o output.jsonl
# the lines that failed (there is no error file when none did)
curl https://api.jarvis.you/v1/files/file-22223333444455556666777788889999/content \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx" \
-o errors.jsonl
یک خط output.jsonl در قالب نتیجهٔ دستهٔ OpenAI است. response.body همان است که مسیر به درخواست مستقیم میداد، با usage، و model در آن همان نامی است که خودتان نوشتید، نه نام نزد ارائهدهنده (شناسهها و عددها ساختگیاند):
خطی که هیچوقت پاسخ نگرفت، مثلاً چون مهلت ۲۴ ساعت پیش از نوبتش تمام شد، در errors.jsonl است و response: null و یک error دارد؛ خطی که اجرا شد و شکست خورد، وضعیت و بدنهٔ واقعی خطا را در response دارد:
دانلود همیشه کل فایل را با ۲۰۰ میدهد، بدون Content-Length؛ Range پشتیبانی نمیشود و هدرش نادیده گرفته میشود. اگر اتصال وسط دانلود قطع شود، دانلود شکست میخورد (هرگز ناقص و سالم تمام نمیشود)، پس کل فایل را دوباره بگیرید. فایلها پس از ۷ روز ۴۰۴ Batch.FileNotFound میدهند.
لغو دسته و حذف فایل
POST /v1/batches/{id}/cancel بسته به وضعیت دسته کار متفاوتی میکند و پاسخش شیء دسته است:
نتیجهٔ لغو برای هر وضعیت دسته
وضعیت دسته
نتیجه
در صف جارویس
بیدرنگ cancelled میشود. چیزی به ارائهدهنده نرفته، برآورد نگهداشتهشده آزاد میشود و هزینهای کسر نمیشود.
نزد ارائهدهنده
cancelling؛ خطهایی که در حال اجرا بودند تمام میشوند و حساب میشوند، بقیه اجرا نمیشوند، و بعد cancelled میشود. اگر ارائهدهنده لغو را تأیید نکند، دسته همانطور که بود میماند و ۴۲۹، ۵۰۲ یا ۵۰۳ میگیرید.
completed / failed / expired / cancelled
۴۰۹ با Batch.NotCancellable.
همین لحظه در حال سپردهشدن به ارائهدهنده
۴۰۹ با Batch.NotCancellable و Retry-After: 5؛ چند ثانیه بعد دوباره امتحان کنید.
cURL · cancel
curl -X POST https://api.jarvis.you/v1/batches/batch_0a1b2c3d4e5f60718293a4b5c6d7e8f9/cancel \
-H "Authorization: Bearer pmai_xxxxxxxxxxxxxxxxxxxx"
DELETE /v1/files/{id} فایل را حذف میکند و فقط وقتی deleted: true میدهد که واقعاً حذف شده باشد؛ اگر ارائهدهنده در دسترس نباشد چیزی حذف نمیشود و خطا میگیرید. فایل ورودی دستهای که هنوز تمام نشده ۴۰۹ با Batch.FileInUse میگیرد. حذف فایل هزینهای را برنمیگرداند. فایلهای بیاستفاده را حذف کنید تا سقف فضای حسابتان پر نشود.
ظرفیت پردازش دستهای بین همهٔ کاربران مشترک است؛ ممکن است در صف بمانید. ارائهدهنده تعداد دستههای همزمان، تعداد خطهای در حال اجرا و حجم فایلها را برای کل جارویس محدود کرده است و همهٔ مشتریان یک ظرفیت را بین خود تقسیم میکنند. طبق اعلام ارائهدهنده، در حال حاضر فقط ۲ خط همزمان اجرا میشود، یعنی برای همهٔ کاربران روی هم حدود ۱٬۴۰۰ خط کوتاه در ساعت؛ این عدد را خودمان اندازه نگرفتهایم و ممکن است عوض شود. پس فایل بزرگ ممکن است در ۲۴ ساعت تمام نشود.
جارویس پیش از ارائهدهنده یک صف دارد تا یک مشتری همهٔ ظرفیت را نگیرد: نوبت میان حسابها میچرخد و در هر حساب هر دسته که زودتر ساخته شده زودتر شروع میشود؛ هر حساب بهطور پیشفرض همزمان حداکثر ۲ دسته را نزد ارائهدهنده دارد. تا نوبتتان نرسیده status همان validating است و jarvis_queue.position جایتان را میگوید (از ۱) و jarvis_queue.estimated_start زمان تقریبی شروع (ثانیهٔ یونیکس). این یک برآورد است، نه قول: ارائهدهنده ظرفیتش را بین همه تقسیم میکند و هیچکس نمیتواند زمان دقیق بدهد.
مهلت ۲۴ ساعت از لحظهای شروع میشود که ارائهدهنده دسته را میگیرد، نه از لحظهٔ ساخت؛ انتظار در صف جارویس جزو آن نیست. خطهایی که تا پایان مهلت نوبتشان نرسد اجرا نمیشوند و حساب نمیشوند. فایل بزرگ را به چند دسته تقسیم کنید تا بخش تمامشده زودتر به دستتان برسد و اگر دستهای منقضی شد، فقط باقیماندهٔ همان را دوباره بفرستید.
دستهای که بیش از ۱۲ ساعت در صف جارویس بماند ناموفق میشود: status میشود failed، در errors کد provider_capacity را میبینید، برآورد نگهداشتهشده آزاد میشود، هیچ هزینهای کسر نمیشود و اعلان میگیرید. دوباره دسته بسازید. (لغو دستهٔ در صف بیدرنگ انجام میشود.)
JSON · ناموفق
{
"id": "batch_0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"object": "batch",
"endpoint": "/v1/chat/completions",
"errors": {
"object": "list",
"data": [
{
"code": "provider_capacity",
"message": "The shared batch capacity did not free up in time, so the batch was not started. Nothing was charged.",
"param": null,
"line": null
}
]
},
"input_file_id": "file-0a1b2c3d4e5f60718293a4b5c6d7e8f9",
"completion_window": "24h",
"status": "failed",
"output_file_id": null,
"error_file_id": null,
"created_at": 1790000000,
"in_progress_at": null,
"expires_at": null,
"finalizing_at": null,
"completed_at": null,
"failed_at": 1790043200,
"expired_at": null,
"cancelling_at": null,
"cancelled_at": null,
"request_counts": {
"total": 3,
"completed": 0,
"failed": 0
},
"metadata": {
"job": "reviews-october"
}
}
هزینه چطور حساب میشود؟
بدون تخفیف؛ هر خط با قیمت عادی. هر خط همان قیمتی را دارد که اگر همان درخواست را مستقیم میفرستادید: برای مدل متنی بر پایهٔ توکن ورودی، کش و خروجی خود آن خط، و برای Embedding بر پایهٔ توکن ورودی و نرخ مدل در لحظهٔ ساخت دسته. برآورد حداکثر هزینه هنگام ساخت دسته نگه داشته میشود و پس از پایان، فقط مصرف واقعی کسر میشود. قاعدههای زیر قاعدهٔ حساب جارویس است.
هنگام ساخت دسته، برآورد حداکثر فایل کنار گذاشته میشود: برای هر خط، تخمین توکن ورودی بهعلاوهٔ سقف خروجی (max_tokens، max_completion_tokens یا max_output_tokens خود خط؛ اگر ندادید، بیشینهٔ خروجی مدل در کاتالوگ، و اگر آن هم نبود ۴٬۰۹۶ توکن). برای Embedding، تخمین توکن ورودی ضربدر نرخ مدل. تا پایان دسته این مقدار از موجودی شما کنار میماند و برای درخواست دیگری در دسترس نیست. max_tokens نزدیک به نیاز واقعی، برآورد را کوچکتر میکند.
این سختگیرانهتر از «موجودی مثبت» است. بارگذاری فقط موجودی مثبت میخواهد، ولی ساخت دسته باید کل برآورد را بتواند نگه دارد؛ وگرنه ۴۰۲ میگیرید و پیامش با «برآورد حداکثر N توکن» تمام میشود. دلیلش این است که مصرف واقعی بعد از پایان معلوم میشود و جارویس باید مطمئن باشد موجودی شما آن را میپوشاند.
در پایان، فایل نتیجه یکبار خوانده میشود و هر خط موفق (با پاسخ ۲xx) جدا و از روی usage خود همان خط حساب میشود. طبق قاعدهٔ جارویس، خطهای فایل خطا، یعنی خطی که پیش از پاسخ مدل شکست خورد یا اجرا نشد، حساب نمیشوند. خط موفقی که usage قابلاستفاده نداشته باشد از روی درخواست و پاسخ تخمین زده میشود و در سوابق مصرف «تخمینی» علامت میخورد.
برآورد سقف نیست. اگر پاسخها از آنچه برآورد شده بلندتر شوند، مصرف واقعی کسر میشود، حتی اگر از برآورد بیشتر باشد؛ بخشی که موجودی شما پوشش ندهد در مصرف شما بهصورت مازاد ثبت میشود و موجودی هرگز منفی نمیشود. اگر کمتر باشد، فقط مصرف واقعی کسر و بقیهٔ برآورد آزاد میشود.
بدون هزینه: دستهای که ناموفق شود، پیش از رسیدن به ارائهدهنده لغو شود یا همهٔ خطهایش شکست بخورد هیچ هزینهای ندارد و کل برآورد آزاد میشود. دستهای که وسط کار لغو شود یا منقضی شود، خطهایی را که اجرا شدهاند حساب میکند.
مثال فرضی: فایلی با ۱٬۰۰۰ درخواست که هرکدام حدود ۳۰۰ توکن ورودی و max_tokens: 200 دارند، برآوردی حدود ۵۰۰٬۰۰۰ توکن دارد و همان مقدار هنگام ساخت کنار گذاشته میشود. اگر ۹۹۰ خط پاسخ بگیرند و هرکدام حدود ۴۲۰ توکن مصرف کنند (۳۰۰ ورودی و ۱۲۰ خروجی) و ۱۰ خط شکست بخورند، ۴۱۵٬۸۰۰ توکن کسر میشود و بقیهٔ برآورد آزاد میشود.
چه کسی فایلها و دستهها را میبیند؟
فایلها و دستهها به حسابِ پرداختکنندهٔ کلیدی که آنها را ساخته تعلق دارند. کلید شخصی هر چیزی را میبیند که با هر کلید شخصی همان صاحب حساب ساخته شده؛ کلید تیمی هر چیزی را که با کلیدهای همان تیم ساخته شده. فایل یا دستهٔ حساب دیگر، شناسهٔ ناموجود و فایل منقضی همگی همان ۴۰۴ را میدهند، پس نمیشود فهمید شناسهای مال کس دیگر هست. فهرست و خواندن حتی با موجودی صفر کار میکند.
تفاوت با API دستهٔ OpenAI
تخفیف دستهای OpenAI در اینجا نیست: بدون تخفیف؛ هر خط با قیمت عادی.
شناسهٔ فایل و دسته مال جارویس است (file-… و batch_…) و شناسهٔ ارائهدهنده هرگز دیده نمیشود. output_file_id و error_file_id هم فایلهای جارویساند که در GET /v1/files فهرست میشوند.
فایل هنگام بارگذاری، نه هنگام شروع دسته، خطبهخط بررسی میشود (عضوها، مدل، پلن، خانواده و سقفها) و خطا شمارهٔ خط را دارد. purpose فقط batch است و completion_window فقط 24h.
فقط مدلهایی که برای پردازش دستهای عرضه شدهاند، و در هر فایل یک خانوادهٔ مدل (Claude یا غیر Claude).
نام مدل بازنویسی میشود: body.model در فایلی که نزد ارائهدهنده است نام خود او میشود و stream همیشه false است؛ ولی در دانلود فایل ورودی و فایلهای نتیجه نام مدل همان است که شما نوشتید. دانلود فایل ورودی همان را میدهد که ارائهدهنده دارد (با stream: false)، نه بایتهای اصلی شما؛ جارویس نسخهٔ اصلی را نگه نمیدارد.
دانلود فایل همیشه کل فایل را با ۲۰۰ میدهد؛ Range پشتیبانی نمیشود.
ساخت دسته پیش از هر چیز بررسی و برآورد حداکثر هزینهاش نگه داشته میشود؛ این از «موجودی مثبت» سختگیرانهتر است.
دسته میتواند پیش از ارائهدهنده در صف جارویس بماند: status میشود validating و عضو افزودهٔ jarvis_queue را دارد. completed فقط پس از ثبت هزینهٔ خطها و ساختهشدن فایلهای نتیجه میآید؛ تا آن وقت finalizing است.
metadata رمزگذاریشده نزد جارویس میماند و هرگز برای ارائهدهنده فرستاده نمیشود.
دستههای ناتمام و فضای فایلها برای هر حساب سقف دارند و ظرفیت اجرا مشترک است (جدول «سقفها» و جعبهٔ «ظرفیت مشترک و صف»).
چه چیزی نگه داشته میشود؟
فایل شما همانطور که نوشتهاید (با نام مدل بازنویسیشده) برای پردازش به ارائهدهندهٔ مدل یا سرویس واسط او فرستاده میشود و او آن را تا ۷ روز نگه میدارد (طبق اعلام خود او؛ سیاست او را خودش تعیین میکند). نتایج ۷ روز نگه داشته میشود؛ پس از آن جارویس هم دیگر فایل و نتیجه را در اختیار شما نمیگذارد. جارویس بایتهای فایل و نتیجه را نگه نمیدارد: فقط نام فایل و metadata دسته (رمزگذاریشده)، شمارشها، فهرست مدلها و سوابق هزینه ثبت میشود. جزئیات در سیاست حریم خصوصی آمده است.
قالب خطاها و مدیریت آنها
خطاهای این مسیرها قالب OpenAI دارند: error.message، error.type، error.param و error.code، و برای خطای یک خط از فایل، عضو افزودهٔ line. پیامها متن ثابت جارویساند و هرگز متن درخواست شما، نام فایل، custom_id یا متن خطای ارائهدهنده را تکرار نمیکنند. کد وضعیت HTTP واقعی است؛ جدول «خطاهای رایج» پایین همین صفحه علت هر کدام را میگوید. با SDK، بارگذاری یا ساختی که رد شود استثنا میاندازد (۴۰۰ با e.param، ۴۲۹ با Retry-After)، ولی دستهای که پذیرفته شد و اجرا نشد با status: "failed" و errors برمیگردد:
Python · openai
import time
import openai
from openai import OpenAI
client = OpenAI(
base_url="https://api.jarvis.you/v1",
api_key="pmai_xxxxxxxxxxxxxxxxxxxx",
)
try:
with open("requests.jsonl", "rb") as f:
file = client.files.create(file=f, purpose="batch")
batch = client.batches.create(
input_file_id=file.id,
endpoint="/v1/chat/completions",
completion_window="24h",
extra_headers={"Idempotency-Key": "reviews-october-1"},
)
except openai.BadRequestError as e:
# 400: e.param names the field; for a line of the file the body also has "line"
line = e.body.get("line") if isinstance(e.body, dict) else None
raise SystemExit(f"fix the file: line {line}, {e.param} ({e.code})")
except openai.RateLimitError as e:
# 429: too many uploads or unfinished batches; wait as long as Retry-After says
time.sleep(int(e.response.headers.get("retry-after", "60")))
raise
except openai.APIStatusError as e:
if e.status_code == 402:
# the balance cannot carry the worst case held at creation; the message ends with the estimate
raise SystemExit(e.message)
raise
print(batch.id, batch.status)
بررسی اتصال
رایگان: GET /v1/batches فهرست دستههای حساب شما را میدهد (برای کلید تازه خالی است). فهرست از رکوردهای خود جارویس خوانده میشود، ارائهدهندهای را صدا نمیزند، حتی با موجودی صفر کار میکند و هزینه ندارد؛ پس هم کلید را میآزماید هم آدرس پایه را.
فایل یا فیلد نامعتبر. error.param فیلد را میگوید و برای خطای یک خط از فایل شما، بدنهٔ خطا عضو line (شمارهٔ آن خط در فایل) را هم دارد. error.code دلیل را میگوید: Batch.InvalidFile (فایل خالی، بدون درخواست، بیش از ۵۰٬۰۰۰ درخواست، خط بلندتر از سقف، JSON یا UTF-8 نامعتبر)، Batch.InvalidRequestLine (عضوی از خط کم، اضافه، تکراری یا نادرست است، یا custom_id تکراری است)، Batch.ModelNotSupported (مدل در پردازش دستهای پشتیبانی نمیشود یا فایل بیش از ۶۴ نوشتار مدل دارد)، Batch.MixedKeyFamilies (مدل Claude و غیر Claude در یک فایل)، Batch.StorageQuotaReached (فایلهای نگهداشتهشدهٔ شما به سقف رسیده؛ فایلهای بیاستفاده را حذف کنید)، Batch.EndpointMismatch (endpoint با url خطهای فایل یکی نیست)، Batch.InputFileInvalid (فایل نتیجه، یا فایلی که دیگر دسته نمیشود؛ دوباره بارگذاری کنید)، Batch.IdempotencyKeyInvalid و Batch.ProviderRejectedFile. خطاهای معمول درگاه دربارهٔ مدل (مثل Gateway.AmbiguousModel) هم با param: body.model و شمارهٔ خط میآیند. هیچکدام هزینه ندارد و فایلی که بارگذاری آن رد شده ذخیره نمیشود.
۴۰۱
کلید ارسال نشده یا نامعتبر است؛ آن را در Authorization: Bearer یا x-api-key بفرستید. توکن ورود به کنسول جای کلید API را نمیگیرد.
۴۰۲
موجودی توکن، سقف یا بودجهٔ همین کلید کافی نیست (Gateway.InsufficientTokens، Gateway.KeyBudgetExceeded یا Gateway.KeyBindingExhausted). بارگذاری موجودی مثبت میخواهد؛ ساخت دسته باید کل برآورد حداکثر را بتواند نگه دارد و پیام خطایش با «برآورد حداکثر N توکن» تمام میشود. چیزی نگه داشته یا ثبت نمیشود.
۴۰۳
مدل یکی از خطهای فایل در پلن این کلید مجاز نیست (Gateway.ModelNotAllowed؛ هنگام بارگذاری با param: body.model و شمارهٔ خط)، اشتراک فعال ندارید، یا حساب یا تیم غیرفعال است. هنگام ساخت دسته پلنِ کلیدی سنجیده میشود که دسته را میسازد، نه کلیدی که فایل را بارگذاری کرده؛ و مدلهای یک دسته باید همه با یک اشتراک پرداخت شوند.
۴۰۴
Batch.FileNotFound یا Batch.NotFound: چنین فایل یا دستهای در حساب (یا تیم) شما نیست، شناسه نادرست است، یا فایل منقضی شده. فایل یا دستهٔ حساب دیگر عمداً همین پاسخ را میدهد.
۴۰۸ / ۴۱۳ / ۴۱۵
۴۰۸ (Gateway.UploadTimeout): بارگذاری بهموقع نرسید، معمولاً بهخاطر اتصال کند. ۴۱۳ (Gateway.RequestTooLarge): فایل از سقف حجم بزرگتر است، یا بدنهٔ ساخت دسته بیش از ۲۵۶ KiB است. ۴۱۵ (Gateway.UnsupportedMediaType): بارگذاری باید multipart/form-data و ساخت دسته application/json باشد.
۴۰۹
Batch.FileInUse: فایل ورودیِ دستهای که هنوز تمام نشده حذف نمیشود. Batch.NotCancellable: دسته تمام شده، یا همین لحظه به ارائهدهنده سپرده میشود (در حالت دوم Retry-After: 5). Batch.IdempotencyKeyReused: همین Idempotency-Key با درخواست دیگری آمده بود.
۴۲۹
Batch.TooManyUnfinished: حساب (یا تیم) شما به سقف دستههای ناتمام رسیده (Retry-After: 60). Batch.Busy: این سرور اکنون همهٔ بارگذاریها یا دانلودهایی را که میتواند میپذیرد و چیزی از درخواست شما نخوانده است (Retry-After: 5). Gateway.UpstreamRateLimited: ارائهدهنده درخواستها را محدود کرده است. محدودیت نرخ خود پلتفرم هم ۴۲۹ میدهد، با قالب خودش (RateLimit.Exceeded) و Retry-After (جدول سقفها). مقدار Retry-After را رعایت کنید؛ SDKهای OpenAI خودشان آن را میخوانند.
۵۰۰ / ۵۰۲ / ۵۰۳ / ۵۰۴
۵۰۳ (Batch.ApiDisabled، Retry-After: 60): پردازش دستهای در این محیط فعال نیست. ۵۰۳ (Batch.CapacityFull، Retry-After: 300): فضای مشترک فایلهای پردازش دستهای پر است؛ به شما ربطی ندارد، بعداً دوباره بفرستید. ۵۰۲ و ۵۰۳ (Gateway.UpstreamUnavailable): مسیر جارویس به ارائهدهنده اکنون در دسترس نیست؛ هرگز به معنای مشکل کلید یا موجودی شما نیست. ۵۰۴ (Gateway.UpstreamTimeout): ارائهدهنده بهموقع پاسخ نداد. ۵۰۰ (Server.Error): خطای غیرمنتظره. در بارگذاری هیچکدام از اینها چیزی ثبت نمیکند و در لغو و حذف چیزی را عوض نمیکند.
کلیدها و مصرف تیمی
با پلنهای واجد شرایط تیمی، اشتراک و موجودی تیم مشترک است و با کلیدهای API تیمی مصرف میشود. این کلیدها را فقط مالک و مدیر میسازند و جدا از کلیدهای شخصی مدیریت میشوند.
مراحل
۱
پلن واجد شرایط تیمی بخرید و در کنسول از روی همان اشتراک تیم بسازید.
۲
اعضا را با نقش مناسب (مدیر، عضو یا بیننده) دعوت کنید.
۳
کلید API تیمی بسازید (فقط مالک و مدیر) و آن را مثل کلید شخصی در ابزارها استفاده کنید؛ مدلهای مجاز همان پلن تیمی است.
۴
مصرف تیم را به تفکیک کلید، سازندهٔ کلید و مدل در داشبورد تیم دنبال کنید (مالک و مدیر).
بدنهٔ درخواست JSON معتبر نیست، model ندارد، نام مدل با چند مدل منطبق است، یا مدل تصویری به مسیر متنی فرستاده شده.
۴۰۱
کلید ارسال نشده یا نامعتبر است. کلید باید با pmai_ شروع شود و در Authorization: Bearer یا x-api-key بیاید.
۴۰۲
اعتبار توکن اشتراک یا سقف مصرف کلید تمام شده است. وضعیت را در صفحهٔ مصرف ببینید.
۴۰۳
مدل در پلن فعال مجاز نیست، اشتراک فعالی وجود ندارد، نام مدل در کاتالوگ نیست، یا حساب/تیم غیرفعال است.
۴۰۴
مسیر اشتباه است. ابزارهای سازگار با OpenAI: https://api.jarvis.you/v1. Claude Code و Claude Desktop: https://api.jarvis.you بدون /v1. اسلش اضافه در انتها نگذارید.
۴۰۹
درخواستی با همین شناسه هنوز در حال اجراست یا قبلاً کامل شده است.
۵۰۲ / ۵۰۳ / ۵۰۴
ارائهدهندهٔ بالادستی در دسترس نبود یا دیر پاسخ داد؛ کمی بعد دوباره تلاش کنید.