Skip to main content

Rate Limiting

Saturday meters requests with a token bucket per account, not per key. Several keys on one account draw from the same bucket. Two ceilings apply: Self-serve accounts run at 2 requests/second with a burst of 5, and 200 calls/day. Platform partner limits are set per agreement and carry no daily ceiling by default. A self-serve account can read its own current numbers from GET https://api.saturday.fit/v1/ without authenticating.

Rate limit headers

Every authenticated response carries the current bucket state:
X-RateLimit-Reset is a delta in seconds, not a Unix timestamp. Adding it to the current time gives the moment the next request will be admitted.

When you’re rate limited

Exceeding a ceiling returns 429 Too Many Requests:
Three cases produce a rate_limit_error, and they want different handling: Read Retry-After with a fallback rather than indexing it, since two of the three cases omit it:
Athlete-delegated callers (OAuth2 and the Claude connector) also pass through a per-athlete bucket inside the account’s bucket, so one heavy user cannot starve the rest. Those 429s carry a longer Retry-After. See OAuth2.

Daily call limits

Alongside the token bucket, every account carries daily call ceilings: Intelligence endpoints (nutrition, products, inference, knowledge, AI) also carry their own daily ceiling, separate from the total. Data endpoints (your athletes, activities, organizations, webhooks) are not counted against it, so hitting the intelligence ceiling never blocks syncing your own data. Without an agreed intelligence ceiling, your budget grows with your day: a base allowance plus a per-athlete allowance for every athlete you compute for that day. Integrations serving real athletes scale automatically; if your traffic pattern needs more than the budget provides, contact api@saturday.fit. Request-pattern friction (rate_limited) also bounds daily variety on a few surfaces: distinct product lookups, distinct search queries, and calculations that carry no athlete. Repeats always serve, so a real workload (your athletes’ usual products, revisited) never feels these; enumeration does. These 429s carry no Retry-After; novel inputs resume at midnight UTC. Reaching a ceiling returns 429 Too Many Requests without a Retry-After header; the message names the limit, and counters reset at midnight UTC. GET /v1/partner reports the ceilings that apply to your account (rate_limits.requests_per_day and rate_limits.ip_requests_per_day, null when none applies). To raise yours, contact api@saturday.fit.

Staying under the ceilings

Spread requests out

The burst allowance covers a short spike, then refills at the sustained rate. Pacing requests across the window keeps the bucket from emptying; draining the burst up front means every subsequent request waits.

Cache prescriptions

A prescription for the same inputs doesn’t change on its own. Cache the result and recalculate when:
  • The athlete’s profile settings change
  • Activity parameters change, such as an updated duration or a new weather forecast
  • You want a fresh calculation for race day

Use the batch endpoint

Each item in a batch debits a token, so a batch of 10 costs what 10 calls cost. What it saves is round trips, not quota. See Batch Operations.

Watch your usage

GET /v1/partner/usage/daily breaks the same counters down by day.

Requesting higher limits

Outgrowing the ceilings is the point at which we want to hear from you. Send your account or partner ID and expected volume to support@saturday.fit. Raising a limit costs nothing.