Limits and rate limits

Concurrency, requests-per-minute, key quota and 5h / 1d / 7d spend windows and plan limits on BigModel.io, the 429 errors each returns, and how to retry with backoff.

On this page
  1. Concurrency
  2. Requests per minute
  3. Account spend caps
  4. Key quota and spend windows
  5. Plan limits
  6. Rate-limit headers
  7. Retry with backoff
  8. Troubleshooting
  9. Related

BigModel.io applies several independent limits. Each one returns HTTP 429 (402 for account spend caps, 403 for balance) with an error that names it, so read the code before you retry.

Limit Scope Set by Error Retry-After
Concurrency User BigModel.io (per account) 429 rate_limit_error "Concurrency limit exceeded for user" or "Too many pending requests" No
Requests per minute (RPM) Group and user BigModel.io (per group / account) 429 rate_limit_exceeded Yes
Key quota Key You 429 API_KEY_QUOTA_EXHAUSTED No
Spend windows 5h / 1d / 7d Key You 429 rate_limit_exceeded "api key 5小时限额已用完" (or 日 / 7天) No
Plan limits daily / weekly / monthly Plan Plan definition 429 USAGE_LIMIT_EXCEEDED No
Account spend caps weekly / monthly Account You 402 spend_cap_reached Yes, until the reset
Free-model calls at a zero balance User BigModel.io 429 rate_limit_exceeded Yes
Balance Account Your top-ups 403 INSUFFICIENT_BALANCE No
Upstream provider limits Model provider Provider 429 rate_limit_error Passed through if sent

There is no per-key RPM or concurrency setting; RPM and concurrency apply to your account and the key's group.

#Concurrency

Each user has a maximum number of requests in flight at once, set per account. When all slots are busy, further requests wait briefly in a queue:

  • If the queue is full, the request is rejected at once with 429 "Too many pending requests, please retry later".
  • If a queued request waits too long for a slot, it fails with 429 "Concurrency limit exceeded for user, please retry later".

Streaming requests hold their slot until the stream ends, so long agent sessions use concurrency for longer. If you run many requests in parallel, cap your own client's parallelism and retry these 429s with backoff.

#Requests per minute

Groups and users can have an RPM limit, set by BigModel.io per group and per account. When it is exceeded, the response is 429 rate_limit_exceeded with a Retry-After header giving the seconds left in the current minute. Wait that long and retry.

While your balance is zero, calls to models priced at $0 have their own per-minute limit, reported the same way. Topping up removes it. See Trial credit & free models.

#Account spend caps

On Balance & billing you can set a weekly and a monthly USD cap on balance spend. Weeks start Monday 00:00 UTC and months on the 1st at 00:00 UTC. When a cap is reached, requests return 402 spend_cap_reached with Retry-After set to the seconds until the reset. Models priced at $0 stay available. Don't retry a 402 in a loop: wait for the reset or change the cap.

#Key quota and spend windows

You set these yourself per key in API Keys:

  • Quota caps total USD spend on the key (0 = unlimited). When used up: 429 API_KEY_QUOTA_EXHAUSTED. You can raise it or reset the used amount.
  • Spend windows cap USD spend per 5 hours, 1 day and 7 days (0 = unlimited).

Windows are fixed, not rolling. A window starts when the key is first used, and resets once its duration has passed. The 429 carries no Retry-After; check reset_at instead:

bash
curl https://bigmodel.io/v1/usage \
  -H "Authorization: Bearer $BIGMODEL_API_KEY"
json
{
  "mode": "quota_limited",
  "rate_limits": [
    { "window": "5h", "limit": 5, "used": 5, "remaining": 0, "window_start": "...", "reset_at": "..." }
  ]
}

GET /v1/usage works even when the key is exhausted or expired. See Per-key limits & budgets.

#Plan limits

Keys in a plan group are limited by the plan's daily, weekly and monthly USD limits. When one is reached, requests return 429 USAGE_LIMIT_EXCEEDED until the period resets. GET /v1/usage shows the plan's usage and limits under subscription.

#Rate-limit headers

The gateway does not add its own x-ratelimit-* headers. If the model provider sends x-ratelimit-* or retry-after, they are passed through. The RPM limit above sets Retry-After itself.

#Retry with backoff

Retry 429 rate limits and 5xx errors; do not retry 400, 401, 402, 403 or quota / window / plan errors, which will fail the same way until something changes. Honour Retry-After when present, otherwise back off exponentially with jitter.

Python
import os, random, time
import requests

URL = "https://bigmodel.io/v1/chat/completions"
HEADERS = {"Authorization": f"Bearer {os.environ['BIGMODEL_API_KEY']}"}
NO_RETRY = {"API_KEY_QUOTA_EXHAUSTED", "USAGE_LIMIT_EXCEEDED", "INSUFFICIENT_BALANCE"}

def chat(body, max_attempts=5):
    for attempt in range(max_attempts):
        r = requests.post(URL, headers=HEADERS, json=body, timeout=600)
        if r.status_code < 400:
            return r.json()
        err = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
        code = err.get("code") or (err.get("error") or {}).get("type")
        message = (err.get("message") or (err.get("error") or {}).get("message") or "")
        retryable = r.status_code >= 500 or (
            r.status_code == 429 and code not in NO_RETRY and "限额" not in message
        )
        if not retryable or attempt == max_attempts - 1:
            raise RuntimeError(f"{r.status_code} {code}: {message} (request {r.headers.get('X-Request-ID')})")
        wait = float(r.headers.get("Retry-After") or min(30, 2 ** attempt))
        time.sleep(wait + random.random())

print(chat({"model": "glm-5.3", "messages": [{"role": "user", "content": "Hello!"}]}))
Node.js
const URL = "https://bigmodel.io/v1/chat/completions";
const NO_RETRY = new Set(["API_KEY_QUOTA_EXHAUSTED", "USAGE_LIMIT_EXCEEDED", "INSUFFICIENT_BALANCE"]);

async function chat(body, maxAttempts = 5) {
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
    const r = await fetch(URL, {
      method: "POST",
      headers: { Authorization: `Bearer ${process.env.BIGMODEL_API_KEY}`, "Content-Type": "application/json" },
      body: JSON.stringify(body),
    });
    if (r.ok) return r.json();
    const err = await r.json().catch(() => ({}));
    const code = err.code ?? err.error?.type;
    const message = err.message ?? err.error?.message ?? "";
    const retryable = r.status >= 500 || (r.status === 429 && !NO_RETRY.has(code) && !message.includes("限额"));
    if (!retryable || attempt === maxAttempts - 1) {
      throw new Error(`${r.status} ${code}: ${message} (request ${r.headers.get("x-request-id")})`);
    }
    const wait = Number(r.headers.get("retry-after")) || Math.min(30, 2 ** attempt);
    await new Promise((res) => setTimeout(res, (wait + Math.random()) * 1000));
  }
}

console.log(await chat({ model: "glm-5.3", messages: [{ role: "user", content: "Hello!" }] }));

The OpenAI and Anthropic SDKs already retry 429 and 5xx with backoff (max_retries / maxRetries, default 2). Raise it for batch jobs rather than wrapping the SDK in another retry loop. To spread load, keep the number of parallel requests at or below your concurrency limit.

#Troubleshooting

429 "Too many pending requests". You are sending far more parallel requests than your concurrency. Limit parallelism in your client (a worker pool or semaphore).

429 "Concurrency limit exceeded for user". Requests queued too long. Reduce parallel requests, or shorten long streams. Contact Support if you need a higher limit.

429 rate_limit_exceeded with Retry-After. The RPM limit; wait the given seconds.

429 rate_limit_exceeded "api key 5小时限额已用完". A key spend window. Wait for reset_at, raise the window or reset its usage in API Keys.

429 rate_limit_error with no other detail. Usually the model provider's own limit. Retry with backoff, or try another model with the models fallback array.

Updated · View as Markdown