速率限制与配额:这里到底卡在哪
没有 RPM 档位,也没有 TPM 上限。真正卡住你的是余额、单 key 配额,以及两个 model id 上的并发限制。
没有 RPM,也没有 TPM 档位
推理路径上既没有 requests-per-minute,也没有 tokens-per-minute。没有需要往上爬的用量档位,没有按账户划分的吞吐等级,也没有「消费到某个额度才解锁」这回事——迁移检查清单上这一项可以直接划掉。
真正约束你的是三件事:钱包里有没有钱、这把 key 本身设没设配额上限,以及仅对两个特定 model id 而言,你同时有多少请求在飞。
以上说的都是网关自己的规则。它背后的上游 provider 各有各的限制,某一家拒绝了请求,那个拒绝会作为 429 转发给你,并带上该 provider 设定的 Retry-After。
余额与单 key 配额
请求转发前,网关先决定这次由哪个钱包出钱。auto 模式的 key 依次看充值余额、贡献收益、活动奖励,取第一个有钱的;绑定了单一钱包的 key 则只查那一个。没有可用钱包就是 403,消息里会写明是哪个余额空了。
每把 key 还能单独设配额上限,与账户余额无关。用完返回 402 "api key quota exceeded"——想给某个服务或某个环境单独封顶、又不影响账户其他部分时,这个很好用。
有两条规则是特例而非通则。Claude 系列要求充值余额不低于 $2.00,且只从充值钱包扣,不满足返回 402 claude_minimum_balance。stable-* 通道则直接拒收贡献收益,返回 402 earned_credit_not_accepted——因为这条通道是我们向外部供应商买的,不是由贡献池承载的。
#!/usr/bin/env bash
set -euo pipefail
for attempt in 1 2 3 4 5; do
status=$(curl -sS -o /tmp/resp.json -D /tmp/resp.headers -w '%{http_code}' \
https://token-share.app/v1/messages \
-H "x-api-key: $TOKEN_SHARE_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 256,
"messages": [{"role": "user", "content": "ping"}]
}')
if [ "$status" != "429" ] && [ "$status" != "503" ]; then
cat /tmp/resp.json
exit 0
fi
# Honour Retry-After when present; otherwise back off exponentially.
wait=$(awk 'tolower($1) == "retry-after:" { print $2 }' /tmp/resp.headers | tr -d '\r')
sleep "${wait:-$((2 ** attempt))}"
done
echo "gave up after 5 attempts" >&2
exit 1两个 id 上的并发限制,以及花费是怎么记的
带并发上限的只有两个 id:claude-sonnet-5 和 gpt-5.6-luna,而它们对「通道满了」的处理方式恰好相反。Sonnet 会让你进 FIFO 队列等空位,等满 30 秒还没轮到才返回 429 model_queue_timeout;Luna 不排队,没空位就立刻拒,返回 429 model_capacity_exceeded 并带 Retry-After: 1。
这是取舍,不是优劣。排队把突发变成延迟,适合宁可等也不想重试的批处理;快速失败把突发变成即时错误,适合宁可重试也不愿挂在一条不动的连接上的交互式调用。哪种更对,取决于你的调用方等不等得起。
还有一点关于扣费:费用是请求完成之后扣,不做事前预留。转发前那道检查只问「钱包是不是非空」,所以一批并发请求打在快见底的余额上,是可能把它带到零以下的,亏空会被记录而不是被抹掉。另外每次计费请求最低按 $0.0001 收,极小的调用也不免费。