Statistics

Indx collects e-commerce-shaped search statistics per dataset: which searches happen, which results get chosen, and which choices convert. Searches are counted by the server itself — you send only what the server cannot see: the click and the conversion. A search counts when it has text and ran: one the server refused (a reason in the response) or that timed out is not search data, and is not counted. An empty search with a filter counts as browsing, reported per filter value. An empty search without one, such as a browse page opening, is not counted, and neither are searches from the web console's own search preview. The dataset's Statistics tab in the web console shows the same numbers these endpoints serve.


How the pieces connect

  1. Every search response carries an Indx-Query-Id header — an opaque id for that one search. It is CORS-exposed, so a browser client can read it:
js
const response = await fetch(searchUrl, { ...});
const queryId = response.headers.get('Indx-Query-Id');
  1. When the user clicks a result, send a select with that id, the document's key and its 1-based position. When something valuable happens — an order, an add-to-cart — send a convert.

  2. Aggregates come back from the statistics/* endpoints, merged over rolled-up days and live events.

A Search-level key (the one already in your storefront) is enough to send events; reading statistics needs a Read key. Events answer 202 Accepted — they are queued and batch-written.


Sending events

POST /api/teams/{teamName}/datasets/{dataSetName}/events/select

bash
curl -X POST https://your-host/api/teams/acme/datasets/products/events/select \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"queryId": "cf55aa99…", "documentKey": 42, "position": 1, "subject": "customer-123"}'

POST /api/teams/{teamName}/datasets/{dataSetName}/events/convert

bash
curl -X POST https://your-host/api/teams/acme/datasets/products/events/convert \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"documentKey": 42, "type": "order", "subject": "customer-123"}'
Field
queryId
optional
The value from the search response's Indx-Query-Id header. Optional on convert — an order may come long after the search, or from another channel; it still counts on the document. An unknown or expired id is accepted too: the event keeps its counts and just finds no search to join
documentKey
required
The document's key
position
select only, required
1-based position of the clicked result in the list
type
convert only, required
Your own name for the event: "order", "addToCart", "signup", …
value, currency, quantity
optional
Accepted and stored, not reported. Indx counts conversions as a search signal; what an order was worth belongs in your own systems
subject
optional
See below
count
optional
false for an event that is not a visitor's (a test, an agent). An event on a search that was sent with count=false is not counted either way

The event posts answer 202 before the event is written, and an unknown queryId is accepted, so the answer cannot tell you whether the click found its search. The reads can, within a few seconds (events are written in batches every couple of seconds, and the reads include them at once):

  1. Search for something unusual and click a result, with the Indx-Query-Id of that response as queryId.
  2. GET …/statistics/queries/documents?days=1&text=<the query> lists the document you clicked. A click that joined its search is counted on the query; one that did not is counted on the document only, so it shows in statistics/documents and not here.

Run the check counted: a search sent with count=false, and every click on it, is left out of the reads by design. A test dataset, or a single counted search you can live with, does it.

The session

Search-as-you-type sends a search on every keystroke, so typing "oslo" sends o, os, osl and oslo. Send the same session on each of them and only the one the visitor settled on is counted:

POST …/search?session=8f3a1c

The session also merges repeats. A front-end often sends the same search more than once: again with facets after a short delay, for a new sort, or to load more. The same session sending the same text and filter within 30 seconds is one search, and the click counts on the last one, so keep the Indx-Query-Id of the latest response. A request for no records (maxNumberOfRecordsToReturn: 0) is not counted at all.

A session is any random id you create per page load. It identifies no one, and it is never shown or stored anywhere but next to the search. Without one, the server can only leave out single letters, so the prefixes of longer queries are counted. A search that got a click is always counted.

A page rendered on the server needs a session too. Without a cookie there is no visitor to follow, so make the id per page view: create it when the results page is first rendered, and carry it in the links and forms that page sends, so paging, a new sort or a facet click repeat it. Without one, each of those counts as another search, and a popular query reads as more searches, with a lower click-through, than it had. The server does not merge searches without a session on its own: on a busy page, two visitors searching the same thing at the same time are two searches.

A strict search with a fuzzy retry is one search in one session. A common pattern searches with includePatternMatches: false first, so an empty answer is a trustworthy no-match, and only then again with pattern matching on, showing those results as guesses. Send both with the same session: they are the same text and filter, so they count as one search, the retry is the one kept, and a click on one of its results counts as a fuzzy find. Sent without a session they are two searches, one of them a search that found nothing.

The surface, and searches that should not count

A dataset can have several ways in: a search box in the header, a product finder, an app. Name the one a search came from with source, and it is stored with the search and counted as usual:

POST …/search?session=8f3a1c&source=header

A search that is not a visitor's - an agent checking what a query returns, a monitor, a test - sends count=false. It is stored, with its source, but left out of every statistic, the way the web console's own search preview is (stored as source console). A select or conversion on such a search is not counted either.

POST …/search?source=monitor&count=false

The subject

subject is one opaque string you define: an end-user id, a session id, or a customer segment. Send it on searches too (POST …/search?subject=customer-123) and the same statistics serve per-user personalization ("top 10 for this user"). Omitted means anonymous — don't invent a placeholder value; anonymous events are counted honestly as anonymous.

DELETE …/statistics/subjects/{subject} is the GDPR erasure: the subject's personalization rows are deleted and its raw events anonymised, so aggregate counts stay true while nothing ties them to the subject any more.


Reading statistics

All reads take ?days= (default 30) and need a Read-level key.

Days, in your time zone

A day runs from midnight to midnight in the dataset's time zone: UTC unless you choose another, or unless the server's operator set a default (Statistics:TimeZone). Every read counts in it, days=7 is the last seven of its days, today included, and from/to on a delete are its days. A Norwegian shop sets Oslo, and an evening search lands on the evening's day:

PUT …/statistics/settings   {"timeZone": "Europe/Oslo"}

The name is an IANA time zone. "" goes back to the default, and a name that is not a time zone is a 400. Changing it counts again every day whose searches are still kept, 90 days by default; older days keep the zone they were counted in. In the web console the choice is on the Options tab.

One surface at a time

overview, timeseries, queries, queries/documents, documents and filters take ?source=, and then count the searches sent with that source alone:

GET …/statistics/overview?days=7&source=typeahead
GET …/statistics/overview?days=7&source=books

A click or conversion counts for the surface of the search it names by queryId; one sent without a queryId belongs to no surface and is counted only in the totals. A source no search was sent with gives zeros, not the totals. A read for one surface comes from the stored searches, so it reaches back as far as they are kept, 90 days by default.

GET …/statistics/sources lists the surfaces in the window, most searched first, with their searches counted as the overview counts them. A surface where visitors only browsed (a filter, no text) is listed with 0 searches. Searches sent without a source are the row with "source": null:

json
[ { "source": "typeahead", "searches": 180 }, { "source": "books", "searches": 52 },
  { "source": null, "searches": 3 } ]

The web console's Statistics tab has the same choice, as a selector beside the period once any search has named its surface.

GET …/statistics/overview — the headline numbers:

json
{
  "searches": 1204, "uncovered": 96, "uncoveredRate": 0.08, "uncoveredChosen": 41, "clickedSearches": 311,
  "selects": 402, "converts": 58, "clickThroughRate": 0.258, "averageClickPosition": 2.4,
  "zeroHits": 37, "zeroHitRate": 0.031
}

Fuzzy finds are where Indx earns its keep. uncovered counts the searches with typos too large for an exact match: coverage confirmed nothing, so what the visitor saw came from fuzzy search alone, or nothing was shown. uncoveredChosen counts the ones where the visitor chose a result anyway, the searches fuzzy search answered. zeroHits remains for compatibility. A search made with coverage switched off is not counted as uncovered, since there is nothing to tell.

Rates are computed server-side so every consumer shares the definitions: click-through counts searches with at least one select against all searches (zero-hit ones included), and a rate whose denominator is zero is null, never 0%.

GET …/statistics/timeseries — one row per day ("date": "2026-09-29"), zero rows included so charts have no holes.

GET …/statistics/queries?limit=50 — top queries with searches, selects, click-through and average click position per query. order= picks the order: searches (the default), lowestClickThrough (searched often and chosen from rarely, so either the dataset lacks what people want or ranks it too low), highestClickThrough, and chosenAnyway with uncoveredOnly=true. The two click-through orders leave out queries searched fewer than five times, where one click reads as a rate of 100 %.

GET …/statistics/queries/documents?text=lamp lists, for one query, every document chosen from its results, most chosen first, with how often, the sum of the positions it was chosen at, and the conversions from the same searches. It tells a query that found the thing people meant from one that only offered a substitute. Read from the raw events, so up to 90 days back by default.

GET …/statistics/queries?uncoveredOnly=true — the misspelled searches behind the console's Fuzzy search section, each with uncovered (how often), uncoveredChosen (how often a result was chosen anyway) and mostChosenDocument, the result chosen most.

GET …/statistics/documents?limit=50 — top documents by selects, with conversions.

GET …/statistics/filters?limit=50 — browsing: how often people narrowed by each filter value, with or without text, and how often that left them nothing. A combined filter counts once per value in it; a range filter is reported by its field, with an empty value.

Browsing stores the filter of every search. On a dataset of people a filter value can be a name or a customer number, so it can be switched off per dataset: PUT …/statistics/settings with {"recordFilters": false} (Full key, team admin), or the Options tab in the web console. Switching it off stops the recording; filter values already recorded stay until they age out of retention or the dataset's statistics are erased. GET …/statistics/settings reads the setting; it is on by default.

GET …/statistics/subjects/{subject}?limit=10 — one subject's lifetime top documents.

Names beside the keys

documents, queries/documents and subjects/{subject} give each document a label beside its documentKey, and the misspelled-query list a mostChosenLabel: the value of one field, so a report can say which book rather than which number. It is the first searchable field (usually the title) unless you choose another:

PUT …/statistics/settings   {"labelField": "title"}

A nested field goes by its dotted path (author.name); an array field gives its first three values. "" goes back to the first searchable field, and a field the dataset does not have is a 400. A property you leave out of the PUT stays as it is, so this does not touch recordFilters. The label is read from the loaded index, and a statistics read never wakes a sleeping dataset: while it sleeps, label is null and the key stands alone. In the web console the choice is on the Options tab, beside the Browsing setting.


What changed, beside the numbers

When a number moves, the first question is what changed. Indx records the changes made to the dataset itself, so the answer sits next to the chart: synonyms saved, boost rules saved, fields changed, a reindex, a replace, the dataset hibernating or waking, a rename. Document inserts, updates and deletes are counted per day, and a single request that changes many documents at once (a thousand, or a tenth of the dataset if that is fewer) is recorded on its own, as is every delete-by-filter and update-by-filter. Configuring a dataset before its first index is setup, not a change, and is not recorded.

Only what changed and when is kept: counts and field names. Never the content, and never who made the change. In the web console the changes are small marks under the chart on the Statistics tab, with a list below it.

GET …/statistics/changes?days=30 — the window's changes, oldest first, each with at (UTC), kind and a small summary, and the document totals per day:

json
{
  "changes": [
    { "at": "2026-09-12T08:41:03Z", "kind": "synonyms", "summary": { "entriesBefore": 34, "entries": 44 } },
    { "at": "2026-09-14T02:04:51Z", "kind": "documents",
      "summary": { "operation": "deleteByFilter", "inserted": 0, "updated": 0, "deleted": 19000, "documents": 28000 } }
  ],
  "documents": [ { "date": "2026-09-14", "inserted": 0, "updated": 5200, "deleted": 19000 } ]
}

Lifecycle and retention

Statistics are keyed on the team and the dataset name — the same way document keys are yours — so they survive dataset deletion and recreation under the same name, a zero-downtime replace continues them seamlessly, and a dataset moved to another team takes them along. DELETE …/statistics (Full key, team Admin) is the one explicit way to start clean, and it deletes the change history too. In the web console it is on the dataset's Options tab.

To remove test traffic without losing the real history, delete part of it instead:

DELETE …/statistics?source=deploy-check                  one surface's searches
DELETE …/statistics?from=2026-10-06&to=2026-10-06       the searches of those days (inclusive)
DELETE …/statistics?source=deploy-check&from=2026-10-06  both

Each takes the searches it selects with their clicks and conversions, and keeps what the owners changed. By days, the daily totals of those days go too. By source, a select or conversion goes with the search it names by queryId, and the daily totals are counted again from what is left; days older than the raw events (90 days) keep that surface's share. A day that is not a date, or from after to, is a 400 and deletes nothing.

Raw events are kept 90 days (operator-configurable) and rolled up into daily aggregates that are kept until deleted. When the operator has switched the feature off, every route here answers 404 with code statisticsDisabled.

BoostRules

POST/api/teams/{teamName}/datasets/{dataSetName}/boosts/from-filter

CreateBoost will create a Boost setup which may be passed to any search.

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}/boosts

Returns the dataset's persisted boost rules (server-side ranking rules applied when a search sets enableBoost). Config, not state-gated — available even when not Ready.

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}/boosts

Replaces the dataset's boost rules (whole list). Each rule needs a name, at least one condition, and every condition must reference a Filterable field and be either a value match or a numeric range (not both).

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}/boosts

Clears all boost rules for the dataset.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No

DatasetExport

GET/api/teams/{teamName}/datasets/{dataSetName}/export

Downloads every document in the dataset as one JSON array, ordered by document key — the records as they were loaded, replaced or last updated, including fields that are not configured. Streams, so it works on a dataset of any size, and works whether the dataset is Ready, hibernated or idle-evicted. Any team member may export. Field configuration and boost rules are separate exports. `progress` is the console's: a token it counts the written records under, for its progress bar. Leave it out.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
progress
query
uuid
No
api-version
header
string
No
api-version
query
string
No

Datasets

POST/api/teams/{teamName}/datasets/{dataSetName}/analyze

As Analyze but handles a stream as input text.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/analyze/text

Analyze the fields of a string containing json. Since json may be invalid, which will cause a 400 error, it is sent as plain text.

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
string
PUT/api/teams/{teamName}/datasets/{dataSetName}

Creates the data set (201). Idempotent: an existing data set is left exactly as it is and answers 200. There is no longer a `configuration` query parameter — there was one configuration to choose from, so choosing was theatre. Clients that still send `?configuration=400` (every published `@indxsearch/intrface` does) are unaffected: a query value that binds to nothing is ignored, which `UnknownQueryParameterTests` pins. Note the one behaviour change that comes with it — a garbage value used to be a validation 400 from enum binding and is now simply ignored, which is safe only because the value no longer reaches anything.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
DELETE/api/teams/{teamName}/datasets/{dataSetName}

DeleteDataSet, will delete the entire dataSet including all contained Documents. Requires team Admin.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/status

GetStatus will return the status of the dataSetName in the search engine.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/me/datasets

Returns all datasets the current user can reach via team membership, across every team they belong to. Each entry carries the owning team name and the caller's role on it.

Parameters
NameInTypeRequired
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets

Lists the datasets owned by a single team.

Parameters
NameInTypeRequired
teamName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/index

IndexDataSet starts the index build and answers 202 with the status as it is then; the build goes on in the background. A Loaded dataset is indexed for the first time: poll GET status until `systemState` is Ready (a build that fails leaves the state it fell back to and `errorMessage`). A Ready dataset is rebuilt on a shadow engine and keeps serving meanwhile: poll until `shadowBuildInProgress` is false, then read `shadowBuildError`. Until Oct 2026 the request waited for the build.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/load/from-database

Loads the jsonData into search engine from the database.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/load

Loads the jsonData into search engine as a stream.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/replace

Atomically replaces the entire dataset's documents with the streamed JSON. Unlike delete+recreate this preserves the dataset's identity, field configuration, boost rules and description, serves the old data with zero downtime until the new index is ready, and leaves the old dataset untouched if the new JSON fails to build. Works whether the dataset is Ready, hibernated or idle-evicted (the old documents are never reloaded). Returns a summary of how the new schema differed from the previous field configuration.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/load/text

Loads the jsonData into search engine as a string.

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
string
POST/api/teams/{teamName}/datasets/{dataSetName}/hibernate

Hibernates the dataset: everything leaves memory while the documents stay in the store. The dataset reports Created with recordsOnDisk > 0 afterwards, and WakeUp — or, for a timed/pinned dataset, simply the next access — restores it.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/wakeup

Wakes a hibernated dataset — Created with records in the store — by reloading the documents from the store and rebuilding the index. The same operation the console's Wake button runs, so its progress shows there too.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No

DemoDatasets

POST/api/teams/{teamName}/demo-datasets/films

Creates the films demo in the team: about 25,000 films from Wikidata, with their field roles set, loaded and indexed. Answers 201 with the dataset's name once it is Ready, which takes a few seconds. The name is "films", or "films-2" and on when the team has one.

Parameters
NameInTypeRequired
teamName
path
string
Yes
api-version
header
string
No
api-version
query
string
No

Documents

DELETE/api/teams/{teamName}/datasets/{dataSetName}/documents/{documentKey}

Deletes a document from the dataset by its key.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
documentKey
path
int64
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/documents/{documentKey}

Inserts one single Json record. The route key must match the document's key field (the engine keys documents from the body, so a disagreeing route would otherwise silently insert under a different key than the URL claims).

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
documentKey
path
int64
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
string
PUT/api/teams/{teamName}/datasets/{dataSetName}/documents/{documentKey}

Updates one single Document. The route key must address an existing document and match the document's key field (the engine keys documents from the body, so a disagreeing route would otherwise silently update a different document than the URL claims).

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
documentKey
path
int64
Yes
api-version
header
string
No
api-version
query
string
No
Request Body
Content TypeSchema
application/json
string
PATCH/api/teams/{teamName}/datasets/{dataSetName}/documents/{documentKey}

Updates a single field on a document identified by its key.

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

Deletes documents from the dataset by their keys.

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
int64[]
POST/api/teams/{teamName}/datasets/{dataSetName}/documents

Inserts new JSON records into the dataset.

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
string[]
PUT/api/teams/{teamName}/datasets/{dataSetName}/documents

Updates existing JSON records in the dataset.

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
string[]
POST/api/teams/{teamName}/datasets/{dataSetName}/documents/lookup

Returns the raw json records as string[] for the keys.

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
int64[]
GET/api/teams/{teamName}/datasets/{dataSetName}/documents/count

Returns the number of JSON records in the database for the given dataset.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/documents/delete-by-filter

Deletes all documents matching the given filter.

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}/documents/update-by-filter

Updates a field on all documents matching the given filter. Returns the number of updated documents.

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

Events

POST/api/teams/{teamName}/datasets/{dataSetName}/events/select

The user chose a result: the document, its 1-based position, and optionally the queryId from the search response's Indx-Query-Id header and a subject.

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}/events/convert

Something the customer considers valuable happened for a document: an order, an add-to-cart — the type is theirs. QueryId is optional; without it the conversion still counts on the document.

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

Fields

GET/api/teams/{teamName}/datasets/{dataSetName}/fields

GetAllFields will return the fields found during analyze.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/facetable

GetFacetableFields will return the array of facetable field names.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/filterable

GetFilterableFields will return the array of filterable field names.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/searchable

GetSearchableFields will return the array of searchable field names.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/sortable

GetSortableFields will return the array of sortable field names.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/word-indexing

GetWordIndexingFields will return the array of word-indexing field names.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/embeddable

GetEmbeddableFields will return the array of embeddable (vector) field names.

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}/fields/configuration

SetFieldConfiguration sets any combination of field properties (Searchable, Filterable, Facetable, Sortable, WordIndexing, Embeddable, PreloadFilters, Weight, BM25b, BM25k1) in one call. Nullable properties have replace semantics: null = leave untouched, any value (including false) = overwrite. The whole request is checked before anything is changed, and a refused one is a 400 that changes nothing. An accepted one answers in one of two ways. <b>204</b>: the change is applied, which is every change on a dataset that is not serving yet and a change of query-time roles on one that is. <b>202</b> with the status: the change needs the index rebuilt on a dataset that is Ready, so a rebuild on a shadow engine has been started and the dataset serves with the old configuration until it is swapped in. Poll GET status until `shadowBuildInProgress` is false, then read `shadowBuildError`: null means the new configuration is in use. Until Oct 2026 the request waited for the rebuild, minutes on a large dataset.

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}/fields/configuration

GetFieldConfiguration returns the full configuration of every field in the dataset. Search level, not Read: a filter panel needs each field's type to know whether a selected value is a value filter or a range with equal limits, and the name lists it reads today do not carry it. A Search key can already search and read documents, so the types and sample values here reveal nothing it does not see.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/fields/key

Returns the dataset's declared key field — the JSON field whose value identifies each document (the primary key). Empty string means none is declared (the engine auto-generates keys). Required, when set, to be a numeric field.

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}/fields/key

Declares the dataset's key field (the JSON field whose value is each document's primary key). Pass an empty string to clear it (auto-generated keys). The field must be numeric. The choice is preserved across reloads and applied on the next Load/replace; documents already loaded keep their existing keys until the data is reloaded.

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
string

Filters

POST/api/teams/{teamName}/datasets/{dataSetName}/filters/combine

CombineFilters will combine two filters using AND or OR operation.

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}/filters/not

NegateFilter returns a filter matching every document the given filter does not: the NOT of a value, range or combined filter. The result is a token like any other and can be combined further.

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}/filters/range

CreateRangeFilter will create a RangeFilter which may be passed to any search.

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}/filters/value

CreateValueFilter will create a ValueFilter which may be passed to any search. Case-insensitive unless `isCaseSensitive` is set; see Indx.Http.ValueFilterProxy for when it should be, and what it costs.

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}/filters/delete

Deletes a single filter from the filter cache.

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}/filters

Deletes all filters from the filter cache.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/filters/load

Pre-loads all registered filters in the background.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/filters/count

Returns the number of filters currently registered in the filter cache.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No

QueryParameters

GET/api/teams/{teamName}/datasets/{dataSetName}/query-parameters

Returns what the dataset sets (`parameters`, null where it sets nothing) and what a search that sends no coverage values runs with (`effective`, every value filled in). Config, not state-gated: available while the dataset is asleep. A search key may read it: it says how this dataset's searches run, and a search page shows it beside its own values.

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}/query-parameters

Replaces the dataset's query parameters. A value left out (or null) is not set, and a search that leaves it out too gets the engine default. Applies from the next search; 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}/query-parameters

Clears the dataset's query parameters: searches get the engine defaults again.

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

Search will validate the search query and return the search result.

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/vector

Searches a single embedding field using approximate nearest-neighbour search.

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/hybrid

Combines text search with embedding nearest-neighbour search and blends scores.

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

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

Statistics

GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/overview

The window's totals and rates - the dashboard's header numbers. Rates are computed here so every consumer shares the definitions (see the response type).

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/timeseries

The per-day series behind the charts: one row per UTC day in the window. Days without events are served as zero rows, so a chart never has holes.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/queries

Top queries in the window: searches, zero-hit count and selects per query text (lowercased). With uncoveredOnly=true, the searches without coverage: those coverage confirmed nothing for, how often a result was chosen anyway, and the document chosen most (mostChosenDocument), which is usually the synonym or spelling to add. order=lowestClickThrough lists the queries searched often and chosen from rarely (highestClickThrough the reverse; both leave out queries searched fewer than five times, where one click reads as 100%), and order=chosenAnyway with uncoveredOnly the fuzzy finds. With zeroHitsOnly=true, the zero-hit report — the searches the dataset could not answer, ordered by how often.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
limit
query
int32
No
zeroHitsOnly
query
boolean
No
uncoveredOnly
query
boolean
No
order
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/queries/documents

For one query (text, compared lowercased like the query list): which documents visitors chose from its results, most chosen first, with the position sum and the conversions from the same searches. A query searched often and chosen from rarely is either missing what people want or ranking it too low; which of the two, and whether the choices were the thing itself or a substitute, is read from this list. From the raw rows, so as far back as they are kept (90 days by default).

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
text
query
string
No
days
query
int32
No
limit
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/filters

Browsing in the window: how often people narrowed by each filter value, with or without text, and how often that came back empty. A combined filter counts once per operand; a range counts by its field, with an empty value.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
limit
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/documents

Top documents in the window: selects, converts and summed convert value per document key. The keys are the customer's own; titles are looked up by key.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
limit
query
int32
No
source
query
string
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/sources

The surfaces searches came from in the window, most searched first: each `?source=` with its searches, counted as the overview counts them, and a row with a null source for the searches that named none. From the raw rows (90 days by default).

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/subjects/{subject}

One subject's lifetime top documents — the personalization read ("top 10 per user"). The subject is whatever the customer sent on the events.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
subject
path
string
Yes
limit
query
int32
No
api-version
header
string
No
api-version
query
string
No
DELETE/api/teams/{teamName}/datasets/{dataSetName}/statistics/subjects/{subject}

The GDPR erasure of one subject: the subject↔document edge is deleted and the raw rows are anonymised, so aggregate counts stay true while nothing ties them to the subject any more.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
subject
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/changes

What the dataset's owners changed in the window, oldest first, and the daily document totals: the why beside the numbers (Notes/statistics-design.md, "Change events").

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
days
query
int32
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/statistics/settings

The dataset's statistics settings. `recordFilters`: whether each search's filter is stored, which is what the Browsing report counts. On by 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}/statistics/settings

Changes the dataset's statistics settings; a property left out stays as it is. Switching `recordFilters` off stops recording filters; what is already recorded stays until it ages out or the statistics are erased. `labelField` names the field the statistics show beside a document key; `""` goes back to the first searchable field, and a field the dataset does not have is a 400. Team admin, Full key: a privacy setting sits here.

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}/statistics

Deletes the dataset's statistics. Bare, every row: the explicit purge, since statistics survive dataset delete/recreate and starting clean is a choice made here. With `source` and/or `from`/`to` (UTC days, yyyy-MM-dd, inclusive), only the visitor events they select: the searches sent with that source or in those days, with their selects and conversions, so test traffic can go without the real history. The owners' changes and the subjects' lifetime top documents stay then. By source, days older than the raw rows' retention (90 by default) keep that surface's share.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
source
query
string
No
from
query
string
No
to
query
string
No
api-version
header
string
No
api-version
query
string
No

Synonyms

GET/api/teams/{teamName}/datasets/{dataSetName}/synonyms

Returns the dataset's synonym list, or a `null` body when it has none — always 200. The list widens every search on this dataset: a query word that matches an entry gets that entry's terms appended to the query text before scoring. One list per dataset — there is no name to supply, and no other dataset is affected.

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}/synonyms

Sets the dataset's synonym list, replacing any list it already had. Send a body of `null` to remove the list — the dataset then searches without synonyms again. Takes effect on the very next search: synonyms are applied to the query text, so nothing is re-indexed and the dataset does not have to be in any particular state. The list is stored with the dataset, so it survives a restart and follows the dataset if it is transferred to another team. Note that widening a query lowers Coverage scores in proportion to how much text is added — see the remarks on `Indx.Api.SynonymList`.

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

WebhookReceiver

POST/hooks/{webhookId}
Parameters
NameInTypeRequired
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/hooks/{webhookId}/sync

The full set, replacing the dataset's documents: a list of documents, or `{ "documents": [...] }`, signed like any call.

Parameters
NameInTypeRequired
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No

Webhooks

GET/api/teams/{teamName}/datasets/{dataSetName}/webhooks/sources

The sources a webhook can have, with their settings.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/webhooks

Makes a webhook for the dataset. The answer carries its address and its secret, which is shown only here: the sender authenticates each call with it, the way its source does. A dataset without documents yet is filled by the first full sync, which also gives it a key field; a webhook whose source Indx fetches from runs that sync at once.

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}/webhooks

The dataset's webhooks, with how many calls wait to be applied and how many batches the brake holds.

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}/webhooks/{webhookId}

Changes a webhook's name, version field, brake and source settings. A secret setting left out keeps the one set. Settings that change what Indx fetches start a full sync. The source, the id field and the secret stay as they are.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
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}/webhooks/{webhookId}
Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/rotate-secret

A new secret, shown once; the old one stops working at once.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/deliveries

The latest calls, newest first: what each applied, ignored and refused, and why.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
limit
query
int32
No
api-version
header
string
No
api-version
query
string
No
GET/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/held

The batches the brake holds, waiting for an admin to apply or discard them.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
DELETE/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/held

Discards every held batch: nothing in them is applied.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/held/{heldId}/apply

Applies a held batch as it came, past the brake.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
heldId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/sync

Fetches the full set from the webhook's source now and replaces the dataset's documents with it (a Sanity or Contentful webhook). A webhook whose sender pushes its own sync is told where.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
POST/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/held/apply

Applies every held batch, oldest first. A busy dataset stops it (409); the batches not yet applied stay held, in their order.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
api-version
header
string
No
api-version
query
string
No
DELETE/api/teams/{teamName}/datasets/{dataSetName}/webhooks/{webhookId}/held/{heldId}

Discards a held batch: nothing in it is applied.

Parameters
NameInTypeRequired
teamName
path
string
Yes
dataSetName
path
string
Yes
webhookId
path
string
Yes
heldId
path
string
Yes
api-version
header
string
No
api-version
query
string
No

Schemas

AskRequest

A question, and for a follow-up the conversation so far (the last three turns are used). `Proactive`: the page started this answer on its own, in the proactive mode, rather than the visitor asking; it counts against the day's proactive answers.

PropertyTypeDefault
question
string
—
history
object[]
—
proactive
boolean
—

AskShown

On a catalogue, the list a turn put on the page: its filters, words and order. A follow-up ("which is the largest?") is about that list.

PropertyTypeDefault
filters
object[]
—
text
string
—
sort
object
—

AskTurn

An earlier question and its answer in the same conversation, for a follow-up.

PropertyTypeDefault
question
string
—
answer
string
—
shown
object
—

BoostCondition

One condition of a boost rule: a filterable field matched either by an exact IndxServer.Models.BoostCondition.Value (string/keyword fields) or by a numeric IndxServer.Models.BoostCondition.Min/IndxServer.Models.BoostCondition.Max range. Exactly one of the two forms is used: if IndxServer.Models.BoostCondition.Min or IndxServer.Models.BoostCondition.Max is set it's a range, otherwise IndxServer.Models.BoostCondition.Value is an exact match.

PropertyTypeDefault
field
string
—
value
string
—
min
double
—
max
double
—
isRange
boolean
—

BoostProxy

PropertyTypeDefault
boostStrength
int32
—
filterProxy
object
—

BoostRule

A persisted, per-dataset ranking rule: when a search has `enableBoost` on, documents matching this rule's combined condition get their score lifted by IndxServer.Models.BoostRule.Strength. Rules are managed in the UI and applied server-side; see `BoostRuleStore`.

PropertyTypeDefault
name
string
—
enabled
boolean
—
conditions
object[]
—
join
int32
—
strength
int32
—
activeFrom
date
—
activeUntil
date
—

ChangePasswordRequest

Body of POST /api/changePassword. Used to rotate the seeded admin's initial password (set at deployment time) before any other API calls can be made.

PropertyTypeDefault
currentPassword
string
—
newPassword
string
—

CombinedFilterProxy

PropertyTypeDefault
a
object
—
b
object
—
useAndOperation
boolean
—

ConvertEventRequest

The convert event: whatever the customer considers valuable (order, add-to-cart, …). Type is the customer's own name for it. Value/Currency/Quantity are optional commerce magnitudes. QueryId is optional — a conversion may happen long after the search or from another channel, and still counts on the document. Count as for IndxServer.Models.SelectEventRequest.

PropertyTypeDefault
queryId
string
—
documentKey
int64
—
type
string
—
value
double
—
currency
string
—
quantity
int64
—
subject
string
—
count
boolean
—

CoverageSetupProxy

PropertyTypeDefault
includePatternMatches
boolean
—
levenshteinMaxWordSize
int32
—
minWordSize
int32
—
truncateWordHitLimit
int32
—
truncateWordHitTolerance
int32
—
coverWholeQuery
boolean
—
coverWholeWords
boolean
—
coverFuzzyWords
boolean
—
coverJoinedWords
boolean
—
coverPrefixSuffix
boolean
—
truncate
boolean
—
truncationScore
int32
—

CreateWebhookRequest

PropertyTypeDefault
name
string
—
idField
string
—
versionField
string
—
brakeShare
double
—
source
string
—
settings
object
—

DatasetQueryParameters

A dataset's query parameters: the values a search takes when its request leaves them out. The same shape, names and meaning as the coverage part of a search body, so a value can be copied between the two. Null means "not set here", and the engine default applies. Resolution, field by field: the request, then this, then the engine default (IndxServer.Services.QueryParameterResolution).

PropertyTypeDefault
coverageDepth
int32
—
coverageSetup
object
—

DemoCreated

The dataset made, and its name.

PropertyTypeDefault
dataSet
string
—

FieldProxy

PropertyTypeDefault
fieldName
string
—
fieldType
string
—
isArray
boolean
—
optional
boolean
—
sampleValue
string
—
searchable
boolean
—
filterable
boolean
—
facetable
boolean
—
sortable
boolean
—
wordIndexing
boolean
—
embeddable
boolean
—
preloadFilters
boolean
—
weight
float
—
bM25b
float
—
bM25k1
float
—
highResolution
boolean
—

FilterFieldUpdateProxy

PropertyTypeDefault
filter
object
—
fieldName
string
—
value
any
—

FilterProxy

PropertyTypeDefault
hashString
string
—

FilterSuggestion

One filter the description asked for: a value (text, or true/false) or a number range, either end open. Field and value are the dataset's own, checked against what it holds.

PropertyTypeDefault
field
string
—
value
string
—
min
double
—
max
double
—

FiltersRequest

PropertyTypeDefault
text
string
—

HybridQueryProxy

PropertyTypeDefault
text
string
—
maxNumberOfRecordsToReturn
int32
10
filter
object
—
timeOutLimitMilliseconds
int32
1000
embeddingField
string
—
vector
float[]
—
alpha
float
0.5

IntentRequest

The text to judge. `Prefetch`: asked while the visitor still types, ahead of the pause; it warms the judge's cache and is not counted as a judgement.

PropertyTypeDefault
text
string
—
prefetch
boolean
—

JsonNode

PropertyTypeDefault
options
object
—
parent
object
—
root
object
—

JsonNodeOptions

PropertyTypeDefault
propertyNameCaseInsensitive
boolean
—

LicenseInfo

PropertyTypeDefault
description
string
—
documentLimit
int32
—
documentLimitExceeded
boolean
—
expirationDate
date-time
—
licenseFileFound
boolean
—
licensed
boolean
—
licensedTo
string
—
licenseFileName
string
—
type
string
—
validLicense
boolean
—

ParseResult

PropertyTypeDefault
token
string
—
progressPercent
int32
—
recordIndex
int32
—
isEndOfStream
boolean
—
errorType
int32
—
errorMessage
string
—
lineNumber
int64
—
bytePositionInLine
int64
—
jsonPath
string
—
wasSanitized
boolean
—
originalToken
string
—

ProblemDetails

PropertyTypeDefault
type
string
—
title
string
—
status
int32
—
detail
string
—
instance
string
—

ProcessError

PropertyTypeDefault
source
string
—
message
string
—
parseError
object
—
timeStampUtc
date-time
—

ProcessErrorCount

PropertyTypeDefault
error
object
—
count
int32
—

QueryProxy

PropertyTypeDefault
boosts
object[]
null
coverageDepth
int32
null
coverageSetup
object
—
enableBoost
boolean
false
enableCoverage
boolean
true
enableFacets
boolean
false
fieldBoosts
object
null
filter
object
—
logPrefix
string
null
maxNumberOfRecordsToReturn
int32
30
removeDuplicates
boolean
true
sortAscending
boolean
false
sortBy
string
null
text
string
—
timeOutLimitMilliseconds
int32
1000

RangeFilterProxy

PropertyTypeDefault
fieldName
string
—
lowerLimit
double
—
upperLimit
double
—

SearchOrAskPhrases

Ask phrases: the words a question is built with, taken off its start so the list searches what the question is about while the visitor is still typing it. "Help me find the movie about the green ogre" searches "green ogre", which finds Shrek; the whole sentence does not, since "movie" and "find" match titles better than "ogre" matches a description (measured on tmdb23k, 20 Oct 2026). No model and no pause: the page applies the list on every keystroke, and the judge's search reads the same text, so it judges the results the question is about. Four groups, matched in order from the start, each the longest phrase that fits: a lead-in ("help me find"), what is asked for ("the movie"), the word that links it to the rest ("about"), and an article. Nothing is taken unless the start has a question's shape (a lead-in of two words or more, a one-word lead-in with what is asked for, or what is asked for with its link) and a word of substance is left: "help" (a title), "help me find" (unfinished), "film noir" and "what we do in the shadows" search as typed. Then the end: what is asked for, typed after the subject, comes off too, so "show me green ogre movie" searches "green ogre" (Shrek first; with "movie" left on it came third). Only once the start had a question's shape, and only when two words are left, one of substance: a title ending in "Movie" keeps it when one word stands before it ("show me bee movie", "show me the lego movie", "scary movie"; 194 of tmdb23k's 23k titles end so), where a description seldom has fewer than two ("green ogre", "tom hanks island"). A dataset's own, kept with its Search or ask settings; null there means IndxServer.Services.SearchOrAsk.SearchOrAskPhrases.Default. The lead-ins, links and articles are the language's; the frames are the dataset's nouns, which is where a catalogue adds its own ("the movie", "the product"). Observr can suggest additions from the statistics: questions that did not start with a known phrase.

PropertyTypeDefault
leadIns
string[]
—
frames
string[]
—
links
string[]
—
articles
string[]
—

SearchOrAskSettings

A dataset's Search or ask settings (IndxServer.Services.SearchOrAsk.SearchOrAskStore). Text and numbers only: the request the judge receives has a fixed shape, so an owner, or Observr after a yes, can make the judge better or worse but cannot break the endpoint.

PropertyTypeDefault
enabled
boolean
—
shown
boolean
—
kind
string
—
siteDescription
string
—
titleField
string
—
sectionFields
string[]
—
snippetFields
string[]
—
thresholds
object
—
mode
string
—
dailyProactiveAnswers
int32
—
cutWhileAsking
boolean
—
cutShareOfTop
double
—
cutTopFloor
double
—
strictCoverageWhileAsking
boolean
—
filtersWhileTyping
string
—
filterNotes
string
—
answerInstructions
string
—
knowledge
string
—
answerLanguage
string
—
answers
string
—
answerModel
string
—
searches
string
—
askPhrases
object
—
refocusWhileTyping
boolean
—
inviteOnAskPhrase
boolean
—
dailyCallBudget
int32
—

SearchOrAskThresholds

Where Jev's probability becomes an offer. Entered at one value and left only below a lower one, so the offer does not blink while a visitor types; the client applies that, since it depends on what this visitor has been shown. Defaults measured on the docs set (Notes/search-or-ask.md): no lookup scored above 0.22 there.

PropertyTypeDefault
strong
double
—
strongHide
double
—
invite
double
—
inviteHide
double
—
hint
double
—
finished
double
—

SelectEventRequest

The select event: the user chose a result. QueryId is the value the search response returned in its `Indx-Query-Id` header; it is optional and opaque — an unknown or expired id still counts on the document, it just finds no search to join. Position is 1-based in the result list. Subject is the optional general identity: a user, a session or a customer-defined segment. Count is false for a select that is not a visitor's (a probe, a test); a select on a search that was not counted is not counted either, whatever it says. See Notes/statistics-design.md.

PropertyTypeDefault
queryId
string
—
documentKey
int64
—
position
int32
—
subject
string
—
count
boolean
—

ServerSystemStatus

SystemStatus extended with server-layer fields that the core library has no knowledge of.

PropertyTypeDefault
documentCount
int32
—
errorMessage
string
—
invalidArgument
boolean
—
invalidDataSetName
boolean
—
invalidState
boolean
—
licenseInfo
object
—
recoverableErrors
object[]
—
searchCounter
int32
—
secondsToIndex
double
—
systemState
int32
—
timeOfInstanceCreation
date-time
—
timeOfLastIndexBuild
date-time
—
tooLongSearchText
boolean
—
indexedTextTruncated
boolean
—
unrecoverableErrors
object[]
—
version
string
—
recordsOnDisk
int32
—
fieldsDiscovered
int32
—
shadowBuildInProgress
boolean
—
shadowBuildStartedUtc
date-time
—
shadowBuildFinishedUtc
date-time
—
shadowBuildError
string
—

ShownRequest

PropertyTypeDefault
shown
boolean
—

SortSuggestion

An order the description asked for ("størst", "flest elever"): a Sortable field.

PropertyTypeDefault
field
string
—
descending
boolean
—

StatisticsSettingsUpdate

A change to the statistics settings (PUT …/statistics/settings). A property left out stays as it is; labelField "" goes back to the first searchable field, timeZone "" to the instance's default.

PropertyTypeDefault
recordFilters
boolean
—
labelField
string
—
timeZone
string
—

SynonymEntry

PropertyTypeDefault
direction
int32
—
source
string
—
terms
string[]
—

SynonymList

PropertyTypeDefault
name
string
—
description
string
—
updatedUtc
date-time
—
entries
object[]
—

UpdateFieldProxy

PropertyTypeDefault
fieldName
string
—
value
any
—

UpdateWebhookRequest

The settings an admin may change once a webhook is made.

PropertyTypeDefault
name
string
—
versionField
string
—
brakeShare
double
—
settings
object
—

ValueFilterProxy

PropertyTypeDefault
fieldName
string
—
value
any
—
isCaseSensitive
boolean
—

VectorQueryProxy

PropertyTypeDefault
fieldName
string
—
vector
float[]
—
maxResults
int32
10
filter
object
—