Rate Limits

The API enforces per-key and per-organization request limits to keep the service responsive. Authenticated, rate-limited routes return headers that help your integration track its request budget.

Request rate limits

Limits are enforced in a 60-second fixed window, applied both per API key and per organization. If either limit is reached, the request receives a 429 response.

Route typePer keyPer organizationApplies to
Read120 / min360 / minjobs, credits
Create60 / min180 / minclassify
Scan20 / min60 / minscan, scan/lite, scan/deep (same numeric policy per path; each path has its own burst bucket)

These are default launch limits. If you need higher throughput for a production workload, contact support@on-page.ai.

Per-org job concurrency

Counts apply to the combined total across classify and scan jobs — one org can't saturate the worker pool with any single job type.

5

Concurrent active jobs per org

Up to 5 jobs can run simultaneously for your organization, across any combination of classify / scan. Additional scan submissions can queue and start as slots free up. Classify submissions may receive a 429 with ORG_ACTIVE_LIMIT_REACHED when the active cap is reached.

100

Max queued jobs per org

If your organization already has 100 jobs waiting, new submissions are rejected with ORG_QUEUED_LIMIT_REACHED until the queue drains.

What happens under heavy load

When the global scan queue is saturated, new requests may receive a 429 with error code SCAN_QUEUE_SATURATED. The Retry-After header tells you how long to wait. This is rare — it only occurs when the entire system is under exceptional load, not just your organization.

Response headers

X-RateLimit-* appears on authenticated, rate-limited routes so you can track your remaining budget in real time. Retry-After and X-Concurrency-* are conditional — present only on 429 responses (see the per-header notes below).

X-RateLimit-Limit

Maximum requests allowed in the current window.

X-RateLimit-Remaining

Requests remaining before the limit resets.

X-RateLimit-Reset

Unix timestamp (seconds) when the current window resets.

Retry-After

Seconds to wait before retrying. Present on 429 responses when the limiter computed one.

X-Concurrency-Limit

The concurrency cap that was hit. Present on 429 responses with ORG_ACTIVE_LIMIT_REACHED or ORG_QUEUED_LIMIT_REACHED.

X-Concurrency-Remaining

Remaining in-flight capacity — always 0 when the caller just hit the cap. Retry after jobs drain (observe via webhooks or GET /v1/jobs/:id polling).

Handling 429 responses

A 429 means you've hit a limit. Here's what to do:

Always respect Retry-After

When the response includes Retry-After, wait for that interval. When it is absent, use bounded exponential backoff and reduce the request rate.

Use idempotency keys on create routes

Pass an Idempotency-Key header so retries are safe and don't create duplicate jobs.

Back off on repeated 429s

If you see multiple 429s in a row, reduce your request rate rather than retrying immediately.

Poll existing jobs instead of resubmitting

If a scan was already submitted, poll its status with GET /v1/jobs/:id instead of submitting a new one.

Scans can take 30 seconds to 3 minutes

Don't treat slow scans as failures. Poll at reasonable intervals (every 3-5 seconds) and let the system work.

Put these limits into practice with the resumable batch-processing guide, or use webhooks to reduce polling.

Rate limit error codes

CodeMeaning
RATE_LIMITEDRequest rate limit exceeded for this key or organization.
ORG_ACTIVE_LIMIT_REACHEDThe active-job cap blocked this admission. Classification can be rejected at the cap; scan submissions can queue. Inspect the response limit.
ORG_QUEUED_LIMIT_REACHEDThe queued-job cap was reached. Inspect the response limit and wait for the queue to drain.
SCAN_QUEUE_SATURATEDGlobal scan capacity is full. Retry after the indicated delay.