Rate Limits

How Selyf's API throttles requests -- the global default, per-route limits, and AI token budgets.

Global default

100 requests / 60 seconds per client, configurable

Applies to every route that has no more specific limit of its own. The numbers shown here are this codebase’s schema defaults (RATE_LIMIT_MAX / RATE_LIMIT_WINDOW_SECONDS) -- an operator can configure different values; this page does not claim to know this specific production deployment’s live configuration.

Authentication routes

20 requests / 60 seconds, fixed

GET /auth/google, GET /auth/google/callback, POST /auth/google/disconnect, and DELETE /auth/account -- the highest-value target for brute-force or account-enumeration attempts, so this limit is a fixed code constant, not environment-configurable.

Mailbox sync

10 requests / 60 seconds, fixed

POST /api/mail/sync. A sync already in progress for the account also returns RATE_LIMITED immediately, independent of this window, so two overlapping syncs never run at once.

AI analysis & drafting

20 requests / 60 seconds, fixed

POST /api/mail/threads/:threadId/analyze and POST /api/mail/threads/:threadId/draft. This is defense in depth on top of the real cost control below (the per-account token budget) -- it bounds how fast either endpoint can be probed regardless of budget.

Analytics

60 requests / 60 seconds, fixed

POST /api/analytics/event. Generous relative to the limits above -- these are cheap UI-interaction pings, not Gmail or AI-provider calls, so the real cost control is the fixed event allowlist, not this number.

AI token budgets

Independent of the request-rate limits above, every AI call is checked against a per-account daily and monthly token budget (input plus output tokens) before it is made. This codebase’s schema defaults are 20,000 tokens/day and 200,000 tokens/month -- again, configurable defaults, not a claim about this deployment’s live values. Exceeding either returns AI_BUDGET_EXCEEDED; see Errors for what that means for a client.

Handling a 429 or 503

A rate-limited or temporarily-unavailable response includes a Retry-After header naming the number of seconds to wait. See API Reference for the exact limit and error codes each route can return.