速率限制
API 按团队限制每秒请求数(而不是按密钥):
| 套餐 | 每秒请求数 |
|---|---|
| Free | 10 |
| Pro | 10 |
| Scale | 25 |
| Enterprise | 定制 |
Resend 的限制是每秒 2 个请求。一个最多包含 100 封邮件的批次只算一个请求,因此在该限制内你每秒可以发送数千封邮件。
限制以一秒为窗口。控制台会话不受速率限制。发送配额(套餐与配额)与请求限制是分开的。
每个响应都包含:
| 标头 | 含义 |
|---|---|
ratelimit-limit |
每个窗口允许的请求数(例如 10)。 |
ratelimit-remaining |
当前窗口中剩余的请求数。 |
ratelimit-reset |
距窗口重置的秒数(1)。 |
retry-after |
仅在 429 时出现:重试前需要等待的秒数(1)。 |
HTTP/1.1 429 Too Many Requestsratelimit-limit: 10ratelimit-remaining: 0ratelimit-reset: 1retry-after: 1
{ "statusCode": 429, "name": "rate_limit_exceeded", "message": "Too many requests. You can only make 10 requests per second." }处理 429
Section titled “处理 429”import { SpacePost, type SendEmailOptions } from "@spacepost/node";
const spacepost = new SpacePost();
async function sendWithRetry(email: SendEmailOptions, key: string, attempts = 5) { for (let i = 0; i < attempts; i++) { const { data, error } = await spacepost.emails.send(email, { idempotencyKey: key }); if (!error) return data; if (error.name !== "rate_limit_exceeded") throw new Error(`${error.name}: ${error.message}`); await new Promise((r) => setTimeout(r, 1000 * (i + 1))); } throw new Error("rate limited");}import time, requests
def post_with_retry(url, headers, json, attempts=5): for _ in range(attempts): r = requests.post(url, headers=headers, json=json, timeout=15) if r.status_code != 429: return r time.sleep(float(r.headers.get("retry-after", 1))) return r重试时请始终复用相同的 Idempotency-Key,这样实际上已经成功的请求就不会被重复执行。
- 优先使用批量发送,而不是大量单封发送。
- 在后台 Worker 中排队发送,并把它的并发数限制在你的限额之内。
- 让导入任务(例如创建联系人)以平稳的节奏进行。