Docs

Rate Limits

Per-key request limits, rate-limit response headers, and how to back off cleanly.

Stile rate-limits API requests per key in fixed one-minute windows. The limits are generous for normal traffic and exist to bound the blast radius of a leaked key or a runaway retry loop.

Limits

Limits are per key, by key type:

Key typeLimit
Secret (stile_sk_)1,000 requests / min
Publishable (stile_pk_)100 requests / min

Publishable keys get a tighter budget because they're exposed in the browser. Limits are per key, not per organization — a separate key for each service gets its own budget.

Rate-limit headers

Authenticated requests processed by the rate limiter include the current state of the window, so you can throttle proactively instead of waiting for a 429:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1741564920
HeaderMeaning
X-RateLimit-LimitYour ceiling for the current window.
X-RateLimit-RemainingRequests left before you're limited.
X-RateLimit-ResetUnix timestamp (seconds) when the window resets.

When you're limited

Exceeding the limit returns 429 Too Many Requests with code rate_limit_exceeded and a Retry-After header (seconds to wait). Honor it:

if (res.status === 429) {
  const retryAfter = parseInt(res.headers.get("Retry-After") || "1", 10);
  await new Promise((r) => setTimeout(r, retryAfter * 1000));
  // retry the request
}

Backend-agnostic retry behavior

Honor Retry-After for 429 responses. For network failures and temporary 5xx responses, use bounded exponential backoff with jitter. Reuse the same Idempotency-Key when retrying writes.

A separate limit protects returning-user lookups

accept_existing is additionally rate-limited to 10 attempts per email per 15-minute window. The eleventh attempt returns 429 accept_existing_rate_limited to prevent credential enumeration. See Returning Users.

Next steps

On this page