Generous, predictable, and in the headers.
Limits are per key and reported on every response, so your sync can pace itself instead of guessing.
Draft limits
These are starting proposals, not commitments. If a nightly job-cost sync or a month-end pay app run would hit them, tell us. That's exactly what early access is for.
- Reads100 requests / second per key
GET on any resource - Writes25 requests / second per key
POST, PATCH, DELETE - List page sizeUp to 100 objects
Use cursors, not offsets - Concurrent requests20 in flight per key
Queue the rest client-side - Webhook endpoints16 per account
Each can subscribe to any events
Headers
Every response includes RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds). A 429 adds Retry-After.
429 response
HTTP/2 429
RateLimit-Limit: 100
RateLimit-Remaining: 0
RateLimit-Reset: 4
Retry-After: 4
Content-Type: application/json
{
"error": {
"type": "rate_limited",
"message": "Too many requests. Retry after 4 seconds.",
"request_id": "req_Z1q9d"
}
}Back off, then retry
On 429 or 5xx, wait for Retry-After (or exponential backoff with jitter) and try again. Reuse the same Idempotency-Key so a retried write never posts twice.
Bulk work? Prefer webhooks over polling, and expand[] over N+1 fetches. One change order with its RFI and pay app is one request.
Retry helper
async function call(url, init, tries = 5) {
for (let i = 0; i < tries; i++) {
const res = await fetch(url, init);
if (res.status !== 429 && res.status < 500) return res;
const wait = Number(res.headers.get("Retry-After")) || 2 ** i;
await new Promise(r => setTimeout(r, (wait + Math.random()) * 1000));
}
throw new Error("gave up after retries");
}
// Same Idempotency-Key on every retry: a write lands once.import random, time, requests
def call(method, url, tries=5, **kw):
for i in range(tries):
res = requests.request(method, url, **kw)
if res.status_code != 429 and res.status_code < 500:
return res
wait = float(res.headers.get("Retry-After", 2 ** i))
time.sleep(wait + random.random())
raise RuntimeError("gave up after retries")
# Same Idempotency-Key on every retry: a write lands once.