Automating Bulk URL Indexing With the API

Wire indexing into your publishing pipeline so every new URL is submitted the moment it goes live — with copy-paste examples.

Published 4 min read 1,085 views English

Submitting URLs by hand works until it does not. Once you are publishing daily, or managing indexing across a portfolio of client sites, the sensible move is to make submission part of the publishing pipeline itself.

Every account has an API key on the profile page. Everything below uses it.

Authentication

Pass the key as an X-API-Key header. A bearer token works too if that fits your client better.

curl https://indx.it.com/api/v1/me \
  -H "X-API-Key: ix_your_key_here"

The response tells you who you are and what you can spend:

{
  "success": true,
  "user": {
    "username": "acme",
    "credits": 412.55,
    "role": "user"
  }
}

Submitting a batch

One POST creates one order. Send up to 10,000 URLs per call.

curl -X POST https://indx.it.com/api/v1/tasks \
  -H "X-API-Key: ix_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "indexer",
    "engine": "google",
    "title": "Blog — August batch",
    "urls": [
      "https://example.com/post-one",
      "https://example.com/post-two"
    ]
  }'

You get back the order id and what it cost:

{
  "success": true,
  "task_id": 8814,
  "status": "queued",
  "quantity": 2,
  "credits_charged": 2,
  "balance": 410.55
}

Two things to know. Duplicate and malformed URLs are filtered server-side before pricing, so you are only charged for what is actually submitted. And if your balance cannot cover the order, the call returns 402 Payment Required rather than partially submitting — check for that status explicitly.

Checking status

curl https://indx.it.com/api/v1/tasks/8814 \
  -H "X-API-Key: ix_your_key_here"

And for per-URL results:

curl "https://indx.it.com/api/v1/tasks/8814/links?status=indexed&per_page=500" \
  -H "X-API-Key: ix_your_key_here"

Poll at a sensible interval. Status meaningfully changes on the order of minutes, so checking every 30 seconds just burns your rate limit — 120 requests per minute per key.

WordPress: submit on publish

Drop this in your theme’s functions.php or a small plugin. It fires once when a post transitions to published.

add_action('transition_post_status', function ($new, $old, $post) {
    if ($new !== 'publish' || $old === 'publish') {
        return;
    }
    if ($post->post_type !== 'post' && $post->post_type !== 'page') {
        return;
    }

    wp_remote_post('https://indx.it.com/api/v1/tasks', [
        'timeout' => 15,
        'headers' => [
            'X-API-Key'    => INDXIT_KEY,
            'Content-Type' => 'application/json',
        ],
        'body' => wp_json_encode([
            'type'  => 'indexer',
            'title' => get_the_title($post),
            'urls'  => [get_permalink($post)],
        ]),
    ]);
}, 10, 3);

Python: submit a sitemap diff nightly

A more efficient pattern than submitting on publish: once a night, diff your sitemap against what you submitted yesterday and send only the new URLs.

import json, pathlib, requests
import xml.etree.ElementTree as ET

KEY   = "ix_your_key_here"
STATE = pathlib.Path("submitted.json")

ns   = {"s": "http://www.sitemaps.org/schemas/sitemap/0.9"}
xml  = requests.get("https://example.com/sitemap.xml", timeout=30).text
urls = {u.text for u in ET.fromstring(xml).findall(".//s:loc", ns)}

seen = set(json.loads(STATE.read_text())) if STATE.exists() else set()
new  = sorted(urls - seen)

if new:
    r = requests.post(
        "https://indx.it.com/api/v1/tasks",
        headers={"X-API-Key": KEY},
        json={"type": "indexer", "title": "Nightly sitemap diff", "urls": new},
        timeout=60,
    )
    if r.status_code == 402:
        raise SystemExit("Out of credits")
    r.raise_for_status()
    print(f"submitted {len(new)} new URLs")

STATE.write_text(json.dumps(sorted(urls)))

n8n, Make and Zapier

There is no dedicated app, but the generic HTTP node covers it. Configure a POST to https://indx.it.com/api/v1/tasks, add the X-API-Key header, and map your URL list into the urls array. An RSS trigger on your own feed plus that one node is a complete auto-submit workflow.

Handling errors properly

StatusMeaningWhat to do
401Bad or missing keyCheck the header name and the key itself
402Insufficient creditsTop up; do not retry the same call
422Invalid inputRead the error field — usually an empty or malformed URL list
429Rate limitedBack off; retry_after tells you how long

Retrying a 402 or a 422 will never succeed. Only 429 and 5xx are worth a retry, and those should back off exponentially.

One habit worth adopting

Log the task_id you get back against the URLs you sent. When someone asks in three weeks whether a particular page was ever submitted, that log is the difference between a one-second answer and an afternoon of guessing.

Keep reading

Related reading

Same language, same territory — the next steps for getting URLs crawled and kept.