RevorRevor

Rate limits, concurrency, and retries

REVOR AI enforces request rate, active-job concurrency, and credits as three independent controls. The API and MCP share account-wide allowances; creating more API keys or changing protocols does not increase them.

Requests per minute (RPM)

RPM is calculated per account and operation type. Each type has its own one-minute window.

Operation typeTypical endpoints or toolsFreeStarterScaleProEnterprise
ReadCredits, Connect, prospect-list indexes and details3060120240600
Job pollingGET /jobs/{id}, revor_get_job1202405001,0003,000
Data-task creationWeb research, contacts, customs, prospect-list creation25102060
Outreach writeEmail, LinkedIn, and WhatsApp outreach or engagement510203060

Cancelling a queued job is treated as a lightweight read/control operation. Customs company-name resolution is currently free, but it starts a data lookup and therefore uses the data-task creation allowance.

Shared account and API-key limits

Membership RPM is an account-wide ceiling. Calls through REST API, Remote MCP, or different API keys for the same account consume the same allowance for their operation type.

An API key may also have a separate, stricter limit. A request must satisfy both the account and key limits; a key-specific limit cannot raise the membership allowance. If an administrator configures a lower key limit, that lower limit can be reached first.

Active-job concurrency

Jobs in queued, scheduled, or running state are active. Each job family is counted separately.

Membership tierCustomsResearchProspect lists
Free111
Starter322
Scale533
Pro1053
Enterprise20105

When the concurrency cap is reached, no new job is created or charged. Submit again after an existing job reaches succeeded, failed, or cancelled.

RPM, concurrency, and credits

ControlPurposeWhen capacity returns
RPMControls request bursts within one minuteWhen the current rate-limit window ends
Active-job concurrencyLimits long-running jobs queued or executing at onceWhen an active job reaches a terminal state
CreditsDetermines available billable usageWhen the account receives more credits

Passing one control does not bypass the others. For example, an account may still have credits while data-task RPM or active-job concurrency is already full.

REST API rate-limit headers

REST responses may include the following headers. X-RateLimit-* describes an API-key limit, while X-User-RateLimit-* describes the membership account limit.

HeaderDescription
X-RateLimit-LimitAPI-key request limit for the current window.
X-RateLimit-RemainingRemaining API-key requests in the current window.
X-RateLimit-Window-MsAPI-key window length in milliseconds.
X-RateLimit-ResetEstimated API-key reset time as a Unix timestamp in seconds.
X-User-RateLimit-LimitAccount request limit for the current operation type.
X-User-RateLimit-RemainingRemaining account requests for the current operation type.
X-User-RateLimit-Window-MsAccount window length in milliseconds.
X-User-RateLimit-ResetEstimated account reset time as a Unix timestamp in seconds.
Retry-AfterMinimum number of seconds to wait after a rejection.

Some X-RateLimit-* fields may be absent when no separate key limit is configured. Clients should use the headers actually returned.

HTTP 429

An account-level rejection returns:

JSON
{
  "ok": false,
  "error": {
    "code": "api_rate_limit_exceeded",
    "message": "api_rate_limit_exceeded",
    "request_id": "req_xxx",
    "rate_limit_scope": "user"
  }
}

For an API-key-level rejection, code is api_key_rate_limit_exceeded and rate_limit_scope is api_key.

Retry guidance

  1. After HTTP 429, wait for Retry-After instead of retrying immediately.
  2. If Retry-After is absent, use exponential backoff with a small amount of random jitter.
  3. Poll asynchronous jobs every 2 to 5 seconds in most cases, then reduce frequency for longer jobs.
  4. After a network timeout, reuse the original Idempotency-Key when retrying the same creation or outreach operation. Generate a new value for a genuinely new operation.
  5. MCP clients should honor retry information in tool errors and must not switch protocols or keys to bypass the wait.
TypeScript
const retryAfterSeconds = Number(response.headers.get("Retry-After") || 1)
await new Promise((resolve) => setTimeout(resolve, retryAfterSeconds * 1000))

Rate limiting protects service stability. It does not by itself mean that a job failed or credits were charged. Continue polling only after the business endpoint confirms that a job was created.