خطاها
قالب پاسخ (Envelope)
هر پاسخ از API عمومی (https://api.plexit.ir/v1/*) — چه موفق چه ناموفق —
به یک شکل است. هیچ Endpointی وجود ندارد که یک آرایه یا شیء خام برگرداند.
موفق، یک شیء تکی:
{
"data": { "...": "..." },
"response": { "status": "success", "message": "..." }
}موفق، یک فهرست:
{
"data": { "list": [ /* ... */ ], "count": 3 },
"response": { "status": "success", "message": "..." }
}خطا:
{
"data": null,
"response": { "status": "not_found", "message": "Assistant not found.", "code": "assistants.not_found" }
}response.code کلید پایدار و ترجمهنشدهی قاعدهای است که نقض شده
(assistants.not_found، products.external_id_taken،
products.limit_reached و …). وقتی خطا از یک قاعدهی نامدار میآید
هست، و در خطاهای عمومی (خطای اعتبارسنجی و 429) نیست. وقتی لازم است دو
خطای هموضعیت را از هم جدا کنید — مثلاً 409 ناشی از محصول تکراری را از
هر 409 دیگر — همراه با response.status از آن استفاده کنید.
response.message از پیش ترجمه شده (بر اساس زبان مذاکرهشدهی درخواست، با
i18n سمت سرور) — برای نمایش به انسان طراحی شده، نه برای Pattern-Matching.
مقادیر response.status
response.status یک enum پایدار و قابلخواندن توسط ماشین است — کد شما
باید بر اساس این مقدار شاخهبندی کند، هرگز بر اساس response.message:
status | وضعیت HTTP |
|---|---|
success | ۲۰۰ (یا ۲۰۱ و غیره) |
bad_request | ۴۰۰ |
not_found | ۴۰۴ |
forbidden | ۴۰۳ |
conflict | ۴۰۹ |
payment_required | ۴۰۲ |
unprocessable | ۴۲۲ |
service_unavailable | ۵۰۳ |
کدهایی که در گفتگو میبینید
response.code | HTTP | معنا |
|---|---|---|
chat.model_unavailable | ۵۰۳ | مدلِ دستیار منتشر شده ولی سرویس گفتگو هنوز نمیتواند آن را اجرا کند. یک مدل usable از GET /v1/models انتخاب کنید. |
chat.assistant_not_found | ۴۰۴ | assistantCode در این حساب وجود ندارد. |
chat.voice_disabled | ۴۰۰ | پیوست صوتی برای دستیاری فرستاده شده که acceptVoice آن خاموش است. |
خطاهای اعتبارسنجی
وقتی بدنهی یک درخواست در اعتبارسنجی رد شود، پاسخ یک bad_request
(HTTP 400) است با یک فیلد اضافه در سطح بالا: fields.
{
"data": null,
"response": { "status": "bad_request", "message": "Validation failed" },
"fields": [
{
"property": "message",
"constraints": ["This field is required."]
}
]
}fields آرایهای از { property, constraints } است، یک عنصر برای هر
فیلد نامعتبر، با constraints از پیش ترجمهشده. برای نمایش خطاهای هر
فیلد در یک فرم، از fields استفاده کنید (نه تجزیهی رشتهی
response.message).
خطاهای احراز هویت در API عمومی عمداً کلیاند
هر مسیر زیر v1/* به هدر Authorization: Bearer <raw_key> نیاز دارد و کلید
در هر درخواست بررسی میشود. در صورت شکست دریافت میکنید:
{
"data": null,
"response": { "status": "bad_request", "message": "Invalid or revoked API key", "code": "api_key.invalid" }
}با کد وضعیت HTTP 401 (توجه: مقدار response.status در اینجا
"bad_request" است، نه "forbidden" — کد ۴۰۱ مقدار status اختصاصی
ندارد و بهصورت bad_request گزارش میشود؛ اگر نیاز دارید مشخصاً حالت «احراز نشده» را تشخیص
دهید، همیشه کد وضعیت HTTP را بررسی کنید، نه فیلد JSON مربوط به
response.status). نکتهی مهم این است که — پیام و code دقیقاً یکسان برای
تمام حالتهای خطا بازگردانده میشود: هدر ارسالنشده، کلید ناشناخته،
کلید بدشکل، کلید باطلشده، یا حساب متعلق به آن کلید حذفشده. این یک تصمیم
طراحیِ عمدی است، نه یک اشکال: از این جلوگیری میکند که پاسخ برای شمارش
کلیدهای معتبر یا استنباط وضعیت حساب از بیرون قابل استفاده باشد.
منطق Retry/شاخهبندیای نسازید که بخواهد فقط بر اساس پاسخ ۴۰۱ بین «کلید وجود ندارد» و «کلید باطل شده» تمایز قائل شود — این API هرگز به شما نخواهد گفت کدامیک بوده است. اگر نیاز به اشکالزدایی یک کلید خاص در زمان توسعه دارید، بهجای آن، وضعیت آن را در صفحهی «API و اتصال» کنسول بررسی کنید.
محدودیت نرخ (Rate limiting)
هر مسیر به ۶۰ درخواست در دقیقه به ازای هر API key محدود شده — نه به
ازای IP (یعنی یک کلید محدود میشود، فارغ از اینکه از چند آدرس مختلف
فراخوانی شود). عبور از این حد یک 429 با همان قالب پاسخِ خطا بازمیگرداند:
{"data": null, "response": {"status": "bad_request", "message": "ThrottlerException: Too Many Requests"}}
همراه با هدر Retry-After: 60.
response.status همچنان "bad_request" است، نه چیزی مخصوص ۴۲۹ (همان
قاعدهی «کد وضعیت HTTP را بررسی کنید، نه فیلد JSON» که برای حالت ۴۰۱ بالا
گفته شد — کد 429 مقدار status اختصاصی ندارد).
هر پاسخ موفق این هدرهای استاندارد را دارد که میتوانید از قبل بخوانید، بدون
اینکه منتظر یک 429 بمانید:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 59
X-RateLimit-Reset: 60خودِ پاسخ 429 بهجای اینها Retry-After (به ثانیه) دارد. شمارش برای
هر نمونهی سرور جداگانه نگه داشته میشود؛ پس پشت چند نمونه، سقف عملی
میتواند کمی بیشتر از ۶۰ باشد.
X-RateLimit-Reset تعداد ثانیه تا ریستشدن پنجره است، نه یک timestamp.
آنچه هنوز اینجا نیست
- بدون کد عددی خطا.
response.codeیک کلید رشتهای است و فقط در خطاهایی هست که از یک قاعدهی نامدار میآیند؛ فهرست کاملی از آنها هنوز وجود ندارد. اول بر اساسresponse.statusشاخهبندی کنید و فقط برای موارد خاصی که خودتان مدیریت میکنید بهresponse.codeنگاه کنید.