We build and maintain content pipelines for clients at Savage Digital Solutions, and last month we shipped a migration for Candid Studios that moved their blog authoring workflow into gitMdx. The idea was clean: writers commit MDX files, a GitHub Action merges the PR, Next.js rebuilds the static pages, and IndexNow fires off a ping to Bing and other search engines so the new post gets crawled within minutes instead of days.
Here is the part that burned us. After a successful publish call in gitMdx, the SDK returns a publishResult object. We assumed publishResult.url would be the live blog URL. It is not. It is the GitHub Pull Request URL.
That concatenation produces https://candidstudios.nethttps://github.com/org/repo/pull/47. Bing's IndexNow endpoint accepted the POST without complaint, because the API does basic schema validation, not URL reachability validation at submission time. The crawler then tried to fetch that nonsense string, failed silently, and the posts never got indexed.
We only caught it when a Candid Studios post that should have surfaced in Bing within the hour was still invisible three days later.
IndexNow requires you to prove ownership of the domain by hosting a plain text file at /{your-key}.txt on the same domain you are submitting URLs for. The filename is literally your API key.
Our deployment script created the key file locally and committed it to the repo, but the Next.js public/ directory for Candid Studios was not being deployed to the root of candidstudios.net. The file existed in the build artifact but was never reachable at https://candidstudios.net/{INDEXNOWKEY}.txt.
Bing returned a 403 on the first attempt and a 404 on subsequent ones depending on CDN cache state. Both mean the same thing operationally: Bing cannot verify you own the domain, so it discards the submission.
"The key file must be accessible at https://{host}/{key}.txt and must return a 200 status code."
Here is exactly what we changed. Stop using publishResult.url for IndexNow submissions.
This is the URL that actually exists on the public web. publishResult.url is useful for linking to the PR in a Slack notification or a CMS audit log. It is not a public URL. POST host and urlList as separate fields.
The IndexNow POST body requires both fields. We had been sending only urlList. The corrected request:
Sending host separately from the URLs in urlList is required by the spec. Without it, some engines reject the batch silently. Host the key file at the correct path on every money site.
The file content is just the key string on a single line. After deployment, verify it manually before running any submissions:
If you get anything other than 200, your submissions are being discarded. Fix the hosting first.
We also had a second client site in the same pipeline. The key file was missing there too. Both sites needed the file deployed before IndexNow would work for either of them.
The IndexNow API returns a 200 OK even when the key file is unreachable at submission time. Bing validates the key asynchronously when it attempts to crawl the submitted URLs. So your POST succeeds, your logs look clean, and you have no idea the submissions are being silently dropped until you notice the pages are not appearing in search results.
The publishResult.url issue is similarly invisible. The URL string looks plausible in a log line if you are not reading carefully. https://candidstudios.nethttps://github.com/... is obviously wrong when you stare at it, but in a JSON log payload scrolling past in a terminal, it reads as a long URL and your eye moves on.
Both bugs required us to go back to first principles: what does this variable actually contain, and is the thing we are submitting publicly reachable right now?
