Documentación
Límites de uso
Cuántos requests admite una credencial, cómo se anuncian y qué hacer con un 429.
Hay dos cubetas, y no miden lo mismo.
| Cubeta | Límite | Por qué existe |
|---|---|---|
| Por credencial | 60 requests / minuto | Es el límite que te importa como integrador, y el que se anuncia en los headers. |
| Por IP | 600 requests / minuto | Se cobra antes de autenticar. Sin ella, golpear con bearers inválidos saldría gratis: verificar la firma y consultar la base ya cuesta, y todavía no hay credencial a la que cobrarle. |
El endpoint de tokens tiene su propia cubeta por client_id, también de 60 por minuto, para que una credencial válida no lo convierta en una fuente infinita de JWT. Es una razón más para cachear el token en vez de pedir uno por request.
Nota
La cubeta por credencial se cobra apenas se sabe quién sos, antes de verificar el scope. Un request con el scope equivocado consume exactamente el mismo trabajo del servidor que uno correcto, así que consume cupo igual.
Los headers
Toda respuesta autenticada trae el estado de la cubeta, incluidas las de error: no hace falta acertar para saber cuánto queda.
HTTP/1.1 200 OK
X-Request-Id: 9f1c0a3e-7b2d-4f18-9a55-2c6e0d1b4a77
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 41
X-RateLimit-Reset: 1767222060HTTP/1.1 429 Too Many Requests
Retry-After: 23
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1767222060
{
"status": "error",
"message": "Demasiados requests",
"message_code": "rate_limit_exceeded",
"data": [],
"meta": { "request_id": "…" }
}Manejar un 429
- Respetá
Retry-After. Es la espera exacta hasta que la ventana se libera; reintentar antes solo gasta otra unidad. - Agregá jitter. Sin él, todos tus workers reintentan en el mismo instante y el
429se repite en bloque. - Si venís usando
X-RateLimit-Remaining, frená antes de llegar a cero: es más barato esperar que rebotar.
import random
import time
def respect_rate_limit(response) -> bool:
"""Duerme lo que pide el 429 y avisa si conviene reintentar."""
if response.status_code != 429:
return False
wait = float(response.headers.get("Retry-After", "1"))
time.sleep(wait + random.uniform(0, 0.5))
return TrueLos turnos son otra cosa
El límite por minuto cuenta requests, no consumo del modelo. Un turno puede durar minutos y gastar miles de tokens siendo un solo request.
El consumo de modelo lo gobierna la licencia del usuario titular: cada turno descuenta del pool de niucredits. Cuando se agota, el envío se rechaza aunque te sobre cupo de requests. El consumo se consulta en Analíticas.
Nota
Y en paralelo está el límite de un turno de la API por chat (ver Idempotencia), que no es de volumen sino de consistencia.