Rate limits and batching
Published
Indexing APIs limit both request rate and job size. IndexChex allows 120 requests per minute per user across v1 and v2, up to 10,000 URLs per index-check or standard submission job, and up to 1,000 per instant job. Large lists should be split into full-size jobs and polled on one shared, paced timer.
Two kinds of limit
An indexing API caps how often you may call it and how much work a single call may contain. The first protects the service from bursts; the second keeps individual jobs to a size that can be processed and reported on. Clients hit the first when they poll too eagerly and the second when they pass a whole export file in one request. Both are easy to design around once the numbers are known. This page uses the IndexChex API, published by the same company as this handbook, as the worked case.
The numbers
| Limit | Value | Applies to |
|---|---|---|
| Requests per minute | 120 per user | All v1 and v2 endpoints combined |
| URLs per index-check job | 10,000 | POST /v1/index-check/jobs, v2 checker create |
| URLs per standard submission | 10,000 | POST /v1/index-submit/jobs, v2 indexer create |
| URLs per instant submission | 1,000 | Either create call with instantIndex: true |
| URLs per single-URL call | 1 | POST /v2/google/url |
The current figures are maintained on the API reference; credit costs per URL are listed on IndexChex pricing.
What happens at each limit
Exceeding the request rate returns HTTP 429. On v1 the body is:
{"message": "Too many requests. Please wait and retry."}
On v2 it keeps the SpeedyIndex envelope:
{"code": 2, "message": "Too many requests. Please retry shortly."}
The response includes standard rate-limit headers (Retry-After and X-RateLimit-*), which a client can read instead of guessing a delay.
Exceeding the job size returns HTTP 422 before any credits are taken. On v1 the body is a validation error with the message "Too many URLs. Maximum allowed: 10000" (or 1000 when instantIndex is true) under errors.urls. On v2 it is {"code": 3, "message": "Invalid request payload.", "errors": {...}} with the same text inside errors. Both shapes are covered in handling API errors.
Batching a large list
A 35,000-URL backlink export becomes four check jobs: three of 10,000 and one of 5,000. Before splitting, normalise and deduplicate, because every array entry is charged.
import os, time, requests
API = "https://indexchex.com/api/v1"
H = {"Authorization": os.environ["INDEXCHEX_API_KEY"], "Accept": "application/json"}
def chunks(items, size):
for i in range(0, len(items), size):
yield items[i:i + size]
def create_jobs(urls, kind="index-check", instant=False, label="batch"):
urls = list(dict.fromkeys(u.strip() for u in urls if u.strip()))
size = 1000 if instant else 10000
job_ids = []
for n, part in enumerate(chunks(urls, size), start=1):
body = {"urls": part, "name": f"{label} {n}"}
if kind == "index-submit":
body["instantIndex"] = instant
while True:
r = requests.post(f"{API}/{kind}/jobs", json=body, headers=H, timeout=60)
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", 30)))
continue
r.raise_for_status()
break
job_ids.append(r.json()["job_id"])
return job_ids
Name each part so jobs can be matched up in the dashboard and in reports. Check the balance with GET /v1/balance first: a job that would overdraw the account is refused with HTTP 422, and the loop above would stop part way through the list.
curl https://indexchex.com/api/v1/balance -H "Authorization: $INDEXCHEX_API_KEY"
{"balance": 41250}
Pacing the poll loop
Create calls are few; polling is where the budget goes. Some planning arithmetic:
| Open jobs | Poll interval | Requests per minute |
|---|---|---|
| 4 | 30 seconds | 8 |
| 20 | 30 seconds | 40 |
| 50 | 15 seconds | 200, over the limit |
| 50 | 60 seconds | 50 |
Run one timer that walks the list of open jobs, not one thread per job. On v2, the status endpoint accepts task_ids so several tasks can be read in one request. The interval guidance per job type is on polling job status.
Sharing the limit across tools
The allowance is per user, so a Google Sheet, a cron script and a CMS publish hook on the same account all draw from the same 120 requests. If several integrations run, give the busiest one most of the headroom and slow the others. A Python indexing script that runs nightly is a good place to concentrate bulk work.
Batching submissions by priority
Splitting is also a chance to separate URLs by value. Fresh, expensive placements can go into a small instant job; the long tail goes into standard jobs of 10,000. The submission guide covers the payload for each, and checking index status covers the verify step.
Related
How limits compare across vendors is part of the backlink indexer API overview, and they are one item on any evaluation of backlink indexer software. The IndexChex entry summarises the account-level limits.
FAQ
Is the 120 per minute limit per key or per account?
Per user. Every key and both API versions for the same account draw on the same allowance.
Is it better to send ten jobs of 1,000 URLs or one of 10,000?
One job of 10,000. It costs the same credits, uses one create call instead of ten, and needs one status poll instead of ten.
Can I drip-feed a submission over several days through the API?
Drip feed is a dashboard option and is not exposed on the API endpoints. To spread submissions over time via the API, schedule smaller jobs from your own code.
Does a 429 response mean the request was processed?
No. A rate-limited request is rejected before it reaches the endpoint, so it is safe to send again after waiting.
Terms used on this page
Sources
Cite this entry
IndexChex. (2026, October 8). Rate limits and batching. backlinkindexersoftware.com. https://backlinkindexersoftware.com/rate-limits-and-batching/