Rate limits protect the API for everyone by capping how many requests you can send per minute. They are separate from metering:
- Metering decides what you're billed for each month. Only write requests are metered.
- Rate limits decide how fast you can send requests. All requests count toward rate limits, including
GET.
"Unlimited reads" means reads are never billed. It doesn't mean reads can be sent at any speed.
Limits by plan
| Plan | Live requests per minute | Burst |
|---|---|---|
| Starter | 60 | Up to 10 in one second |
| Growth | 300 | Up to 25 in one second |
| Scale | 1,000 | Up to 60 in one second |
| Enterprise | 3,000 (can be raised) | Agreed with you |
| Sandbox (any plan) | 100 per key | Up to 25 in one second |
Limits apply per account per environment. All live keys on your account share the live limit.
There are no daily limits and no monthly caps on requests. Your monthly allowance only affects billing.
Rate limit headers
Every response includes:
RateLimit-Limit: 300
RateLimit-Remaining: 287
RateLimit-Reset: 42
| Header | Meaning |
|---|---|
RateLimit-Limit |
Requests allowed in the current one-minute window |
RateLimit-Remaining |
Requests left in the current window |
RateLimit-Reset |
Seconds until the window resets |
When you hit the limit
You'll receive 429 Too Many Requests with a Retry-After header in seconds:
HTTP/1.1 429 Too Many Requests
Retry-After: 12
RateLimit-Limit: 300
RateLimit-Remaining: 0
RateLimit-Reset: 12
{
"success": false,
"error": {
"type": "rate_limit_error",
"code": "rate_limited",
"message": "Too many requests. Retry after 12 seconds.",
"request_id": "req_Qm29xLp0a",
"doc_url": "https://docs.mysubbyapp.com/errors#rate_limited"
}
}
Rate-limited requests are not processed and are never metered.
Handling 429s well
- Wait for
Retry-Afterbefore retrying. - Back off with jitter if you get repeated 429s, so your workers don't all retry at the same moment.
- Send an
Idempotency-Keywith everyPOST, so retrying is always safe. - Spread bulk jobs out. Importing 10,000 customers? Run them through a queue at a steady pace below your limit.
async function subbyRequest(url, options, attempt = 0) {
const res = await fetch(url, options);
if (res.status !== 429 || attempt >= 5) return res;
const retryAfter = Number(res.headers.get('Retry-After') ?? 1);
const jitter = Math.random() * 500;
await new Promise((r) => setTimeout(r, retryAfter * 1000 + jitter));
return subbyRequest(url, options, attempt + 1);
}
Using fewer requests
- Use webhooks instead of polling for status changes.
- Use
limit=100on list endpoints to fetch more per request. - Cache plans on your side. They rarely change.
Need a higher limit?
Scale and Enterprise accounts can request higher limits from Dashboard → Developers → Rate limits → Request increase. Tell us your expected peak requests per minute and what's driving it.