---
title: محدودیت‌ها
description: سقف نرخ درخواست API دانا، هدرهای پاسخ و روش درست مدیریت خطای ۴۲۹
---

هر کلید API سقف نرخ خودش را دارد. پیش‌فرض ۶۰ درخواست در دقیقه است و از رد شدن یک کلید، بقیه کلیدهای شما آسیب نمی‌بینند.

## پنجره چطور شمرده می‌شود

شمارش روی پنجره ثابت است، نه لغزان. دقیقه به بازه‌های سرراست تقسیم می‌شود و شمارنده سر هر بازه از صفر شروع می‌کند.

این یک نتیجه عملی دارد. فرض کنید ۶۰ درخواست را در ثانیه‌های پایانی یک بازه بفرستید و ۶۰ تای بعدی را در ثانیه‌های آغازین بازه بعد. هر دو دسته می‌گذرند، یعنی برای یک لحظه دو برابر سقف رد شده است. پس بار سنگین را پخش کنید و به مرز پنجره تکیه نکنید.

## هدرهای پاسخ روی ۴۲۹

وقتی از سقف رد شوید، پاسخ `429` این چهار هدر را همراه دارد:

| هدر | معنا |
|---|---|
| `Retry-After` | چند ثانیه دیگر پنجره باز می‌شود |
| `X-RateLimit-Limit` | سقف همین کلید |
| `X-RateLimit-Remaining` | باقی‌مانده، که اینجا همیشه صفر است |
| `X-RateLimit-Reset` | زمان باز شدن پنجره به شکل unix timestamp |

بدنه پاسخ روی رابط OpenAI:

```json
{
  "error": {
    "message": "Rate limit exceeded.",
    "type": "rate_limit_error",
    "param": null,
    "code": null
  }
}
```

## اول `type` را بخوانید

کد `429` چهار علت جدا دارد و دو موردشان با تلاش مجدد حل می‌شوند. پیش از تلاش مجدد، فیلد `type` را نگاه کنید:

| مقدار `type` | معنا | تلاش مجدد؟ |
|---|---|---|
| `rate_limit_error` | سقف نرخ همین کلید | بله، بعد از `Retry-After` |
| `capacity_busy` | صف موقت سرویس | بله، بعد از `eta_seconds` |
| `insufficient_quota` | اعتبار تمام شده | خیر، باید شارژ کنید |
| `window_cap` | سقف پنجره توکن | خیر، تا زمان `reset_at` صبر کنید |

شرح کامل هر چهار حالت با نمونه بدنه در [خطاها](/docs/errors) آمده است.

## مدیریت خطا در کد

به `Retry-After` گوش بدهید؛ حدس زدن فاصله، یا زودتر می‌زند یا بی‌خود صبر می‌کند. کمی jitter هم اضافه کنید تا چند worker هم‌زمان دوباره به دیوار نخورند.

```python
import random
import time

import httpx


def call_with_retry(payload, api_key, max_attempts=3):
    for attempt in range(max_attempts):
        response = httpx.post(
            "https://api.dana.expert/v1/chat/completions",
            headers={"Authorization": f"Bearer {api_key}"},
            json=payload,
            timeout=120,
        )
        if response.status_code != 429:
            response.raise_for_status()
            return response.json()

        kind = response.json().get("error", {}).get("type")
        if kind not in ("rate_limit_error", "capacity_busy"):
            raise RuntimeError(f"۴۲۹ غیرقابل تلاش مجدد: {kind}")

        wait = float(response.headers.get("Retry-After", 2**attempt))
        time.sleep(wait + random.random())

    raise RuntimeError("سقف نرخ بعد از سه تلاش هنوز باز نشده بود")
```

## سقف هر کلید

سقف روی خودِ کلید می‌نشیند، نه روی حساب. در [کنسول دانا](https://console.dana.expert/keys) می‌توانید برای هر کلید مقدار جداگانه بگذارید.

الگویی که معمولا جواب می‌دهد: یک کلید پرسقف برای سرویس اصلی، یک کلید کم‌سقف برای اسکریپت‌های آزمایشی. اسکریپتی که از کنترل خارج شود، آن‌وقت فقط سهم خودش را می‌سوزاند.

## نکته‌ها

- درخواست‌های ناموفق هم شمرده می‌شوند. شمارش پیش از رسیدن به مدل انجام می‌شود، پس یک `400` هم یک درخواست است.
- streaming و non-streaming فرقی ندارند؛ هر کدام یک درخواست‌اند، هرچند پاسخ streaming دقایقی طول بکشد.
- شمارش با شناسه کلید انجام می‌شود. چند سرور که یک کلید مشترک دارند، در یک پنجره سهیم‌اند.
- برای حجم بالا با پشتیبانی دانا تماس بگیرید.

## صفحه‌های مرتبط

- [خطاها](/docs/errors) - همه کدها و پاکت‌های خطا
- [احراز هویت](/docs/authentication) - ساخت و باطل کردن کلید
- [قیمت و توکن](/docs/pricing-and-tokens) - سقف اعتبار و شمارش توکن
