15Справочник
Лимиты
Частоту запросов и число незавершённых заданий ограничивают по отдельности. Лимиты аккаунта общие для всех его ключей; у опроса заданий и месячного бюджета свои правила.
Главное
Это значения по умолчанию: они одинаковы для любого аккаунта, и для только что зарегистрированного тоже. У аккаунта лимит может быть другим: если вам не хватает, напишите в поддержку.
Все лимиты
| Лимит | По умолчанию | Ответ при превышении |
|---|---|---|
| Частота запросов Аккаунт, общий для всех ключей | 120 запросов в минуту, окна по 60 секунд | 429 ERR_RATE_LIMIT |
| Параллельные генерации Аккаунт | 100 заданий в очереди или в работе | 429 ERR_QUOTA_EXCEEDED, details.scope = "account" |
| Интервал опроса Ключ и задание | Не чаще раза в 5 секунд | 429 ERR_RATE_LIMIT, details.min_interval_seconds |
| Загрузка образцов Аккаунт, который зарегистрировался сам и ещё не пополнял баланс; сутки по UTC | 100 образцов в сутки; после первого пополнения лимита нет | 429 ERR_RATE_LIMIT, details.window = "1d" |
| Месячный лимит аккаунта Все ключи вместе, календарный месяц по UTC | Необязательная сумма в долларах; её задаёте вы в кабинете, в разделе «Баланс и пополнение» | 402 ERR_INSUFFICIENT_BALANCE, details.reason = monthly_budget_exceeded |
| Месячный лимит ключа Один ключ, календарный месяц по UTC | Необязательная сумма в долларах; её задаёте вы в разделе «Ключи API» | 402 ERR_INSUFFICIENT_BALANCE, details.reason = monthly_budget_exceeded |
| Блокировка при ошибках доступа IP-адрес, с которого шли запросы | 30 отказов 401 или 30 отказов 403 в минуту (считаются отдельно); блокировка до 120 секунд | 429 ERR_RATE_LIMIT, details.reason = burst_block |
Частота запросов
В счёт частоты входят запуск генераций, загрузка файлов, чтение каталога моделей и чтение баланса. Опрос задания считается отдельно, по правилу ниже. Дополнительные ключи этот счёт не увеличивают.
Ответ при превышении содержит details.limit, details.window = "1m" и details.retry_after, а в заголовке — Retry-After.
Параллельные генерации
Задания в очереди и в работе занимают место в лимите аккаунта до завершения. Если ответ содержит details.scope = "account", дождитесь готовых заданий и отправляйте новые реже.
Для массовой отправки держите свою очередь: запускайте новые задания по мере того, как освобождаются места, а не пачкой.
Интервал опроса
Опрашивайте одно задание одним ключом не чаще раза в 5 секунд. Слишком ранний опрос получает 429 с details.min_interval_seconds = 5. Ждите не меньше большего из этого числа и Retry-After: заголовок иногда указывает меньший интервал.
Прекращайте опрос, когда статус стал completed или failed. Чтобы не опрашивать вовсе, используйте вебхуки; как получить результат — в разделе «Задачи и статусы».
Загрузка образцов
Аккаунт, который зарегистрировался сам и ещё ни разу не пополнял баланс, может использовать не больше 100 образцов в сутки — по календарным суткам UTC. В счёт идут и файлы, загруженные через POST /uploads, и адреса в image_urls. Лимит проверяется до загрузки, скачивания и списания: баланс при отказе не меняется.
После первого пополнения лимита нет. Другие аккаунты им не ограничены.
При превышении приходит 429 ERR_RATE_LIMIT с details.limit, details.window = "1d" и details.retry_after, а в заголовке — Retry-After. Пополните баланс, и лимит исчезнет; иначе дождитесь следующих суток.
Месячные лимиты трат
Месячный лимит — необязательный предел расходов. По умолчанию его нет. Задать его можно двумя способами, и работают они вместе:
- Лимит аккаунта — на все ключи вместе. Его задают в кабинете, в разделе «Баланс и пополнение».
- Лимит ключа — только на один ключ. Его задают в разделе «Ключи API».
Считаются списания за генерации в пределах календарного месяца по UTC; возврат за неудачную картинку освобождает сумму. Когда исчерпан любой из двух лимитов, следующий запрос на генерацию получает 402 ERR_INSUFFICIENT_BALANCE с details.reason = monthly_budget_exceeded и числовым полем details.cap в долларах. Деньги при этом не списываются.
Это жёсткий предел: пока месяц не сменился или вы не подняли лимит, новые генерации не принимаются.
Блокировка при ошибках доступа
Остановите повторы при 401 и 403 и устраните причину: неверный ключ, отключённый аккаунт. Повторные 401 могут заблокировать API-трафик с вашего IP-адреса на время; повторные 403 блокируют публичный API с этого адреса, а кабинет остаётся доступен.
Интеграции за общим NAT делят один IP-адрес, а значит, и эту блокировку. При burst_block подождите Retry-After и сначала исправьте причину отказов.
Примеры ответов
Значения заголовков здесь для примера: читайте их в каждом ответе. Формат — стандартный, как в разделе «Коды ошибок».
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 } } }
Повторы при 429
Ждите не меньше Retry-After секунд и добавляйте небольшую случайную задержку, чтобы процессы не повторяли запрос одновременно. Ограничьте число попыток и сохраняйте тело запроса, ключ API и X-Idempotency-Key: повтор той же отправки тогда не создаст второе задание.
Пока первая отправка ещё обрабатывается, повтор с тем же ключом повтора может вернуть details.reason = "idempotency_in_flight" — подождите и спросите ещё раз (подробнее).
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}", # один и тот же на все попытки "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: # блокировку и последнюю попытку отдаём наверх return response wait = int(response.headers.get("Retry-After", "2")) # ждём не меньше Retry-After time.sleep(max(0, wait) + random.uniform(0, 1))
// Node.js 22+, файл .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", // один и тот же на все попытки "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) { // блокировку и последнюю попытку отдаём наверх return response; } const wait = Number(response.headers.get("Retry-After") ?? 2); const delay = Math.max(0, wait); // ждём не меньше Retry-After await sleep((delay + Math.random()) * 1000); } }
Пример повторяет только 429, остальные ответы отдаёт вашему коду, а при burst_block останавливается. Если соединение оборвалось или ответ потерялся, сохраните тот же ключ и проверьте известное задание перед новой отправкой.
Частые вопросы
Можно ли поднять лимит?
Увеличат ли лимит дополнительные ключи?
Как опрашивать задание, чтобы не получить 429?
completed или failed. Ещё проще подписаться на вебхук: тогда опрос не нужен.Что делать, если пришёл 429 burst_block?
Retry-After.