IndexNow API — Submit URLs to Bing, Yandex, and IndexNow Partners
REST API for submitting URLs via the IndexNow protocol to Bing, Yandex, Naver, and other partner search engines. Faster than waiting for crawlers, with key.txt publication handled automatically.
Submit URLs via IndexNow to Bing, Yandex, and IndexNow partner search engines. Faster than waiting for crawlers to discover changes. Mirrors the shape of indexing.gsc.submit for consistency.
Conceptual overview
IndexNow is a free protocol supported by Bing, Yandex, and a growing number of search engines. You POST a URL (or batch), and partner engines pick it up within minutes. Unlike GSC, there's no per-day quota and no auth-cookie complexity — just a workspace key per domain.
CitationBench handles the IndexNow key publication (the key.txt file at your domain root) when you connect — you don't have to manage it manually.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| POST | /v1/indexing/indexnow | Submit URL(s) |
| GET | /v1/indexing/indexnow | List recent submissions |
| CRUD | /v1/indexing/indexnow/config | Manage workspace IndexNow config |
POST /v1/indexing/indexnow
POST /v1/indexing/indexnow HTTP/1.1
Authorization: Bearer sk_live_***
X-Workspace-Id: ws_acme
Content-Type: application/json
{
"urls": [
"https://acme.com/blog/engineering-team-capacity-tracking",
"https://acme.com/blog/sprint-planning-patterns"
]
}| Field | Type | Required | Notes |
|---|---|---|---|
urls | string | string[] | yes | One or many on your verified domain |
Response
{
"submitted": [
{
"url": "https://acme.com/blog/engineering-team-capacity-tracking",
"submissionId": "sub_***",
"state": "ACCEPTED"
},
{
"url": "https://acme.com/blog/sprint-planning-patterns",
"submissionId": "sub_***",
"state": "ACCEPTED"
}
],
"engines": [
{ "name": "bing", "status": "submitted" },
{ "name": "yandex", "status": "submitted" },
{ "name": "naver", "status": "submitted" }
]
}state per URL: ACCEPTED (submitted to all engines), REJECTED (URL malformed or domain not configured).
GET /v1/indexing/indexnow
curl -G .../v1/indexing/indexnow \
--data-urlencode "since=2026-05-01T00:00:00Z" \
--data-urlencode "urlContains=/blog/" \
--data-urlencode "limit=50"{
"data": [
{
"url": "https://acme.com/blog/post-a",
"submissionId": "sub_***",
"submittedAt": "...",
"engines": ["bing", "yandex"]
}
]
}CRUD: /v1/indexing/indexnow/config
# Get current config
curl .../v1/indexing/indexnow/config
# Connect (initializes the key.txt under your domain)
curl -X POST .../v1/indexing/indexnow/config -d '{
"domain": "acme.com",
"keyLocation": "/citationbench-indexnow-key.txt",
"engines": ["bing", "yandex", "naver"]
}'
# Update
curl -X PATCH .../v1/indexing/indexnow/config -d '{
"engines": ["bing", "yandex"]
}'
# Disconnect
curl -X DELETE .../v1/indexing/indexnow/config{
"id": "inc_***",
"domain": "acme.com",
"keyLocation": "/citationbench-indexnow-key.txt",
"keyVerified": true,
"engines": ["bing", "yandex", "naver"],
"autoQueueOnPublish": true,
"lastSubmissionAt": "2026-05-24T08:30:00Z"
}keyVerified: true means we fetched the key file at the publicized URL and confirmed it returns the workspace's key. If false, you need to publish keyLocation at your domain (download from the config endpoint).
MCP
> Submit my latest 5 blog posts to IndexNow.Claude calls produce.blog_post.list then indexing.indexnow.submit.
> Is IndexNow active for this workspace?Claude calls indexing.indexnow.config.get and renders the status.
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | validation_error | URL malformed |
| 403 | indexnow_not_connected | Config missing — POST /config first |
| 403 | key_not_verified | The key.txt isn't reachable at the publicized URL |
| 422 | domain_mismatch | URL not on the configured domain |
| 503 | engine_unavailable | One or more engines unreachable; the submission to others still went through |
Cost
| Action | Credits |
|---|---|
| Per URL | 0.1 |
Auto-submit from produce.publish | included in the publish credit |
| Config CRUD | free |
Use cases (string things together)
A. Auto-submit everything on publish
Set autoQueueOnPublish: true on both GSC and IndexNow configs. Every publish notifies both.
B. Standalone batch submission
URLS=$(cat my-new-pages.txt | jq -Rsc 'split("\n")[:-1]')
curl -X POST .../v1/indexing/indexnow -d "{ \"urls\": $URLS }"C. Sitemap refresh on demand
After a sitewide redesign, submit your entire sitemap:
SITEMAP=$(curl -sf https://acme.com/sitemap.xml | xmllint --xpath '//*[local-name()="loc"]/text()' - | jq -Rs 'split("\n")[:-1]')
curl -X POST .../v1/indexing/indexnow -d "{ \"urls\": $SITEMAP }"Related
- API: Indexing · gsc index — peer endpoint; identical shape
- API: Production · publish — auto-fires this on publish if enabled
GSC index
REST API to submit URLs to Google for indexing and check their current crawl/index status. Wraps the GSC Indexing API with auth handling, rate-limit smoothing, and auto-mirroring to IndexNow.
SERP outreach
Turn a single keyword into a fully scoped outreach campaign. Fetches the top SERP, filters junk, discovers contacts, drafts personalized emails, and parks the campaign at WAITING_APPROVAL for review.