Search or Ask

Search or ask lets one search field answer questions too: a judge reads what is typed on each pause and offers to answer it, and an answer is written, on request, from the dataset's own records. The Search or Ask guide explains the settings and the front end; this page is the API.

The routes answer 404 until the instance shows Search or ask (the console's Admin > Settings > Experimental) and a team admin shows it on the dataset (its Options tab). They answer 409 searchOrAskDisabled while the dataset's settings have it switched off, and 409 searchOrAskUnavailable where the instance has no model key.

All routes are under /api/teams/{teamName}/datasets/{dataSetName}/search-or-ask. A Search key is enough for everything a visitor's page calls: the settings, intent, filters and ask.


Judge what is typed

Call intent on a pause in typing, beside the search the page already runs.

To have the judgement ready when the pause comes, also call it while the visitor types, with "prefetch": true and one call in flight at a time: when one returns, send the next for whatever the field holds by then. The judge reads the text ahead and keeps its answer, so the pause's own call comes back at once. Only the pause's call counts as a judgement in the statistics, and calls made ahead never use the last fifth of the day's budget, which stays for the pauses. useSearchOrAsk() does this for you.

http
POST /api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/intent?session={pageLoadId}&queryId={searchQueryId}
Content-Type: application/json

{ "text": "how do i set up boost rules" }
json
{
  "p": 0.91,
  "answerable": 0.84,
  "criteria": null,
  "offer": "strong",
  "thresholds": { "strong": 0.65, "strongHide": 0.45, "invite": 0.4, "inviteHide": 0.3 },
  "cached": false,
  "ms": 312,
  "searchText": "set up boost rules",
  "refocusWhileTyping": true,
  "inviteOnAskPhrase": true,
  "cutWhileAsking": true,
  "cutShareOfTop": 0.5,
  "cutTopFloor": 0.2,
  "strictCoverageWhileAsking": true,
  "filtersWhileTyping": "off",
  "mode": "soft"
}
FieldMeaning
p
The probability the visitor is asking something an answer would serve, 0 to 1
answerable
Whether the results the judge read could answer it
criteria
On a catalogue, the probability the text describes what to list; null on documentation
offer
none, invite or strong, from p (or criteria) and the thresholds
searchText
What the list searches for this text, its Ask phrases taken off
finished
Whether the visitor has finished typing it, 0 to 1: what type is has not. Proactive answers on its own only from thresholds.finished
mode
The dataset's mode. proactive comes back as inviting once the day's proactive answers are spent, so a page stops starting answers on its own
reason
Set when the judge did not answer: timeout, failed:{status}, or identifier for a code the judge is never asked about. p is then 0; the call itself never fails

The other fields are the dataset's While asking settings, sent with every judgement so a change applies on the next pause. A front end keeps an offer up while p stays above the …Hide threshold, so it does not blink as the visitor types on. Text is 1 to 300 characters.


Answer a question

http
POST /api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/ask?session={pageLoadId}
Content-Type: application/json

{ "question": "how do i set up boost rules", "history": [] }

The answer streams as server-sent events:

event: status
data: {"step":"Searching"}

event: sources
data: [{"n":1,"documentKey":42,"title":"Boost Rules"},{"n":2,"documentKey":57,"title":"Schedule Boost Rules for Campaigns"}]

event: text
data: {"delta":"Open the dataset's Boost rules tab and choose New boost rule [1]."}

event: done
data: {"model":"anthropic/claude-sonnet-5.5","askId":"9b1c…","latencyMs":3480}
EventData
status
{ step }: what the answer is doing, for a line such as "Searching…"
sources
The records the answer may use, numbered; [n] in the text cites them
filters
On a catalogue: the filters, words and sort it searched with, to put the same list on the page
text
{ delta }: the next part of the answer, in markdown
done
{ model, askId, latencyMs }
error
{ code, message }: nothingFound, upstreamBusy or failed

history carries the conversation for a follow-up: up to three earlier turns of { question, answer }. A question is 1 to 1,000 characters. Send "proactive": true when the page starts the answer on its own, in the proactive mode, rather than the visitor asking: it counts against the day's proactive answers, and a dataset in another mode answers 429. The response's Indx-Ask-Id header names the answer from the first byte: send it as the queryId of a select when the visitor opens a cited source.


Turn a description into filters

On a catalogue, when intent reports a strong criteria, filters turns the text into filters on the dataset's own fields: a value or a number range on a Filterable field, checked against the values it holds. text is what no filter covers, to search for.

http
POST /api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/filters
Content-Type: application/json

{ "text": "funny space movies from the 80s" }
json
{
  "filters": [
    { "field": "genres", "value": "Comedy" },
    { "field": "release_year", "min": 1980, "max": 1989 }
  ],
  "text": "space",
  "sort": null,
  "ms": 1460
}

Settings

GET returns the dataset's settings, what it runs with after defaults (effective: the site description, the fields the judge reads, the Ask phrases in effect, the model the answers are written with, how a catalogue's questions are searched, and the models the instance offers as answerModels) and whether the instance can run it (available). A Search key reads them without knowledge. PUT replaces them (a Full key) and applies from the next call; DELETE puts every value back to its default. PUT …/shown with { "shown": true } is the team admin's switch.

SettingDefaultMeaning
enabled
false
Search or ask is on for visitors
kind
documentation
documentation or catalogue
siteDescription
the dataset's description
Who reads the site, what the records hold
titleField, sectionFields, snippetFields
automatic
What the judge reads of a result
filterNotes
none
What values mean, one per line (catalogue)
knowledge
none
Markdown facts no record holds; answers may state them, up to 8,000 characters
answers
best
best or fast: the instance's answer model or its fast one
answerModel
none
Another model the instance offers, by its id (one of effective.answerModels), in place of the one answers names. A model the instance stops offering answers with the one answers names
searches
follows answers
On a catalogue, several (an agent that searches, sorts and filters until it has the answer) or one (one search and a summary of what it found). Unset, best searches several times and fast once
answerInstructions
none
Voice and house rules, up to 1,500 characters
answerLanguage
the visitor's
One language for every answer
askPhrases
English defaults
{ leadIns, frames, links, articles }
refocusWhileTyping
true
The list searches what a question is about
inviteOnAskPhrase
true
The invitation shows as soon as a phrase matches
mode
soft
How forward the offer is: strict, soft, open, inviting or proactive (see the guide)
dailyProactiveAnswers
500
Answers proactive writes without a click per UTC day; past it the mode is inviting until midnight
thresholds
see above
strong, strongHide, invite, inviteHide; hint, where the inviting modes' hint starts (null: 0.25 on a catalogue, 0.31 on documentation); finished, 0.5, the score proactive needs before it answers on its own
cutWhileAsking, cutShareOfTop, cutTopFloor
true, 0.5, 0.2
Keep only the strong matches while the full offer is up
strictCoverageWhileAsking
true
Whole words only on the page's searches while asking
filtersWhileTyping
off
off, facets or model (catalogue)
dailyCallBudget
5000
Calls per UTC day; 0 stops all calls

Limits

A call over the per-address limit, or over the dataset's daily budget, answers 429 with Retry-After and retryAfterSeconds; the budget's code is searchOrAskBudgetSpent, and it resets at midnight UTC.


Statistics

http
GET /api/teams/{teamName}/datasets/{dataSetName}/statistics/search-or-ask?days=30

A Read key. Offers shown and taken, questions asked and how they ended, the answers the proactive mode wrote on its own (proactiveAnswers, apart from asks), cited sources opened, what it cost, and the calls against the budget, with the questions the content did not answer first. Pass ?session=, ?source= and ?queryId= on intent and ask as on searches, so the statistics tie them to the searches they came from.

SearchOrAsk

GET/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask

What the dataset sets, what it runs with (the site description and fields after defaults), and whether this instance can run it at all (`available`: an API key is configured). A search key may read it: a search page needs to know whether to ask, and the thresholds.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
PUT/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask

Replaces the dataset's settings. Applies from the next call; no reindex.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
object
DELETE/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask

Removes the dataset's settings: the feature is off and every value back to its default.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
PUT/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/shown

Whether this dataset has Search or ask (its Options tab): a team admin's switch. Experimental, so off by default; on, the dataset's tab and its visitor routes appear, and `enabled` in the settings then takes it live.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
object
POST/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/intent

Judges what a visitor has typed so far: `p`, the probability they are asking for something an answer would serve, `answerable`, whether the results could answer it, and the `offer` those come to on their own. Call it on a typing pause, beside the search the page already ran. A judge that is slow or failing answers `p` 0 with a `reason`; it never fails the call. With `prefetch` true, call it while the visitor types as well, one call in flight at a time: the judge reads the text ahead of the pause and keeps its answer, so the pause's own call comes back from that at once. Only the pause's call is a judgement in the statistics.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
object
POST/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/filters

A catalogue's description of what to list, as filters on the dataset's own fields: call it when intent's `criteria` reaches the strong threshold. Each filter is a value or a number range on a Filterable field, checked against the values the dataset holds; a text field also needs to be Facetable, which is where its values come from. `text` is what no filter covers, to search for.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
object
POST/api/teams/{teamName}/datasets/{dataSetName}/search-or-ask/ask

Answers a question from the dataset's records, as server-sent events: `sources` (the records the answer may use, numbered), `text` (the answer as it is written, citing sources as [n]), then `done`; or `error` with a code. The answer uses those records and nothing else, and says so when they do not hold it.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
object
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/search-or-ask

What Search or ask did in the last `days` (today included, in the dataset's time zone): offers shown and taken, questions asked and how they ended, cited sources opened, and what it cost. `questions` lists the questions asked, the ones the content did not answer first; `offered` the texts an offer was shown beside (from the searches the page named), so a false offer can be found. Counted rows only, like every statistics read.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
source
query
string
No
limit
query
int32
No
api-version
header
string
No
api-version
query
string
No