Knowing where you stand
Every non-304 response on /v1/* carries the standard RateLimit headers, so a client can
slow down before it is refused rather than after:
remaining is what is left in the current window, and reset is the seconds until it
refills.
A 304 Not Modified carries none of these headers — they come from the rate limiter, and the
caching middleware that produces a 304 replaces the response before it reaches the client,
headers included. Don’t rely on seeing them on every request; /health and /openapi.json
are unmetered and never carry them either.
Being refused
Over budget, the API answers429:
reset seconds and retry. Nothing is charged against the budget by a request that
was refused for a bad key — the limiter runs after authentication, keyed to the key itself.
Staying under it
The catalog changes slowly, so caching is still worth doing — it just doesn’t stretch this budget. Responses on/v1/* carry an ETag, and a client that sends If-None-Match gets a
304 Not Modified for anything it already holds, saving the bandwidth and the parsing. It
does not save a request: the limiter counts a conditional request before the 304 is
produced, so it costs exactly as much of the 300-per-minute budget as a full 200 would. The
only way to stay under the limit is to make fewer requests — poll less often, or ask for a
wider page with a larger limit instead of paging through many small ones.