Request Limits

Overview

Opora enforces rate limits at the network edge to protect service reliability for all users. Limits apply at the Cloudflare Worker layer before any AI processing occurs. You will never be billed API credits for a rate-limited request.

The vast majority of operators will never encounter a rate limit under normal usage. The limits described here are designed to prevent automated abuse, not to restrict legitimate operator workflows.

The three tiers

Per-IP global — 60 requests per minute

Every request from your IP address counts toward a global 60 req/min limit, regardless of which tool you use or whether you are signed in.

Who this affects: Automated scripts, browser extensions, or unusual usage patterns that send requests far faster than a human operator would. Normal operators running tools at a steady pace generate 3–10 requests per session — well under this limit.

Per-browser — 30 requests per minute

Opora identifies individual browser sessions using a lightweight fingerprint. Anonymous visitors (not signed in) are limited to 30 requests per minute per browser. This tier protects against scripts that cycle through IP addresses while staying in the same browser profile.

Signed-in users are identified by their account rather than their browser, so this tier has less impact on authenticated traffic.

Per-tool — 10 requests per minute

Each AI tool (Bid Drafter, RFP Decoder, Handbook Drafter, and others) has a separate 10 req/min limit per identity — your user ID if signed in, otherwise your browser or IP.

This limit prevents a single session from monopolizing a computationally intensive tool while other operators are trying to use it. In practice, you can use multiple tools in parallel without hitting this limit — the 10 req/min cap only triggers if you submit the same tool more than 10 times in 60 seconds, a pattern that occurs only with automation.

What you see when a limit is reached

When any limit is exceeded, the Opora web application displays a friendly message and automatically retries once the window resets. You do not need to reload the page.

If you are making API requests directly, the response is:

HTTP 429 Too Many Requests
Retry-After: <seconds>
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Please wait a moment and try again.",
    "request_id": "...",
    "retry_after_seconds": 42
  }
}

The retry_after_seconds field tells you exactly how long to wait before your next request will succeed. The request_id can be shared with support if you believe the limit was applied in error.

Anonymous (not signed in) limits

Visitors who have not signed in are also subject to a daily free-tier limit: 3 free runs per tool per day, enforced at the database layer. Once exhausted, you will see a 402 Payment Required response with a link to start your free 30-day trial.

The edge rate limits above are in addition to the daily free-tier limit — they protect the service from abuse even before a tool run is counted.

Limits by plan

Plan Per-IP Per-browser Per-tool
Free trial 60/min 30/min 10/min
Solo / Pro / Team 60/min 30/min 10/min
Enterprise Custom Custom Custom

All current paid plans share the same edge rate limits. Enterprise customers can request higher limits through their account manager.

Paths that are never rate limited

Path Purpose
/api/health Service health check
/api/_internal/metrics Internal observability (admin only)
/api/webhooks/* Inbound webhooks (Clerk, Stripe)

How to avoid hitting limits

  • Sign in. Authenticated users have their identity tied to their account, which gives more predictable limit behavior across devices and avoids the stricter anonymous-browser tier.
  • Pace your requests. If you are using Opora programmatically or building an integration, add a short delay between requests — 1–2 seconds is sufficient.
  • Contact support if your legitimate workflow requires higher limits. Enterprise plans include custom rate limit configuration.

Technical reference

The edge rate limiter uses a fixed-window counter algorithm backed by Cloudflare KV. Windows are 60 seconds. Limits reset on the window boundary (not a rolling window). Response headers on allowed requests:

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 57

Response headers on blocked requests:

Retry-After: 23
X-RateLimit-Remaining: 0