Concepts fondamentaux
Limites de débit
Alloovium exécute un token bucket par identifiant. Chaque capability a un coût en tokens ; chaque niveau a un taux de remplissage et une capacité de burst maximale. Restez dans votre bucket et vous ne verrez jamais un 429.
Comment fonctionne le bucket
Chaque clé API et identifiant OAuth a son propre token bucket. Les tokens se remplissent continuellement au taux par minute du niveau, jusqu'à la capacité de burst du niveau. Quand une requête arrive, le coût de la capability est déduit du bucket. Si le bucket n'a pas assez de tokens, la requête est rejetée avec code et doit être retentée plus tard.
Token-bucket, pas fenêtre fixe
Niveaux
| Niveau | Tokens / minute | Capacité de burst | Usage typique |
|---|---|---|---|
| free | 10 | 20 | Hobby projects and prototyping |
| standard | 60 | 120 | Most SaaS integrations |
| pro | 300 | 600 | High-volume automations and ETL |
| enterprise | 1500 | 3000 | Platform integrations, custom SLAs |
Le niveau est défini sur chaque clé API lors de la création et peut être mis à niveau depuis le tableau de bord. Les identifiants OAuth héritent du niveau du plan de tenant de l'utilisateur.
Coûts des capabilities
Les lectures bon marché coûtent 1 token. Les recherches et requêtes structurées coûtent 5. Le chat et les appels LLM coûteux coûtent 10. Les exécutions de workflow et les remplissages de template coûtent 25. Utilisez ce tableau pour budgétiser :
| Capability | Coût |
|---|---|
| meta.whoami | 1 |
| vault.list_projects | 1 |
| vault.get_project | 1 |
| vault.create_project | 2 |
| vault.list_documents | 1 |
| vault.get_document | 1 |
| vault.upload_document | 10 |
| vault.search | 5 |
| chat.list_conversations | 1 |
| chat.get_conversation | 1 |
| chat.ask | 10 |
| chat.ask_stream | 10 |
| templates.start_fill | 25 |
| templates.get_fill_status | 1 |
| workflows.list | 1 |
| workflows.run | 25 |
| workflows.get_run_status | 1 |
Headers de réponse
Chaque réponse — succès ou limite de débit — porte ces headers :
| Header | Signification |
|---|---|
| X-RateLimit-Limit | Burst capacity of your bucket |
| X-RateLimit-Remaining | Tokens left after this call was accounted for |
| X-RateLimit-Reset | Unix timestamp when the bucket is expected to be full |
| X-RateLimit-Cost | Tokens this particular call deducted |
| Retry-After | Seconds until you can retry (only on 429) |
Surveillez header de manière proactive et ralentissez avant d'atteindre zéro — vous obtiendrez un comportement plus propre qu'en réagissant aux 429.
Atteindre la limite
Quand vous manquez de tokens, l'API retourne code avec cette enveloppe :
json{ "type": "https://api.alloovium.com/errors/rate_limited", "title": "Rate limit exceeded", "status": 429, "detail": "Rate limit exceeded. Retry in 12 seconds.", "code": "rate_limited", "retry_after_seconds": 12 }
Le header header porte la même valeur. Respectez-le. Ne retentez pas immédiatement dans une boucle serrée — cela prolongerait seulement le backoff et gaspillerait votre quota.
Stratégie de retry
La stratégie recommandée pour tout client :
- Sur 429, attendez
headersecondes et retentez. - Sur 5xx, retentez avec backoff exponentiel — commencez à 1s, doublez jusqu'à 30s, ajoutez 10% de jitter. Limitez à cinq tentatives.
- À chaque retry, conservez le même
headerafin que l'API puisse rejouer la réponse originale au lieu de s'exécuter deux fois. Voir Idempotence. - Abandonnez après des erreurs 4xx non-429 répétées — celles-ci ne sont pas transitoires.
Exemple de boucle de retry (pseudocode)
pythonimport time, httpx def call_with_retry(client, method, url, *, body=None, idem_key=None, max_retries=5): headers = {"Authorization": f"Bearer {API_KEY}"} if idem_key: headers["Idempotency-Key"] = idem_key for attempt in range(max_retries): resp = client.request(method, url, json=body, headers=headers) if resp.status_code < 400: return resp.json() if resp.status_code == 429: time.sleep(int(resp.headers.get("Retry-After", "1"))) continue if 500 <= resp.status_code < 600: time.sleep(min(30, 2 ** attempt) + (0.1 * attempt)) continue # 4xx other than 429 — do not retry resp.raise_for_status() raise RuntimeError("max retries exhausted")
Conseils d'ingénierie de quota
- Groupez avec
search(coût 5) plutôt que plusieurs appelsget(coût 1 chacun) lorsque vous avez besoin du contenu. - Pour les workflows, interrogez
statustoutes les 2–5 secondes — ne faites pas de boucle serrée. - Si vous ingérez en fan-out, exécutez les appels
uploaden concurrent jusqu'àformula, puis attendez que le bucket se remplisse. - Utilisez
whoami(coût 1) comme sonde de santé — pas les endpoints plus coûteux.