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.

CubetaLímitePor qué existe
Por credencial60 requests / minutoEs el límite que te importa como integrador, y el que se anuncia en los headers.
Por IP600 requests / minutoSe 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
HTTP/1.1 200 OK
X-Request-Id: 9f1c0a3e-7b2d-4f18-9a55-2c6e0d1b4a77
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 41
X-RateLimit-Reset: 1767222060
Al agotarla
HTTP/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 429 se 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 True

Los 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.