Rate Limits & Quotas

Metered by plan.
Capped by the minute.

Screening calls count against your plan's monthly allowance and are also capped at 120 requests per minute per tenant (a fixed window shared by all of your keys and portal users). Use up the allowance and, once any prepaid credit is spent, your plan decides: either calls stop with a 402 or they go through and the overage is billed. Exceed the per-minute cap and you get a 429. Both refusals use the standard error envelope.

What governs throughput

Allowances are plan-dependent and shown in the portal under Usage. Enterprise contracts set their own volume; talk to us if you need a different ceiling.

Endpoint groupRuleWhen exceeded
Screening endpoints (/screening/*)Every call under /screening/*, reference reads such as topics and adverse-media categories included, counts toward one fixed window of 120 requests per minute per tenant, shared by all of your API keys and signed-in portal users. The allowance it is metered against depends on the endpoint: screenings draw on screenings_monthly, onboarding-guard on prekyc_monthly, and reference reads on none. Cache reference lists instead of fetching them on every request.Allowance used up: prepaid credit first, then by plan either 402 QUOTA_EXCEEDED or the call goes through and the overage is billed; 429 RATE_LIMIT_EXCEEDED beyond 120/min
Orchestrated screen (/orchestrate/screen)Metered per module that screened, against that module's monthly allowance. No per-minute limiter.402 QUOTA_EXCEEDED, or 403 FEATURE_NOT_INCLUDED for a module your plan lacks
Batch file upload (/portal/batch/jobs/upload)60 uploads per minute: per tenant for API keys (all keys share it), per user for portal sessions.429 RATE_LIMIT_EXCEEDED
Billing units1 unit per subject; full scan adds 1 per advanced check; payment screen is 1 per leg; address parse without `screen` is free.Usage is visible in the portal (Usage)

What a rejection looks like

Both kinds of rejection use the same envelope as every other error, so one handler covers them. The 402 names the exhausted feature (screenings_monthly, prekyc_monthly ...); on a demo account it reads Demo query quota exhausted. instead. Branch on the code, not the message.

responses
HTTP/1.1 429 Too Many Requests
{ "success": false, "error": { "code": "RATE_LIMIT_EXCEEDED", "message": "Too many requests. Please try again later." } }

HTTP/1.1 402 Payment Required
{ "success": false, "error": { "code": "QUOTA_EXCEEDED", "message": "Monthly quota for 'screenings_monthly' exhausted." } }

Handle 429 gracefully

A 429 carries a Retry-After header telling a well-behaved client exactly when the fixed window reopens; honour it. Fall back to exponential backoff with full jitter only when the header is absent. Do not retry a 402; it clears when the allowance renews, credit is added or the plan changes.

retry.js
async function callWithRetry(fn, attempt = 0) {
  const res = await fn();
  if (res.status === 429 && attempt < 5) {
    // The server says when the window reopens; honour it.
    const retryAfter = Number(res.headers.get("Retry-After"));
    const seconds = Number.isFinite(retryAfter) && retryAfter > 0
      ? retryAfter                         // wait exactly as told
      : Math.random() * 2 ** attempt;      // else exponential backoff, full jitter
    await new Promise((r) => setTimeout(r, seconds * 1000));
    return callWithRetry(fn, attempt + 1);
  }
  return res;
}

Watch the allowance, not the clock

Usage is reported per month in the portal. Alert yourself at 80 percent: past the allowance, depending on your plan, a busy onboarding day either ends in a 402 or arrives as an overage charge.

Batch large workloads

For files and back-book re-screens, use the asynchronous batch job endpoints instead of thousands of synchronous calls; the same units apply, with less overhead.

Need a higher ceiling?

Talk to us about a plan with the volume your integration needs.

Get in touch