Skip to content

Site.audit

Crawl a whole site, yours or a rival’s, and rank every issue by how many pages it hits, each with an example and its fix.

Price
1.5¢ per 100 pages
Success rate
100% of 90 calls
Freshness
Fresh for 7 days
Emits
Site.audited
Capability
Web
POST https://api.sb/{your-domain}/sites/audit

Options and prices

You getInput that selects itPriceSuccess rate
Start a crawl{"mapOnly":false}About 2¢ a crawl100% of 90 calls
Each page crawled and checked{"maxPages":500}About 1.5¢ per 100 pages100% of 90 calls
Every URL on a site, without checks{"mapOnly":true}About 0.015¢ a site map99.98% of 10,138 calls

Inputs

NameTypeDefaultMeaning
hostnameHostnameRequiredThe site to crawl: yours or a rival’s.
maxPagesnumber500Pages to crawl, at most 10,000. The crawl stops here and says complete: false.
mapOnlybooleanfalseList every URL with its status and no checks.
render'none' | 'js''none'Run each page’s scripts before checking it, for sites built in the browser.
maxCostnumber0.50The most this crawl may spend, in USD. Over it, the call is refused before it spends, or stops early with what it has.

Outputs

FieldTypeWhat null means
hostnameHostnameNever null.
pagesnumber, in pages crawledNever null.
completebooleanNever null: false when the crawl stopped at maxPages or maxCost.
issues{ id: string; pages: number; example: string; fix: string }[]Never null: most pages first; empty when every check passed.
urls{ url: string; status: number; score: number | null }[]Present with mapOnly; score: null because a map runs no checks.
(crawl)ObservedThe audit carries observedAt and method.
costCost, in USDNever null. In try mode usd is 0 and maxUsd is what the call would have cost.

Read the result

FieldValueWhat it meansWhat to do
issuesThe first rowThe fix that helps the most pages at once.Fix it site-wide in the template, not page by page. (the site-audit order)
issuesthin-content on tag or location pagesNear-empty pages a search engine judges not worth indexing.Merge or remove them; they drag the whole site’s crawl. (the index-state playbook)
issuesorphanNo page links to them, so crawlers find them late or never.Link each from 2 indexed pages, then check them with Domain.verify. (the index-state playbook)
completefalseThe site is bigger than maxPages.Run mapOnly first to count the URLs, then size maxPages to them. (the contract every data call keeps)

Effects

Action class

None: it reads, so no approval rule names it

Modes
  • try: Crawls and returns the audit; nothing is saved and nothing is billed.
  • send: Returns a pending Action at once; Site.audited carries the audit when the crawl ends.
  • do: Waits for the crawl to end, which can take minutes, then returns the audit.
Idempotency

The same Idempotency-Key with the same input replays the first audit at $0; with other input it returns 409.

Saved or shared

The audit is kept with your Site for 7 days; audits of other sites are yours alone.

Emits

Site.audited with { hostname, pages, complete, issues }

Performed by

Analyst

Price

About 1.5¢ per 100 pages. Free: pages past maxPages, which are never crawled. maxCost defaults to 50¢. A 500-page crawl: 500 × 0.015¢ a page is about 7.5¢.

Reliability

The first route succeeds 100% of 90 calls. If it fails, the call refuses with sources-busy and nothing is spent.

Freshness

A reading younger than 7 days returns at $0. Readings about people are never shared across startups.

Batch and pages

Up to 10,000 pages a crawl. Every crawl: send returns a pending Action at once and Site.audited delivers the audit

Rate

The shared rate rules: 10 calls a second per key, and an array input counts as one call.

Refuses when

This call has no refusals of its own. Every data call can also meet the shared data-call refusals: filter-unsupported, input-missing, limit-exceeded, max-cost, rate-limited, sources-busy, venue-unsupported.

When it waits

FactValue
send returnsA pending Action, status: running, with its $id.
Delivered bySite.audited
TypeScript
await $.Watch.create({
  selector: 'Site.audited',
  url: 'https://leaseline.app/hooks/audits',
})

Example

Text
Crawl leaseline.app and tell me which fix helps the most pages. Spend up
to 5¢.

To retry, send the same Idempotency-Key: the retry returns the first answer for $0. A new key reads again.

Test values, and watching it

A sk_test_ key answers these the same way every time, at $0 (every test value).

Test valueAlways returnsWhat it is for
maxCost: 0.0001Refuses with max-costAny priced call with a maxCost of 0.0001 is refused before it spends: the price is above the cap.
rate-limited.testRefuses with rate-limitedAny call naming this hostname answers 429 with Retry-After, so your retry logic runs.
sources-busy.testRefuses with sources-busyAny call naming this hostname answers 503 as if every route were busy, and nothing is spent.

Watch it on a schedule: a Monitor runs this call and records an Event only when the reading changes.

TypeScript
await $.Monitor.create({
  verb: 'Site.audit',
  input: { hostname: 'leaseline.app', maxPages: 200 },
  change: 'new-issue',
  every: '1w',
})

Used by