subbydocs
Visit Subby Start building

Rate limits

Per-minute request limits by plan, rate limit headers, and how to handle 429 responses.

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

  1. Wait for Retry-After before retrying.
  2. Back off with jitter if you get repeated 429s, so your workers don't all retry at the same moment.
  3. Send an Idempotency-Key with every POST, so retrying is always safe.
  4. 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=100 on 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.