Skip to content

Keyword.ask

Ask ChatGPT, Gemini, Perplexity and the other answer engines a buyer’s question and see whether they name you and which pages they cite.

Price
0.4¢ an answer
Success rate
99.96% of 131,093 calls
Freshness
Fresh for 7 days
Emits
Keyword.asked
Capability
Market data
POST https://api.sb/{your-domain}/keywords/ask

Options and prices

You getInput that selects itPriceSuccess rate
An answer from ChatGPT{"venues":["chatgpt"]}About 0.4¢ an answer99.96% of 131,093 calls
An answer from Gemini{"venues":["gemini"]}About 0.24¢ an answer98.6% of 69,436 calls
An answer from Perplexity{"venues":["perplexity"]}About 0.6¢ an answer99.98% of 69,361 calls
An answer from Copilot{"venues":["copilot"]}About 0.28¢ an answer99.6% of 34,753 calls
An answer from Claude{"venues":["claude"]}About 2.5¢ an answer100% of 17,151 calls
An answer from Google AI Mode{"venues":["google-ai-mode"]}About 0.24¢ an answer99.8% of 62,793 calls

Inputs

NameTypeDefaultMeaning
keywordstringRequiredThe question, worded as a buyer would type it to an assistant.
venues('chatgpt' | 'gemini' | 'perplexity' | 'copilot' | 'claude' | 'google-ai-mode')[]['chatgpt', 'gemini', 'perplexity', 'google-ai-mode']The engines to ask, in parallel. Each is its own job with its own price.
runsnumber1Times to ask each engine, 1 to 3. Answers vary run to run, so a tracked question takes 3.
countrystringyour home MarketWhere the question is asked from, signed out.
brandsstring[]your Brand and your rivalsThe brands mentioned reports on, named or cited.
maxAgestring'7d'A stored reading younger than this returns at $0 instead of reading again.
maxCostnumber0.10The most this call may spend, in USD. Over it, the call is refused before it spends, or stops early with what it has.

Outputs

FieldTypeWhat null means
keywordstringNever null.
answersAnswer[]Never null: one per engine per run.
answers[].venueVenueIdNever null.
answers[].runnumber, in 1 to 3Never null.
answers[].textstringNever null: the answer as shown.
answers[].named{ brand: string; position: number; host: Hostname | null }[]Never null: brands in order of first mention; empty when none is named.
answers[].cited{ position: number; url: string; host: Hostname; title: string | null }[]Never null: empty when the engine cites nothing.
answers[].queriesstring[]Never null: the searches the engine ran, empty when it does not show them.
answers[].mentioned{ brand: string; named: boolean; cited: boolean }[]Never null: one row per brand in brands.
answers[]ObservedEach answer also carries observedAt, method and locale.
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
runs1One answer is an anecdote: the same engine names different brands on the next run.Ask a tracked question 3 times on each engine. (the answer-share sampling rule)
mentioned.namedShare across 200 answersAt a 10% share, 200 answers read ±4.2 points.Flag only a move of 5 points or more that holds for 2 weeks; anything less is noise. (binomial interval, the strategy numbers)
citedReddit threads on Perplexity, encyclopedic pages on ChatGPTEngines cite different sources: Reddit is 46.7% of Perplexity’s top-10 cited domains, and only about 11% of domains are cited by both.Read each engine on its own and plan per engine; never blend them into one score. (a study of about 680M citations)
mentioned.citedfalse everywhereBranded mentions on the web track AI visibility more closely (0.664) than referring domains do (0.295).Get listed and mentioned on the pages engines already cite before you build links. (a correlation study of 75,000 brands)
queriesSearches the engine ranThe engine looked these up before it answered.Measure them with Keyword.measure; a page that ranks for them gets cited. (the AEO playbook)

Effects

Action class

None: it reads, so no approval rule names it

Modes
  • try: Asks the engines and returns real answers; nothing is saved and nothing is billed.
  • send: Returns a pending Action at once; Keyword.asked carries the answers when every engine has replied.
  • do: Waits about 30 seconds for every engine, then returns the answers, billed per answer.
Idempotency

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

Saved or shared

Nothing is written to your records. Answers are shared across startups for the same question, engine and country for 7 days; mentioned is yours.

Emits

Keyword.asked with { keyword, venue, run, named, cited, mentioned }, one Event per answer

Performed by

Analyst

Price

About 0.4¢ an answer. Free: an answer younger than maxAge. maxCost defaults to 10¢. 20 buying questions on 4 engines: 80 × 0.4¢ an answer is about 32¢.

Reliability

The first route succeeds 99.96% of 131,093 calls. If it fails, a second route answers at 97.9% of 109,468 calls, and you pay for one.

Freshness

A reading younger than 7 days returns at $0. Readings are shared across startups for the same subject and locale.

Batch and pages

Up to 18 answers a call: 6 engines × 3 runs. An answer takes about 30 seconds, so send returns a pending Action at once and Keyword.asked delivers the answers

Rate

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

Refuses when

CheckErrorFixThen call
A search engine, answer engine or network the call does not read, such as ChatGPT sent to Keyword.measurevenue-unsupportedPick one the call’s venue input lists; AI answers are Keyword.ask, posts are Keyword.search.Keyword.ask

Every data call can also meet the shared data-call refusals: filter-unsupported, input-missing, limit-exceeded, max-cost, rate-limited, sources-busy.

The venue-unsupported payload
JSON
{
  "type": "https://startupbuilder.dev/errors/venue-unsupported",
  "title": "The call does not read that search engine or network",
  "status": 422,
  "detail": "A search engine, answer engine or network the call does not read, such as ChatGPT sent to `Keyword.measure`.",
  "fix": "Pick one the call’s `venue` input lists; AI answers are `Keyword.ask`, posts are `Keyword.search`.",
  "next": {
    "verb": "Keyword.ask",
    "input": {
      "keyword": "best rent tracking software for a 40-unit property manager",
      "venues": [
        "chatgpt"
      ]
    }
  },
  "instance": "https://api.sb/leaseline.app/actions/action_1"
}

When it waits

FactValue
send returnsA pending Action, status: running, with its $id.
Delivered byKeyword.asked
TypeScript
await $.Watch.create({
  selector: 'Keyword.asked',
  url: 'https://leaseline.app/hooks/answers',
})

Example

Text
Do ChatGPT and Perplexity name Leaseline when a 40-unit property manager
asks for rent tracking software? Spend up to 2¢.

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: 'Keyword.ask',
  input: { keyword: 'best rent tracking software for a 40-unit property manager', runs: 3 },
  change: 'answer-citation',
  every: '1w',
})

Used by