Skip to content

Rate limits and quota ​

Two separate counters guard the API.

  • Rate limit: requests per minute, per key. Smooths bursts.
  • Quota: requests per UTC day on paid plans, per calendar month on the trial, per account. Sets the plan.

Both are enforced at the edge, before a request reaches the index, so a rejected call is cheap for both of us.

Reading the headers ​

Every response carries the state of the minute window:

HeaderMeaning
X-RateLimit-LimitRequests allowed in the window
X-RateLimit-RemainingRequests left in it
X-RateLimit-ResetUnix seconds when the window rolls over
Retry-AfterSeconds to wait. Present on 429 only

Period quota is not in the headers, because it changes too slowly to be worth a byte on every response. Read it from GET /usage, which does not count against either counter.

When you cross a limit ​

Both cases answer 429. The code tells them apart:

json
{ "error": { "code": "rate_limited", "message": "120 requests per minute exceeded", "retryAfter": 27 } }
  • rate_limited: the minute window. Wait retryAfter seconds and repeat the same request.
  • quota_exceeded: the day or the month. Retrying will not help until the counter resets (00:00 UTC on paid plans, periodEnd on the trial), or until the plan changes. Treat it as a state, not a transient error, and stop the loop.

Retry rate_limited with exponential backoff and jitter. A fleet that all retries at Retry-After exactly rebuilds the same spike it just caused.

Plans ​

PlanForRequestsPer minute
TrialTry every endpoint, decide if the corpus fits.500 / month30
StarterOne app or site in production.2,000 / day60
GrowthHigher volume, several products under one account.25,000 / day300
EnterpriseVolume beyond the plans above, or terms of your own.Talk to usTalk to us

Quota is counted per account, not per key. Creating a second key separates your environments; it does not double your allowance.

Paid plan numbers are quoted per integration for now, see Pricing.

Staying under them ​

The index changes once a day at most. Almost every integration that hits a limit is asking the same question repeatedly:

  • Cache word lookups. A word's clip list is stable for hours, see Caching.
  • Store clipId and videoId on your side after the first lookup. Clip metadata and transcripts are immutable for a given clip.
  • Fetch transcripts once per clip, not once per viewing.