# خطاها و پیام‌ها


## ساختار پاسخ خطا

```json
{
  "error": {
    "code": "invalid_request",
    "message": "..."
  }
}
```

## کدهای خطا

| HTTP | code | معنی | تکرار؟ |
| --- | --- | --- | --- |
| 401 | `missing_authorization` | هدر Authorization ارسال نشده یا طرح Bearer ندارد | خیر |
| 401 | `invalid_api_key` | کلید نامعتبر است | خیر |
| 403 | `revoked_api_key` | کلید لغو شده است | خیر |
| 403 | `expired_api_key` | تاریخ انقضای کلید گذشته است | خیر |
| 403 | `ip_not_allowed` | IP درخواست در فهرست IPهای مجاز این کلید نیست | خیر |
| 403 | `model_not_allowed` | این کلید اجازهٔ استفاده از این مدل را ندارد | خیر |
| 403 | `spend_cap_exceeded` | سقف مصرف روزانه یا ماهانهٔ کلید پر شده (اول روز/ماه بعد، به وقت تهران، صفر می‌شود) | پس از شروع دورهٔ بعد |
| 403 | `user_banned` | حساب مسدود شده است | خیر |
| 403 | `insufficient_credits` | اعتبار کافی نیست (پیام مقدار لازم و موجودی را می‌گوید) | خیر |
| 429 | `rate_limit_exceeded` | بیش از سقف دقیقه‌ای (60 درخواست) | پس از Retry-After |
| 400 | `invalid_request` | بدنه یا پارامتر نامعتبر؛ پیام فیلد مشکل‌دار را می‌گوید | خیر |
| 400 | `unsupported_model` | شناسهٔ مدل برای این مسیر پشتیبانی نمی‌شود | خیر |
| 400 | `invalid_idempotency_key` | مقدار `Idempotency-Key` نامعتبر | خیر |
| 404 | `task_not_found` | تسکی با این شناسه برای این حساب وجود ندارد | خیر |
| 409 | `idempotency_key_in_progress` | درخواست قبلی با همین کلید هنوز در حال اجراست | پس از Retry-After |
| 422 | `idempotency_key_reused` | همان `Idempotency-Key` با بدنهٔ متفاوت | خیر |
| 500 | `generation_failed` | ارسال به مدل ناموفق بود؛ اعتباری رزرو نشده | بله |
| 500 | `internal_error` | خطای غیرمنتظرهٔ سرور | بله (با backoff) |

> خطای تسک با خطای HTTP فرق دارد: اگر تسک ثبت شود ولی تولید شکست بخورد، HTTP 200 است و `status` تسک `failed` و دلیل در `error` می‌آید؛ اعتباری کسر نمی‌شود.

## محدودیت نرخ (429)

هدرهای مفید: `Retry-After`، `X-RateLimit-Limit`. برای 429 اعتباری کسر نمی‌شود.

> صبر کنید تا Retry-After بگذرد، backoff کنید، و polling را هر ۳ تا ۵ ثانیه نگه دارید.
