15Referencia
Límites
La frecuencia de solicitudes y el número de tareas sin terminar se limitan por separado. Los límites de la cuenta son comunes a todas sus claves; el sondeo de las tareas y el presupuesto mensual tienen sus propias reglas.
Lo principal
Son los valores predeterminados: son los mismos para cualquier cuenta, también para una recién registrada. El límite de una cuenta puede ser otro: si te queda corto, escribe a soporte.
Todos los límites
| Límite | Valor predeterminado | Respuesta al superarlo |
|---|---|---|
| Frecuencia de solicitudes Cuenta, compartida por todas las claves | 120 solicitudes por minuto, en ventanas de 60 segundos | 429 ERR_RATE_LIMIT |
| Generaciones simultáneas Cuenta | 100 tareas en cola o en curso | 429 ERR_QUOTA_EXCEEDED, details.scope = "account" |
| Intervalo del sondeo Clave y tarea | No más de una vez cada 5 segundos | 429 ERR_RATE_LIMIT, details.min_interval_seconds |
| Carga de imágenes de referencia Cuenta que se registró por sí sola y aún no ha recargado el saldo; día en UTC | 100 imágenes de referencia por día; tras la primera recarga no hay límite | 429 ERR_RATE_LIMIT, details.window = "1d" |
| Límite mensual de la cuenta Todas las claves juntas, mes calendario en UTC | Un importe opcional en dólares; lo fijas tú en el portal, en la sección «Saldo y recargas» | 402 ERR_INSUFFICIENT_BALANCE, details.reason = monthly_budget_exceeded |
| Límite mensual de la clave Una clave, mes calendario en UTC | Un importe opcional en dólares; lo fijas tú en la sección «Claves de API» | 402 ERR_INSUFFICIENT_BALANCE, details.reason = monthly_budget_exceeded |
| Bloqueo por errores de acceso Dirección IP desde la que llegaron las solicitudes | 30 rechazos 401 o 30 rechazos 403 por minuto (se cuentan por separado); bloqueo de hasta 120 segundos | 429 ERR_RATE_LIMIT, details.reason = burst_block |
Frecuencia de solicitudes
En el recuento de frecuencia entran el inicio de generaciones, la carga de archivos, la lectura del catálogo de modelos y la lectura del saldo. El sondeo de una tarea se cuenta aparte, según la regla de más abajo. Las claves adicionales no aumentan este recuento.
La respuesta al superar el límite contiene details.limit, details.window = "1m" y details.retry_after, y en el encabezado, Retry-After.
Generaciones simultáneas
Las tareas en cola y en curso ocupan un lugar en el límite de la cuenta hasta que terminan. Si la respuesta contiene details.scope = "account", espera a que haya tareas listas y envía las nuevas con menos frecuencia.
Para envíos masivos, mantén tu propia cola: lanza las tareas nuevas a medida que se liberen lugares, no todas de golpe.
Intervalo del sondeo
Comprueba el estado de una tarea con una misma clave no más de una vez cada 5 segundos. Un sondeo demasiado temprano recibe 429 con details.min_interval_seconds = 5. Espera como mínimo el mayor de ese número y Retry-After: el encabezado a veces indica un intervalo menor.
Deja de consultar cuando el estado sea completed o failed. Para no consultar en absoluto, usa webhooks; cómo obtener el resultado está en la sección «Tareas y estados».
Carga de imágenes de referencia
Una cuenta que se registró por sí sola y todavía no ha recargado el saldo ni una vez puede usar como máximo 100 imágenes de referencia por día, contando por días calendario en UTC. Cuentan tanto los archivos subidos con POST /uploads como las direcciones de image_urls. El límite se comprueba antes de la carga, de la descarga y del cargo: si se rechaza, el saldo no cambia.
Tras la primera recarga ya no hay límite. Las demás cuentas no tienen este límite.
Al superarlo llega 429 ERR_RATE_LIMIT con details.limit, details.window = "1d" y details.retry_after, y en el encabezado, Retry-After. Recarga el saldo y el límite desaparecerá; si no, espera al día siguiente.
Límites mensuales de gasto
El límite mensual es un máximo de gasto opcional. Por defecto no existe. Se puede fijar de dos formas, y funcionan a la vez:
- Límite de la cuenta — para todas las claves juntas. Se fija en el portal, en la sección «Saldo y recargas».
- Límite de la clave — solo para una clave. Se fija en la sección «Claves de API».
Se cuentan los cargos por generaciones dentro del mes calendario en UTC; el reembolso de una imagen fallida libera el importe. Cuando se agota cualquiera de los dos límites, la siguiente solicitud de generación recibe 402 ERR_INSUFFICIENT_BALANCE con details.reason = monthly_budget_exceeded y el campo numérico details.cap en dólares. Entonces no se hace ningún cargo.
Es un límite estricto: hasta que cambie el mes o subas el límite, no se aceptan generaciones nuevas.
Bloqueo por errores de acceso
Deja de reintentar ante 401 y 403 y corrige la causa: una clave incorrecta, una cuenta desactivada. Los 401 repetidos pueden bloquear temporalmente el tráfico de la API desde tu dirección IP; los 403 repetidos bloquean la API pública desde esa dirección, y el portal sigue disponible.
Las integraciones detrás de un mismo NAT comparten una dirección IP y, por tanto, también este bloqueo. Con burst_block, espera Retry-After y corrige primero la causa de los rechazos.
Ejemplos de respuestas
Los valores de los encabezados son de ejemplo: léelos en cada respuesta. El formato es el estándar, como en la sección «Códigos de error».
HTTP/1.1 429 Too Many Requests Retry-After: 17 { "error": { "code": "ERR_RATE_LIMIT", "message": "rate limit exceeded", "details": { "limit": 120, "window": "1m", "retry_after": 17 } } }
HTTP/1.1 429 Too Many Requests Retry-After: 2 { "error": { "code": "ERR_QUOTA_EXCEEDED", "message": "concurrency limit reached", "details": { "limit": 100, "scope": "account" } } }
HTTP/1.1 429 Too Many Requests Retry-After: 2 { "error": { "code": "ERR_RATE_LIMIT", "message": "polled too soon — retry after the minimum interval", "details": { "min_interval_seconds": 5 } } }
HTTP/1.1 429 Too Many Requests Retry-After: 41230 { "error": { "code": "ERR_RATE_LIMIT", "message": "Daily upload limit reached. Add funds to your account to lift it.", "details": { "limit": 100, "window": "1d", "retry_after": 41230 } } }
HTTP/1.1 429 Too Many Requests Retry-After: 120 { "error": { "code": "ERR_RATE_LIMIT", "message": "Too many errors. Please wait before retrying.", "details": { "reason": "burst_block", "retry_after": 120 } } }
Reintentos ante 429
Espera como mínimo Retry-After segundos y añade un pequeño retardo aleatorio para que los procesos no repitan la solicitud a la vez. Limita el número de intentos y conserva el cuerpo de la solicitud, la clave de API y el X-Idempotency-Key: así, repetir el mismo envío no creará una segunda tarea.
Mientras el primer envío aún se está procesando, repetirlo con la misma clave de idempotencia puede devolver details.reason = "idempotency_in_flight": espera y vuelve a preguntar (más información).
import os import random import time import requests API = "https://api.rendergrid.io/ api/ public/ v1" def submit_with_backoff(payload, idempotency_key, max_attempts=5): key = os.environ["RENDERGRID_API_KEY"] headers = { "Authorization": f"Bearer {key}", # el mismo en todos los intentos "X-Idempotency-Key": idempotency_key, } for attempt in range(max_attempts): response = requests.post( f"{API}/images/generate", headers=headers, json=payload, timeout=(10, 120), ) if response.status_code != 429: return response try: body = response.json() except ValueError: body = {} details = body.get("error", {}).get("details", {}) last = attempt + 1 == max_attempts if details.get("reason") == "burst_block" or last: # el bloqueo y el último intento se devuelven al llamador return response wait = int(response.headers.get("Retry-After", "2")) # esperamos como mínimo Retry-After time.sleep(max(0, wait) + random.uniform(0, 1))
// Node.js 22+, archivo .mjs const API = "https://api.rendergrid.io/ api/ public/ v1"; const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); async function submitWithBackoff(payload, idempotencyKey, maxAttempts = 5) { for (let attempt = 0; attempt < maxAttempts; attempt++) { const response = await fetch(`${API}/images/generate`, { method: "POST", headers: { Authorization: `Bearer ${process.env.RENDERGRID_API_KEY}`, "Content-Type": "application/json", // el mismo en todos los intentos "X-Idempotency-Key": idempotencyKey, }, body: JSON.stringify(payload), signal: AbortSignal.timeout(120_000), }); if (response.status !== 429) return response; const body = await response .clone() .json() .catch(() => ({})); const last = attempt + 1 === maxAttempts; if (body.error?.details?.reason === "burst_block" || last) { // el bloqueo y el último intento se devuelven al llamador return response; } const wait = Number(response.headers.get("Retry-After") ?? 2); const delay = Math.max(0, wait); // esperamos como mínimo Retry-After await sleep((delay + Math.random()) * 1000); } }
El ejemplo solo reintenta 429, entrega las demás respuestas a tu código y se detiene con burst_block. Si la conexión se cortó o se perdió la respuesta, conserva la misma clave y comprueba la tarea conocida antes de un nuevo envío.
Preguntas frecuentes
¿Se puede subir el límite?
¿Aumentan el límite las claves adicionales?
¿Cómo consultar una tarea para no recibir un 429?
completed o failed. Aún más sencillo es suscribirte a un webhook: entonces no hace falta consultar.¿Qué hacer si llega un 429 burst_block?
Retry-After.