Skip to main content
API rate limiting and quotas.

Default limits

Rate limit headers

Every response includes rate limit headers:

Rate limit response

When rate limited, you’ll receive:
HTTP Status: 429 Too Many Requests

Best practices

1. Implement exponential backoff

2. Use batch endpoints

Instead of individual requests:

3. Cache results

Per-endpoint limits

Some endpoints have specific limits:

Request size and time limits

Beyond request-count quotas, the API enforces hard size and wall-clock bounds on expensive operations. These limits are fixed and apply to every plan tier.

/verify/stats upload limits

Statistical verification accepts a CSV upload, and both the transfer and the parsed dataset are capped: The byte cap is enforced while the body is received, before any parsing starts, so chunked uploads without a Content-Length header are bounded too. The cell cap is enforced during parsing: QWED reads the CSV in chunks and aborts with 413 the moment the accumulated row × column count crosses the budget, so a compact but very wide file cannot allocate an oversized DataFrame. Empty or column-less CSVs return 400. On 503, retry after a short delay. On 413, reduce the file size or split the dataset — the limit cannot be raised per request.

LLM provider call timeout

Every outbound LLM provider call (translation and codegen for natural-language verification) is pinned to a 30-second HTTP timeout with SDK retries disabled. A stalled provider surfaces as a bounded verification failure instead of holding the request open. Implement retries in your client if you need them; see best practices.

Consensus deadline

/verify/consensus runs all engines under a single 30-second aggregate deadline. Engines that miss the deadline are returned as explicit BLOCKED results rather than hanging the request or returning HTTP 500. See Consensus engine — execution deadlines.

Math expression compute-cost bounds

Math expressions whose exact evaluation would be unboundedly expensive (huge integer literals, oversized exponents, power towers, large factorials) are rejected before evaluation. See Math engine — compute-cost bounds.

Per-IP limits on authentication endpoints

Anonymous /auth/* routes such as POST /auth/signup and POST /auth/signin carry no API key, so the per-key limiter cannot apply. As of v7.2, these routes are rate limited per client IP instead. This blocks password-guessing and prevents unauthenticated requests from saturating the service with expensive password hashing. When the limit is exceeded, the API returns 429 Too Many Requests with a Retry-After header (always at least 1 second):

Client IP resolution behind proxies

By default the direct peer address is the rate-limit key and the X-Forwarded-For header is ignored, so a client cannot mint fresh quotas by rotating spoofed header values. If QWED runs behind a load balancer or reverse proxy, set QWED_AUTH_TRUSTED_PROXIES to the proxy’s address range:
When the direct peer matches a trusted proxy, QWED uses the rightmost X-Forwarded-For hop as the client IP. Trusted proxies append the real client address after any client-supplied entries, so clients still cannot choose their own bucket. Port suffixes (1.2.3.4:8080, [2001:db8::1]:8080) are stripped before bucketing.
Per-IP buckets are process-local. Running multiple workers or replicas multiplies the effective per-IP budget by the process count. Run a single replica for exact limits, or move rate limiting to a shared store such as Redis before scaling out.

Thread-safe in-memory limiter

The default in-memory rate limiter is thread-safe. All check-and-record operations (per-key and global) are protected by a lock, making it safe to use with multi-threaded ASGI servers such as Uvicorn with multiple workers. The get_reset_time method also operates under the lock to prevent stale reads.

Fail-closed enforcement

When using Redis-backed rate limiting, the rate limiter operates with a fail-closed policy. If the Redis backend encounters an error at runtime, requests are denied rather than allowed through. This ensures that a temporary Redis outage does not silently bypass rate limits. If Redis is unavailable at startup, an in-memory fallback is used until the service is restarted with a healthy Redis connection.

Enterprise options

For higher limits, contact us for:
  • Custom rate limits
  • Dedicated infrastructure
  • SLA guarantees