Skip to content

Index the site

Your domain in, each key page’s index state out, read daily from Google and Bing until it is indexed or names why not.

Kind
Workflow
Price
Free
Your time
5 minutes
Approval
Runs on its own
Site.index
You, to your agent

Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.

curl -X POST "https://api.sb/leaseline.app/sites/index?mode=try" \
  -H "Authorization: Bearer $SB_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"goal":"Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.","budget":{"amount":2,"currency":"USD"}}'
npx startup-builder do Site.index --try --data '{"goal":"Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.","budget":{"amount":2,"currency":"USD"}}'
{
  "name": "do",
  "arguments": {
    "mode": "try",
    "code": "return await $.Site.index({ goal: 'Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })"
  }
}
import { $ } from 'startup-builder'

const result = await $.try.Site.index({ goal: 'Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.', budget: { amount: 2, currency: 'USD' } })
Response
{
  "mode": "try",
  "stored": false,
  "estimate": "Free",
  "sample": {
    "page": "https://leaseline.app/rent-ledger-template",
    "state": "crawled",
    "reason": "Crawled - currently not indexed",
    "since": "2026-10-25"
  }
}
Try mode reads, stores nothing and spends nothingAPI referenceIts Nouns

What you get

  • 1 site · Your domain in, each key page’s index state out, read daily from Google and Bing until it is indexed or names why not. · Site
  • engines · Google and Bing verified or pending, and whether IndexNow is set.
  • sitemap · URLs submitted against URLs indexed: the first number a new site can read, weeks before any clicks.
  • pages[].state · discovered, crawled, indexed or excluded, with the date it got there.
  • pages[].reason · The engine’s own reason for a page that is not indexed: noindex, canonical elsewhere, soft 404, or crawled and not indexed.

Connect once: Google Search Console, Bing Webmaster. How long: Setup in about a minute; then it waits days to weeks on the engines, and the waits cost nothing.

Trigger

It runs once when you connect the domain; every page you publish later is pinged as it goes live.

TypeScript
on.Domain.connected((domain, $) => $.Site.index({ site: domain.hostname }))

Steps

Your agent does these steps, one row per step; each step’s check is part of its row and its price.

StepVerbReturnsPriceApproval
1. Connect the domain to Google and BingDomain.connectBoth properties verified by DNS, the sitemap submitted to each and the IndexNow key set, as effects of the connectFreeRuns on its own
2. Read index state on each key page, dailyDomain.verifyEach key page’s state and the engine’s reason, read from your own Search Console within its 2,000 a dayFreeRuns on its own
3. Press Request indexing on stuck pagesIntegration.callThe request pressed in Search Console, read back from its page; off unless pressRequest is setFreeRuns on its own
4. Hand stragglers to the weekly readoutCollection.queryPages still not indexed after until, with their reasons, added to Search readoutFreeRuns on its own

Calls: Domain.connect, then Domain.verify, then Integration.call, then Collection.query.

Free, each time it runs, capped at $2.00.

Example: give it a goal

Get every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first.

The plan it shows runs 4 steps, priced before it spends anything; Run it above shows the result it returns.

When something fails

Each failure, and what happens next
WhenThen
The Search Console connection needs signing in againIt stops before any read with the fix: “Reconnect Search Console: npx startup-builder connect google”. Nothing is billed.
A page reads excludedIt records the engine’s reason and opens a task for the site owner: an excluded page needs a fix, not money, so goal mode never spends on it.
The 2,000-a-day inspection quota is spentThe rest wait until the quota resets (quota-reached, with resetsAt) and are read first the next day.
You call it again on the same siteIt re-reads state and never re-adds a property: it is idempotent per site.

Each step retries three times, then falls through to the next route; one item's failure lands in skipped with its reason, never failing the call. Before a step would cross maxCost it stops and returns what it has, with a resume link. Each step's idempotency key is the call's key plus the step and the item: leaseline-site-index-1-<step>-<item>.

Change it

AskCompiles to
Press Request indexing on any page stuck for a week.Site.index
Tell me the day a page drops out of Google.Monitor.create
Check every page in the sitemap, not just the key ones.Domain.verify
TypeScript
import { $, workflow } from 'startup-builder'

export default workflow({
  name: 'site-index',
  verb: 'Site.index',
  input: { site: 'string', keyPages: 'string[]?', pressRequest: 'boolean' },
  maxCost: 2,
  execute: async (ctx, { site, keyPages, pressRequest = false, until = 28 }) => {
    await ctx.step('connect', () => $.Domain.connect({ hostname: site, engines: ['google', 'bing'], indexNow: true }))   // verify, sitemap, IndexNow
    const pages = keyPages ?? (await ctx.step('pages', () => $.Collection.query({ from: 'page', where: `site = '${site}'`, sort: '-links', limit: 20 }))).map((p) => p.url)
    for (let day = 0; day < until; day++) {
      const state = await ctx.step(`state-${day}`, () => $.Domain.verify({ hostname: site, pages }))                 // free on your own account
      if (state.pages.every((p) => p.state === 'indexed' || p.state === 'excluded')) return state
      const stuck = state.pages.filter((p) => p.state === 'crawled' && p.days >= 7)
      if (pressRequest && stuck.length) await ctx.step(`request-${day}`, () => $.Integration.call({ integration: 'google-search-console', op: 'request-indexing', urls: stuck.map((p) => p.url), maxCost: 0.16 * stuck.length }))
      await ctx.sleep('1d')
    }
  },
})

Extend it with extends: 'Site.index' and base(), or compose your own from these steps.

Works with

Plays that order it: Make your API easy for agents to find, Developer relations, Free tools, Open source, Programmatic SEO.

It serves Get indexed, and runs in Launch and search. It deepens Content marketing.

For agents

For agents: the guide, its approvals, retries and lookups
FactValue
GuideSite.index
Guide approvallimits
GoalGet every page on leaseline.app indexed by Google and Bing, spend up to $2, and show me the plan first. It may change counts, the order of steps, soft filters and the route a read takes, and it stops early when the goal is met. It never relaxes your words, raises its own budget, answers its own approval, calls a Play or acts outside your standing approval.
Triggeron.Domain.connected((domain, $) => $.Site.index({ site: domain.hostname }))
RetryThree times with backoff, then the next route; the same idempotency key never charges, sends or posts twice
Idempotency keyleaseline-site-index-1
LookupsA find: input asks unless exactly one record fits
Step
1. Connect the domain to Google and Bing
2. Read index state on each key page, daily
3. Press Request indexing on stuck pages
4. Hand stragglers to the weekly readout

The amounts live once, on the hub (approvals).

Who does each step, and how it is checked
StepFunctionDoerCheckerAssuranceInputs
1. Connect the domain to Google and BingcodeCodeCode reads the result back from where it landedmeasured$0.site
2. Read index state on each key page, dailycodeCodeCode checks each result against its declared typemeasured$0.site, $0.keyPages
3. Press Request indexing on stuck pagesagenticThe Content lead agentCode reads the result back from where it landedmeasured$2.stuck, $0.pressRequest
4. Hand stragglers to the weekly readoutcodeCodeCode checks each result against its declared typemeasured$2.pages, $0.until

The doer is never the checker, and the weakest assurance on the path is the whole call’s.

Under the hood

Under the hood: the Systems, Nouns and Events it touches
KindWhat it touches
SystemsSites and content
NounsDomain, Integration, Collection
EventsDomain.connected, Domain.verified, Integration.called, Collection.queried

Reference

Inputs, outputs, its Event and its errors
NameTypeDefaultMeaning
siteHostnameRequiredYour site.
keyPagesstring[]home and the 19 most-linked pagesThe pages read daily. The sitemap still covers every page.
pressRequestbooleanfalsePress Request indexing on a page still crawled after 7 days, through the browser agent signed in as you.
untilstring'28d'How long it reads before it hands the stragglers to the weekly Search readout.
maxCostnumber2.00The most this call spends each time it runs, in USD. It stops before a step would cross it and returns what it has, with a resume link.

Emits Site.indexed. Refuses with max-cost before it spends, and with the Data calls and Accounts groups (refusals).

Contents