# レート制限と同時実行性

Tripo API は、サービスの安定性と公正な使用を確保するために、レート制限と同時実行制限を適用します。

## レート制限

レート制限により、時間枠内で実行できる API リクエストの数が制限されます。

### 制限ルール

- レート制限は **API Key** レベルで計算されます
- 制限はエンドポイントによって異なります。 `/v3/generation/*` などの生成エンドポイントには低い制限があり、`/v3/tasks/*` などのクエリ エンドポイントには高い制限があります
- 制限を超えると、API は HTTP `429 Too Many Requests` をエラー コード `1007` とともに返します。

### 応答ヘッダー

すべての API 応答には、レート制限関連の応答ヘッダーが含まれます。

| 応答ヘッダー | 説明 |
| :-: | :-: |
| `X-RateLimit-Limit` | 現在の時間枠内で許可されるリクエストの最大数 |
| `X-RateLimit-Remaining` | 現在の時間枠内で利用可能な残りのリクエストの数 |
| `X-RateLimit-Reset` | レート制限ウィンドウがリセットされたときの Unix タイムスタンプ (秒単位) |

### レート制限時の応答

```json
{
  "code": 1007,
  "message": "Rate limit exceeded, you've generated too many requests in a short amount of time",
  "suggestion": "Please wait for a while and try again"
}
```

---

## 同時実行の制限

同時実行制限により、アカウントで**同時に**実行できるタスクの数が制限されます。これはレート制限とは異なります。レート制限はリクエスト頻度を制限しますが、同時実行制限は並列実行タスクを制限します。

### 仕組み

- 同時実行性は **アカウント** レベルで計算されます (API Key ごとではありません)。
- 制限は **タスク カテゴリごとに適用されます** - 各カテゴリには独自の独立した同時実行プールがあります
- カテゴリの同時実行数がいっぱいになると、そのカテゴリの新しいタスクを作成すると、エラー コード `2000` を伴う HTTP `429` が返されます。
- 他のカテゴリのタスクは **影響を受けません** - 利用可能なスロットがあるカテゴリでは引き続きタスクを作成できます

### デフォルトの制限

すべてのユーザーは、カテゴリごとにデフォルトの同時実行数 **10** で開始します。一部のカテゴリには異なる制限があります (以下の表を参照)。

| カテゴリ | 含まれるタスクの種類 | デフォルトの同時実行性 |
| :-: | :-: | :-: |
| 3D 生成 — H シリーズ | テキストからモデルへ (H)、画像からモデルへ (H)、マルチビューからモデルへ (H) | 10 |
| 3D 生成 — P シリーズ | テキストからモデルへ (P)、画像からモデルへ (P)、マルチビューからモデルへ (P) | 5 |
| 画像生成 | テキストから画像へ、画像から画像へ、画像からマルチビューへ、編集からマルチビュー | 1 |
| アニメーション | 自動リグ、リグチェック、アニメーション リターゲット | 10 |
| モデル処理 | テクスチャ、フォーマット変換、リファイン | 5 |
| メッシュ操作 | セグメンテーション、補完、リトポロジー | 10 |

> **注:** 同じカテゴリ内のタスクは同時実行プールを共有します。たとえば、H シリーズのテキストからモデルへのタスクが 10 個実行されている場合、H シリーズのイメージからモデルへのタスクは 1 つが完了するまで開始できません。ただし、P シリーズまたはイメージ生成タスクを開始することはできます。

### 同時実行数を超えた場合の応答

```json
{
  "code": 2000,
  "message": "You have exceeded the limit of generation",
  "suggestion": "Try again later. You can also check `Retry-After` header."
}
```

応答には、再試行するまでに待機する秒数を示す `Retry-After` ヘッダーが含まれています。

### 同時実行性の向上

より高い同時実行制限をリクエストするには、サポート チャネル経由で当社のチームにお問い合わせください。カスタム同時実行性は、使用上のニーズに基づいてカテゴリごとに構成できます。

---

## 429 応答の処理

### Python

```python
import time
import requests

def request_with_backoff(method, url, headers, json=None, max_retries=5):
    for attempt in range(max_retries):
        response = requests.request(method, url, headers=headers, json=json)

        if response.status_code != 429:
            return response

        retry_after = response.headers.get("Retry-After")
        reset_at = response.headers.get("X-RateLimit-Reset")

        if retry_after:
            wait = int(retry_after)
        elif reset_at:
            wait = max(int(reset_at) - int(time.time()), 1)
        else:
            wait = 2 ** attempt

        print(f"429 triggered. Waiting {wait} seconds (attempt {attempt + 1})...")
        time.sleep(wait)

    raise Exception("Maximum retry attempts exhausted")
```

### JavaScript

```javascript
async function requestWithBackoff(url, options, maxRetries = 5) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) {
      return response;
    }

    const retryAfter = response.headers.get("Retry-After");
    const resetAt = response.headers.get("X-RateLimit-Reset");
    const wait = retryAfter
      ? Number(retryAfter)
      : resetAt
        ? Math.max(Number(resetAt) - Math.floor(Date.now() / 1000), 1)
        : 2 ** attempt;

    console.log(`429 triggered. Waiting ${wait} seconds (attempt ${attempt + 1})...`);
    await new Promise(resolve => setTimeout(resolve, wait * 1000));
  }

  throw new Error("Maximum retry attempts exhausted");
}
```

## ベストプラクティス

- **指数バックオフ再試行を実装します**: 最初は 1 秒待機し、毎回待機時間を 2 倍にし、最大待機時間を 32 秒に制限します。
- **`Retry-After` ヘッダーと `X-RateLimit-Reset` ヘッダーを優先します**: 制限ウィンドウがリセットされるまで正確に待ちます
- **カテゴリ レベルの同時実行性を考慮した設計**: 可能であれば、カテゴリ間でワークロードを分散します。画像生成と 3D 生成には個別のプールがあります。
- **バッチ API を使用**: 複数の `GET /v3/tasks/{task_id}` リクエストの代わりに `POST /v3/tasks/list` を使用します。
- **賢明にポーリング**: タスクの完了を待機するときは、クエリ エンドポイントをフラッディングするのではなく、適切な間隔 (1 ～ 2 秒ごと) でポーリングします。
