# Limites de débit et concurrence

Le Tripo API applique des limites de débit et des limites de concurrence pour garantir la stabilité du service et une utilisation équitable.

## Limites de taux

Les limites de débit limitent le nombre de requêtes API que vous pouvez effectuer dans une fenêtre horaire.

### Règles de limite

- Les limites de débit sont calculées au niveau **API Key**
- Les limites varient selon le point final. Les points de terminaison de génération, tels que `/v3/generation/*`, ont des limites inférieures, tandis que les points de terminaison de requête, tels que `/v3/tasks/*`, ont des limites plus élevées.
- Lorsqu'une limite est dépassée, le API renvoie HTTP `429 Too Many Requests` avec le code d'erreur `1007`

### En-têtes de réponse

Chaque réponse API comprend des en-têtes de réponse liés à la limite de débit :

| En-tête de réponse | Descriptif |
| :-: | :-: |
| `X-RateLimit-Limit` | Nombre maximum de demandes autorisées dans la fenêtre horaire actuelle |
| `X-RateLimit-Remaining` | Nombre de demandes restantes disponibles dans la fenêtre horaire actuelle |
| `X-RateLimit-Reset` | Horodatage Unix, en secondes, lorsque la fenêtre de limite de débit se réinitialise |

### Réponse lorsque le débit est limité

```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"
}
```

---

## Limites de concurrence

Les limites de simultanéité limitent le nombre de tâches pouvant s'exécuter **simultanément** sous votre compte. Ceci est différent des limites de débit : les limites de débit plafonnent la fréquence des demandes, tandis que les limites de concurrence plafonnent les tâches exécutées en parallèle.

### Comment ça marche

- La simultanéité est calculée au niveau du **compte** (et non selon API Key).
- Les limites sont appliquées **par catégorie de tâches** — chaque catégorie possède son propre pool de concurrence indépendant
- Lorsque la simultanéité d'une catégorie est pleine, la création d'une nouvelle tâche pour cette catégorie renvoie HTTP `429` avec le code d'erreur `2000`.
- Les tâches des autres catégories ne sont **pas affectées** : vous pouvez toujours créer des tâches dans des catégories qui ont des emplacements disponibles

### Limites par défaut

Tous les utilisateurs commencent avec une simultanéité par défaut de **10** par catégorie ; certaines catégories ont des limites différentes (voir le tableau ci-dessous).

| Catégorie | Types de tâches inclus | Concurrence par défaut |
| :-: | :-: | :-: |
| Génération 3D — Série H | texte-modèle (H), image-modèle (H), multivue-modèle (H) | 10 |
| Génération 3D — Série P | texte-modèle (P), image-modèle (P), multivue-modèle (P) | 5 |
| Génération d'images | texte à image, image à image, image à multivue, édition multivue | 1 |
| Animations | auto-rig, rig-check, animation-retarget | 10 |
| Traitement du modèle | texture, conversion de format, affinement | 5 |
| Opérations de maillage | segmentation, complétion, retopologie | 10 |

> **Remarque :** Les tâches d'une même catégorie partagent le pool de concurrence. Par exemple, si 10 tâches de conversion de texte en modèle de série H sont en cours d'exécution, vous ne pouvez pas démarrer une tâche de conversion d'image en modèle de série H tant qu'une d'entre elles n'est pas terminée. Cependant, vous pouvez toujours démarrer des tâches de série P ou de génération d'images.

### Réponse lorsque la concurrence est dépassée

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

La réponse inclut un en-tête `Retry-After` indiquant le nombre de secondes à attendre avant de réessayer.

### Augmentation de la concurrence

Pour demander des limites de simultanéité plus élevées, veuillez contacter notre équipe via le canal d'assistance. La concurrence personnalisée peut être configurée par catégorie en fonction de vos besoins d'utilisation.

---

## Traitement de 429 réponses

### 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");
}
```

## Meilleures pratiques

- **Mettez en œuvre des tentatives d'attente exponentielles** : attendez initialement 1 seconde, doublez l'attente à chaque fois et limitez l'attente maximale à 32 secondes.
- **Préférez les en-têtes `Retry-After` et `X-RateLimit-Reset`** : Attendez précisément que la fenêtre de limite se réinitialise
- **Conception pour une simultanéité au niveau des catégories** : répartissez les charges de travail entre les catégories lorsque cela est possible : la génération d'images et la génération 3D ont des pools distincts
- **Utiliser les lots API** : utilisez `POST /v3/tasks/list` au lieu de plusieurs requêtes `GET /v3/tasks/{task_id}`
- **Interrogez judicieusement** : lorsque vous attendez la fin d'une tâche, interrogez à des intervalles raisonnables (toutes les 1 à 2 secondes) plutôt que d'inonder le point de terminaison de la requête.
