Skip to content

Keyword.find

Find the terms worth a page: ideas from your seed words, buyers’ questions, and the terms a rival ranks or pays for.

Price
5¢ per 100 ideas
Success rate
100% of 16,219 calls
Freshness
Fresh for 30 days
Emits
Keyword.found
Capability
Market data
POST https://api.sb/{your-domain}/keywords/find

Options and prices

You getInput that selects itPriceSuccess rate
Ideas around your seed words{"seeds":["rent tracking software"]}About 5¢ per 100 ideas100% of 16,219 calls
How people finish your words in the search box{"mode":"suggestions"}About 10¢ per 100 seeds100% of 37,928 calls
The questions buyers type{"mode":"questions"}About 18¢ per 100 seeds66% of 3,022 calls
The terms a rival ranks for{"rival":"rentrival.example"}About 5¢ per 100 terms100% of 19,441 calls
The terms a rival pays for{"rival":"rentrival.example","mode":"rival-paid"}About 20¢ per 100 terms99.9% of 2,200 calls
What is rising on a site now{"mode":"trending","venue":"tiktok"}About 0.1¢ a board99.9% of 1,350 calls

Inputs

NameTypeDefaultMeaning
seedsstring[]None.Up to 20 phrases. Seed from the words buyers used in problem posts and calls, not from your product’s own words. Pass seeds or rival.
rivalHostnameNone.The terms this domain ranks for, or pays for with mode: rival-paid.
excludeHostnameNone.With rival: drop the terms this domain already ranks for. Pass your own to get the content gap.
mode'ideas' | 'suggestions' | 'questions' | 'rival' | 'rival-paid' | 'trending''ideas' with seeds, 'rival' with rivalWhich job runs. Each one returns the same row.
venueVenueId'google-search'youtube and tiktok take suggestions; tiktok, x and reddit take trending.
localestringyour home MarketThe market and language, such as en-US.
where{ searches?: Range; difficulty?: Range; intents?: Intent[] }None.Filters run before the list returns, so you never pay for a term you would drop.
limitnumber100Terms to return, at most 1,000. You pay for terms returned.
savenumber0Save the first n terms as Keywords; free, and it follows the call’s Mode.
maxCostnumber0.50The most this call may spend, in USD. Over it, the call is refused before it spends, or stops early with what it has.

Outputs

FieldTypeUnitWhat null means
termsKeyword[]None.Never null: empty when nothing passed where, at $0.
terms[].termstringNone.Never null.
terms[].searchesnumber | nullsearches a monthUnknown: no reading for a long-tail term. Never zero demand.
terms[].cpcnumber | nullUSD a clickNo advertiser bids on it, or no reading.
terms[].difficultynumber | null0 to 100Unknown.
terms[].intent'buy' | 'compare' | 'learn' | 'navigate' | nullNone.Unknown.
terms[].trend'rising' | 'flat' | 'falling' | null12 monthsUnder 12 months of readings.
terms[].positionnumber | nullNone.Absent without rival; null past position 100.
terms[].rivalUrlstring | nullNone.Absent without rival.
terms[].monthlyAdCostnumber | nullUSD a monthAbsent unless mode: rival-paid.
terms[].postsnumber | nullposts this weekAbsent unless mode: trending.
terms[]ObservedNone.Each row also carries observedAt, method, venue and locale.
foundnumbertermsNever null: before where ran.
keptnumbertermsNever null: after where ran; you pay for these.
peopleAlsoAskstring[]None.Never null: empty when the results page shows none.
ignoredstring[]None.Never null: empty when every filter you sent was applied.
costCostUSDNever null. In try mode usd is 0 and maxUsd is what the call would have cost.

Read the result

FieldValueWhat it meansWhat to do
searchesnullUnknown, not zero: most long-tail B2B terms have no reading.Keep it if a problem post uses the phrase; drop it only when it reads null and no buyer writes it. (the drop rule in the search playbook)
difficultyAbove your ceilingYour ceiling is the difficulty your referring domains reach; above it, page one needs links you do not have yet.Park it for week 12; target the terms at or under the ceiling now. (the referring-domain scale difficulty is defined on)
trendfallingDemand is leaving the term.Drop it if it fell more than 30% over 12 months. (our planning number)
intentnavigate to a rival’s brandThe searcher wants that site, not a choice.Drop it; a page cannot win a search for someone else’s login page. (the intent rule in the search playbook)
keptUnder 60 of 300The seeds are your words, not the buyer’s.Reseed from the phrases in problem posts and People also ask. (our planning number: 200 to 500 ideas leave about 60)
monthlyAdCostOver $0 on a term you wantA rival pays for it, so the term converts for someone.Earn it if its cost per click is over your break-even; buy it only if under. (break-even cost per click, the strategy numbers)

Effects

Action class

None: it reads, so no approval rule names it

Modes
  • try: Runs the read and returns real rows; nothing is saved and nothing is billed.
  • send: Returns a pending Action at once; its Event carries the rows when the read finishes.
  • do: Waits for the read and returns the rows, billed per result.
Idempotency

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

Saved or shared

Terms are returned, not saved, unless you pass save. Ideas are shared across startups for the same seeds and locale for 30 days.

Emits

Keyword.found with { terms, found, kept, seeds, rival }

Performed by

Analyst

Price

About 5¢ per 100 ideas. Free: ideas from your own Google Ads account, saving terms as Keywords, ideas filtered out by where before they return. maxCost defaults to 50¢. 300 ideas from 5 seeds: 300 × 0.05¢ an idea is about 15¢.

Reliability

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

Freshness

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

Batch and pages

Up to 1,000 terms a call. It answers in one response.

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

Returns in one response; nothing waits.

Example

Text
Which rent-tracking search terms are worth a page, at difficulty 30 or
under? Spend up to 20¢.

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.find',
  input: { mode: 'trending', venue: 'tiktok' },
  change: 'new-term',
  every: '1w',
})

Used by