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 时,请停止轮询。要完全避免轮询,请使用 Webhook;如何获取结果,见“任务与状态”。
参考图上传
自行注册且从未充值过的账号,每天最多可使用 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 可能会让来自你 IP 地址的 API 流量被暂时限制;反复出现的 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。更简单的办法是订阅 Webhook:这样就不需要轮询。收到 429 burst_block 怎么办?
Retry-After 之后恢复工作。