backlinkindexersoftware.comSoftware and API handbook

Handling indexing API errors

Published

Indexing API errors fall into two groups: ones the client must fix, such as a bad key (401), invalid payload or low balance (422 on v1, 402 on v2) and unknown jobs (404), and temporary ones, such as rate limiting (429) and server errors (500). Only the temporary group should be retried, with a delay.

Two families of error

When a call to an indexing API fails, the first question is whether sending it again could ever succeed. A wrong key, a malformed body or a job ID from another account will fail the same way every time; the fix is in the client or the account. A rate limit or a temporary server problem will clear by itself, and a delayed retry is correct. Mixing the two up produces the classic failure modes: a tight loop hammering a 401, or a script that gives up on a 429.

The tables below list what the IndexChex API returns, verbatim. IndexChex publishes this handbook; the endpoint reference is on its API documentation.

v1 responses

v1 errors carry a message field. Validation errors add an errors object keyed by field name.

HTTPBodyCauseRetry?
401{"message": "Invalid API credentials."}Missing, wrong or revoked keyNo
404{"message": "Resource not found."}Unknown job ID, a job owned by another user, or a wrong pathNo
422{"message": "...", "errors": {"urls": ["..."]}}Validation: missing urls, empty entries, more URLs than allowed, name over 255 characters, checker outside 0 to 5No; fix the body
422{"message": "Insufficient credits. You need N credits but only have M available."}Balance too low for the jobNo; top up first
422{"message": "No valid URLs provided"}None of the entries is a valid web addressNo
422{"message": "Report not ready. Check status and retry later."}Check report requested before the job completedYes, after polling
429{"message": "Too many requests. Please wait and retry."}Over 120 requests per minuteYes, after Retry-After
500{"message": "Unable to create index submission job at this time."}Temporary failure on submission createYes, after confirming no job exists
500{"message": "Unable to create index check job at this time."}Temporary failure on check createYes, after confirming no job exists

Successful create calls return 202; status, report and balance calls return 200.

v2 responses

v2 keeps the SpeedyIndex envelope, so errors carry a numeric code alongside the HTTP status. The exception is authentication, which returns the same 401 body as v1 with no code.

HTTPcodemessageCause
401noneInvalid API credentials.Bad key
4021Insufficient credits. You need N credits but only have M available.Balance too low
404404Task not found.Unknown task ID or one owned by another user
4223Invalid request payload. plus errorsValidation failure on create, status, report or single-URL calls
4223Unsupported search engine.Engine other than google
4223Unsupported task type.Type other than indexer or checker
4223Report not ready. Check status and retry later.Task or its scheduled check still running
4223Report not available for this task.Indexer task created without checker
4292Too many requests. Please retry shortly.Rate limit
5002The server is currently unavailable. Please try again later.Temporary failure on task create

The single-URL endpoint POST /v2/google/url returns a bare {"code": 2} with HTTP 500 on a temporary failure and {"code": 0} on success. Migration notes for v2 are in migrating a SpeedyIndex integration.

A Python handler

import time, requests

class PermanentError(Exception): pass
class RetryLater(Exception): pass

def call(method, url, headers, retries=5, **kw):
    for attempt in range(retries):
        r = requests.request(method, url, headers=headers, timeout=30, **kw)
        if r.status_code in (200, 202):
            return r.json()
        body = r.json() if r.headers.get("content-type", "").startswith("application/json") else {}
        msg = body.get("message", r.text[:200])
        if r.status_code == 429:
            time.sleep(int(r.headers.get("Retry-After", 30)))
            continue
        if r.status_code >= 500:
            if method == "POST":
                raise RetryLater(f"create may or may not have succeeded: {msg}")
            time.sleep(2 ** attempt * 5)
            continue
        if r.status_code == 422 and "not ready" in msg.lower():
            raise RetryLater(msg)
        raise PermanentError(f"{r.status_code}: {msg} {body.get('errors', '')}")
    raise RetryLater(f"gave up after {retries} attempts")

Three decisions are built in. Rate limits are waited out using the server's Retry-After header. Server errors on reads are retried with exponential back-off, but on create calls they are raised, because the job may already exist. And "report not ready" is surfaced as a retry-later signal rather than a failure, so the caller can go back to polling.

Avoiding errors in the first place

  • Validate before sending. Trim, deduplicate and drop blank lines; keep name short; cap each job at 10,000 URLs, or 1,000 for instant. Rate limits and batching has a chunking helper.
  • Check the balance first. GET /v1/balance returns {"balance": N}. Compare it with the URL count (times 60 for instant, plus 1 per URL for a scheduled check) before creating a job.
  • Send Accept: application/json. Without it, some validation failures may not come back as JSON.
  • Store job IDs immediately. Most 404s in practice come from IDs lost or mixed up between accounts.

Errors that are not errors

A finished index check can list URLs under failed_links. Those lookups could not complete; the API call itself succeeded. Likewise, a completed submission with URLs that later prove unindexed is not a failure of the request: IndexChex guarantees Googlebot crawling, and indexing remains Google's decision. How to read those results is covered in checking index status via an API and submitting URLs via an API.

Error semantics are a fair test when comparing backlink indexer APIs and the wider category of backlink indexer software. The IndexChex entry lists the account-level API facts.

FAQ

Should I retry a 500 on a create call?

Only after checking whether the job exists. List recent jobs in the dashboard or, on v2, with the list endpoint, and resubmit only if nothing was created. A blind retry can create a duplicate job and charge twice.

Why does a job I can see in the dashboard return 404 over the API?

Jobs belong to the user that created them. A key from a different account, or a typo in the job ID, returns the same 404 so that job IDs from other accounts are never confirmed.

Is a URL in failed_links an error?

Not an API error. The job finished; that URL's lookup could not complete. Check it again later instead of treating it as not indexed.

What does code 3 mean on v2?

The request could not be accepted as sent: an invalid payload, an unsupported engine or task type, too many URLs, or a report that is not ready or not available. The message field says which.

Terms used on this page

Sources

  1. IndexChex API reference

Cite this entry

IndexChex. (2026, October 8). Handling indexing API errors. backlinkindexersoftware.com. https://backlinkindexersoftware.com/api-error-handling/