baba/apiOpenAPI schema

Documentation

View .md

Rate limits and quota

Two separate limits apply, and they fail differently.

The rate limit is per minute and protects the service from a burst. The quota is per calendar month, UTC, and is what you are paying for. Hitting the first means slow down; hitting the second means the month is spent.

PlanRateMonthly quota
Starter60 per minute10,000
Team300 per minute100,000
Enterprise1,000 per minute1,000,000

Headers

Every authenticated response carries the current state, so you never have to guess.

HeaderMeaning
X-RateLimit-LimitRequests allowed this minute on this plan.
X-RateLimit-RemainingRequests left in the current minute.
Retry-AfterSeconds to wait. Present on both kinds of 429.
X-Request-IdUnique id for this request. Quote it in support.

The two 429s

Rate limited
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 60

{"error":{"code":"rate_limited","message":"Rate limit exceeded. Slow down and retry."}}
Quota exceeded
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 0
Retry-After: 1209600

{"error":{"code":"quota_exceeded","message":"Monthly quota exceeded."}}

Read the code, not the status. rate_limited clears within the minute. quota_exceeded clears when the UTC month rolls over or when you change plan, and its Retry-After can be a fortnight, so a client that blindly sleeps on it will hang.

Backoff

Sleep for Retry-After seconds and retry once. If you are running many workers, add jitter so they do not all wake at the same instant.

A 503 unavailable is retryable with exponential backoff. A 400, 401, 403 or 404 is not: retrying an unchanged request produces the same answer.

Spending less

  • Send If-None-Match with the previous ETag. A 304 costs a request but no payload, and the brief and story detail change rarely.
  • Poll the change feed rather than re-listing everything. GET /api/v1/changes?since=… returns only what moved.
  • Raise limit to 100 rather than paging in 40s.