Developers / Rate limits

Rate limits

Each key may make a set number of requests a minute, 120 unless you choose otherwise. Here's how to read the limit and what to do when you hit it.

Updated 4 November 2026API v1.0.1

How the limit works#

  • Each key has its own limit. It isn't shared with your other keys or counted by IP address.
  • A key can send up to its whole limit at once, then refills steadily through the minute. At 120 a minute, that's 2 more requests every second.
  • The limit is set when the key is created, under Requests per minute: empty means 120, and you can choose 1 to 6000. To change it, create a new key.

Headers#

HeaderWhat it says
X-RateLimit-LimitRequests this key may make a minute.
X-RateLimit-RemainingRequests it can make right now.
Retry-AfterOn a 429 only: seconds to wait before you try again.

A request refused before its key is checked, such as a 401 for a missing key, carries none of these.

Over the limit
HTTP/1.1 429
Retry-After: 2
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
Content-Type: application/problem+json

{
  "type": "urn:problem:rate_limited",
  "title": "Too many requests",
  "status": 429,
  "detail": "This key is limited to 30 requests a minute. Retry after 2 seconds.",
  "instance": "/api/v1/subscribers",
  "code": "rate_limited"
}

Stay under it#

  • Use webhooks instead of asking every few seconds whether something changed.
  • Use lookup to find one subscriber instead of paging through all of them.
  • Ask for size=200 when you read in bulk.
  • Spread big jobs out, and slow down when X-RateLimit-Remaining gets low.
  • On a 429, wait Retry-After seconds. Retrying at once only fails again.
// Wait as long as CoreSync asks, then try again.
async function withRateLimit(call, tries = 5) {
  for (let i = 1; ; i++) {
    try {
      return await call();
    } catch (err) {
      if (err.status !== 429 || i === tries) throw err;
      await new Promise((r) => setTimeout(r, (err.retryAfter || 1) * 1000));
    }
  }
}

const plans = await withRateLimit(() => api("/plans", { query: { status: "ACTIVE" } }));
NextVersioning →

Stuck, or missing something? Tell us what you're building.

hello@coresyncisp.com