Rate limits and errors
Handle throttling, authentication failures, and retries.
Responses include rate limit headers so clients can throttle without guessing:
| Header | Meaning |
|---|---|
X-RateLimit-Limit | Requests allowed in the current 60-second window. |
X-RateLimit-Remaining | Requests left in the window. |
X-RateLimit-Reset | Unix timestamp for the next retry on 429; on success, an upper bound for expiry of the current rolling window. |
Retry-After | Seconds to wait on a 429 response. |
On 429, wait for Retry-After before retrying. For transient server errors, use exponential backoff with a cap. Treat authentication and validation errors as requests that need correction rather than immediate retries.
The allowance is a rolling 60-second window: requests leave it as they age out. api-capabilities reports the same minute snapshot in its body and headers. If an intermediary strips Retry-After, use the response body's positive retryAfterSeconds, falling back to 60 seconds when neither is available. Daily API request quota headers remain omitted.
Hosted MCP can carry a quota failure inside HTTP 200. Check the JSON-RPC error and tool result isError before treating a response as successful; see MCP retry handling.
| Status | Meaning | Action |
|---|---|---|
400 | Bad request | Check required fields and the error string for invalid filter formats. |
401 | Unauthorized | Send a valid full API key in x-searchleads-api-key. |
403 | Forbidden | Check your plan, key scope, and filter or feature access. |
402 | Insufficient credits | Add credits or reduce the requested operation. |
422 | Unprocessable operation | Read error, reason, and any skipped_filters; correct unsupported fields, formats, or account constraints. |
429 | Rate limited | Wait for Retry-After before trying again. |
500 | Server error | Retry with exponential backoff, such as 1, 2, 4, then 8 seconds. |
Current limits vary by account and endpoint. Read capabilities, including export-specific limits, before scheduling large jobs.
Malformed search requests return 400 with a field and an issues array of { "path": "...", "message": "..." }. Invalid page, size, and searchType retain their established codes: invalid_page, invalid_page_size, and invalid_search_type. Other malformed shapes use invalid_search_request. Correct the supplied path before retrying. For example, filterRules.account.location.matchAll must contain a boolean, not the text "true". These failures occur before credit charging or search execution. MCP reports corresponding validation failures through JSON-RPC/tool error conventions; always inspect the result body.
Filter selection limits count normalized distinct values separately for inclusion and exclusion. REST and MCP use the same limits. Exceeding a normal selection limit returns HTTP 400 with code: "filter_value_limit_exceeded", field, bucket, limit, and received. Exact domain/LinkedIn bulk-limit violations retain HTTP 413. The server rejects the request before searching or charging returned-record credits; it does not silently truncate it. Correct the values or intentionally divide the operation before retrying.
API search and filter-option requests have no daily request cap. REST and hosted MCP share the account's rolling 60-second request allowance. Read rateLimits.perMinute from authenticated capabilities; rateLimits.perDay is { "limit": null, "current": null, "remaining": null, "unlimited": true }. A null daily limit means unlimited, not zero. Daily quota headers are omitted for these API calls. Per-minute limits, credit billing, permissions, maximum page sizes, and export-job concurrency limits still apply. Export create and status requests have no per-minute, per-hour or per-day request quotas and do not consume the shared search allowance, including through MCP. Unlimited daily requests do not mean unlimited requests per second or free returned records.