Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.qwairy.co/llms.txt

Use this file to discover all available pages before exploring further.

Rate limits ensure fair usage and platform stability. Limits are applied per team, across all API tokens belonging to that team.

Current Limits

Two windows are enforced simultaneously on every request:
WindowLimit
Per-minute (burst)1,000 requests / minute
Per-day (daily cap)20,000 requests / day
A request is accepted only if both windows have budget remaining. If either window is exhausted, the API returns 429 Too Many Requests.
Need higher limits for production workloads (e.g. ingesting data for many brands/domains)? Contact us at team@qwairy.co.

Rate Limit Headers

Every response, including 429s, includes headers for both windows:
HeaderDescription
X-RateLimit-LimitPer-minute request cap
X-RateLimit-RemainingRequests remaining in the current minute window
X-RateLimit-ResetISO 8601 timestamp when the minute window resets
X-RateLimit-Daily-LimitPer-day request cap
X-RateLimit-Daily-RemainingRequests remaining in the current day window
X-RateLimit-Daily-ResetISO 8601 timestamp when the day window resets
Retry-AfterSeconds to wait before retrying, based on the limit actually hit (only set on 429)

Example Headers

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 873
X-RateLimit-Reset: 2026-04-07T09:13:00.000Z
X-RateLimit-Daily-Limit: 20000
X-RateLimit-Daily-Remaining: 4211
X-RateLimit-Daily-Reset: 2026-04-08T00:00:00.000Z
Always check both windows. A request can be rejected while X-RateLimit-Remaining still shows plenty of per-minute budget if the daily cap is exhausted. Conversely, a healthy daily budget doesn’t guarantee the next request will pass the per-minute window.

Handling Rate Limits

When either window is exceeded, the API returns 429 Too Many Requests with a body indicating which window was hit:
{
  "error": "Too Many Requests",
  "limit": "daily",
  "message": "Daily rate limit (20000/day) exceeded. Please try again in 32451 seconds.",
  "retryAfter": 32451
}
The limit field is either "burst" (per-minute) or "daily". Retry-After and the X-RateLimit-*-Reset headers are always aligned with the actual blocker, so you can trust Retry-After without having to inspect the payload.

Best Practices

Trust Retry-After

Use the Retry-After header as-is. It already reflects whichever window (minute or day) is the real blocker.

Watch both remaining headers

Monitor X-RateLimit-Remaining and X-RateLimit-Daily-Remaining to throttle proactively.

Cache responses

Store and reuse data that doesn’t change frequently (brands, competitors, topics).

Batch and filter

Use query filters (provider, period, limit) to fetch only the data you need.

Retry Logic Example

async function fetchWithRetry(url, options, maxRetries = 10) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    const response = await fetch(url, options);

    if (response.status !== 429) return response;

    // Trust the Retry-After header — it points at the real blocker
    // (minute or day window), not just the minute reset.
    const retryAfterSec = Number(response.headers.get('Retry-After') ?? '60');
    const waitMs = Math.max(retryAfterSec * 1000, 1000);

    const body = await response.clone().json().catch(() => ({}));
    console.warn(
      `Rate limited on ${body.limit ?? 'unknown'} window. Retrying in ${waitMs}ms...`
    );

    await new Promise((r) => setTimeout(r, waitMs));
  }

  throw new Error('Max retries exceeded');
}
If you see "limit": "daily" on retry, waiting within the same process rarely helps: the daily window can be hours away. Persist the X-RateLimit-Daily-Reset timestamp and reschedule the job instead of blocking a worker.

Optimizing API Usage

Use Filtering Parameters

Instead of fetching all data and filtering client-side, use query parameters:
# Bad: Fetch all answers, filter in code
GET /api/v1/brands/{brandId}/answers

# Good: Filter at the API level
GET /api/v1/brands/{brandId}/answers?provider=chatgpt&hasSelfMention=true&limit=50

Cache Static Data

Some data changes infrequently and can be cached:
  • Brands list: Changes rarely
  • Competitors list: Changes when you add/remove competitors
  • Topics/Tags: Changes when you modify your workspace

Use Date Ranges

Limit data retrieval to relevant time periods:
# Fetch only last 7 days instead of default 30
GET /api/v1/brands/{brandId}/performance?period=7

Need Higher Limits?

If 20,000 requests per day is too tight for your ingestion pipeline, contact us at team@qwairy.co with your use case and expected volume. We can raise the daily cap on your team.