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.
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.
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
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.
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
- After HTTP
429, wait forRetry-Afterinstead of retrying immediately. - If
Retry-Afteris absent, use exponential backoff with a small amount of random jitter. - Poll asynchronous jobs every 2 to 5 seconds in most cases, then reduce frequency for longer jobs.
- After a network timeout, reuse the original
Idempotency-Keywhen retrying the same creation or outreach operation. Generate a new value for a genuinely new operation. - MCP clients should honor retry information in tool errors and must not switch protocols or keys to bypass the wait.
TypeScriptconst 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.