Schemas

Reference for all request and response shapes used by the HTTP API.


QueryProxy

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

json
{
  "text": "wireless headphones",
  "maxNumberOfRecordsToReturn": 20,
  "enableCoverage": true,
  "coverageDepth": 500,
  "enableFacets": false,
  "enableBoost": false,
  "removeDuplicates": true,
  "sortBy": null,
  "sortAscending": false,
  "timeOutLimitMilliseconds": 1000,
  "filter": null,
  "boosts": null,
  "fieldBoosts": { "title": 2.0 },
  "coverageSetup": null
}

coverageDepth — how many pattern-match candidates coverage confirms, default 500. Hits past that depth are never evaluated, so on a broad query the shortfall appears as a total that lands exactly on the depth: a count equal to coverageDepth is the cap, not your data. Raise it to the document count on small and mid-sized datasets, and use the same depth for the result list and the facet counts. See Deep coverage.

enableFacets — required for an empty text. Empty text with enableFacets: false is refused, not treated as match-everything: 200, no records, and reason set to Search called with empty string and EnableFacets=false. The dataset also needs at least one facetable field. See Empty search.

fieldBoosts — per-query multipliers on each field's configured weight (a field with weight: 2.0 and a boost of 2.0 counts 4×). Keys must be searchable fields: a key that is not empties the whole search, returned today as 200 with no records. Only applies in BM25F mode. null, or a field left out, uses the configured weight unchanged. See Search for details.


Result

Response from POST /api/teams/{teamName}/datasets/{dataSetName}/search

json
{
  "records": [
    { "documentKey": 42, "score": 220 },
    { "documentKey": 17, "score": 185 }
  ],
  "facets": {
    "category": [
      { "key": "electronics", "value": 12 },
      { "key": "accessories", "value": 5 }
    ]
  },
  "truncationIndex": -1,
  "truncationScore": 0,
  "didTimeOut": false
}

score is a 16-bit unsigned integer (0–65535). truncationIndex is the position of the last result that reached the coverage bar, and -1 when none did: on a text query with coverage on, every result is then a pattern match. It is also -1 when coverage did not run.

reason is present when the engine refused the query rather than finding nothing — an empty text without enableFacets, text over the 300-character limit, a dataset that is not ready. The records are empty either way, so check reason alongside didTimeOut and report a refusal as a failure rather than as an empty result.


VectorQueryProxy

POST /api/teams/{teamName}/datasets/{dataSetName}/search/vector

json
{
  "fieldName": "embedding",
  "vector": [0.12, -0.45, 0.33],
  "maxResults": 10,
  "filter": null
}

The vector must match the dimension of the indexed embedding field. Its length does not matter: Indx brings it to unit length.


HybridQueryProxy

POST /api/teams/{teamName}/datasets/{dataSetName}/search/hybrid

json
{
  "text": "comfortable wireless headphones",
  "embeddingField": "embedding",
  "vector": [0.12, -0.45, 0.33],
  "alpha": 0.6,
  "maxNumberOfRecordsToReturn": 20,
  "filter": null,
  "timeOutLimitMilliseconds": 1000
}

alpha — blend weight in [0, 1]. 0 = pure text, 1 = pure embedding.


EmbeddingResultEntry

Response from search/vector and search/hybrid

json
[
  { "documentKey": 42, "score": 0.94 },
  { "documentKey": 17, "score": 0.81 }
]

score is in [0, 1]. For vector search it is cosine similarity; for hybrid search it is the blended value.


FieldProxy

Used by PUT fields/configuration (request) and GET fields/configuration (response). null on a PUT means "leave unchanged".

json
[
  {
    "fieldName": "name",
    "fieldType": "String",
    "isArray": false,
    "searchable": true,
    "filterable": false,
    "facetable": false,
    "sortable": false,
    "wordIndexing": false,
    "embeddable": false,
    "preloadFilters": false,
    "highResolution": false,
    "weight": 2.0,
    "bM25b": 0.75,
    "bM25k1": 1.2,
    "highResolution": false
  }
]

fieldType and isArray are read-only — they are populated by the server on GET and ignored on PUT.


SystemStatus

Response from GET /api/teams/{teamName}/datasets/{dataSetName}/status

json
{
  "systemState": 4,
  "documentCount": 5000,
  "recordsOnDisk": 5000,
  "fieldsDiscovered": 12,
  "searchCounter": 142,
  "secondsToIndex": 3,
  "shadowBuildInProgress": false,
  "shadowBuildStartedUtc": null,
  "version": "5.0.0",
  "licenseInfo": { ... },
  "errorMessage": "",
  "timeOfInstanceCreation": "2025-01-01T00:00:00Z",
  "timeOfLastIndexBuild": "2025-01-01T00:05:00Z"
}

systemState values: 0 Created · 1 Loading · 2 Loaded · 3 Indexing · 4 Ready · 255 Error

A hibernated dataset reports Created together with recordsOnDisk > 0; fieldsDiscovered says how many fields its stored configuration holds. (-1 Hibernated existed until Sep 2026 and was removed.)


DataSetListDto

Response from GET /api/me/datasets

json
[
  { "name": "products", "teamName": "acme", "role": "Admin" },
  { "name": "catalogue", "teamName": "research", "role": "Editor" }
]

role is "Admin", "Editor", or "Viewer" — your role on the owning team.


TransferToTeamRequest

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

json
{ "targetTeamName": "research" }

Moves the dataset to another team. The caller must be an Admin of both teams.


FilterProxy

A filter reference returned by filters/value, filters/range, filters/combine or filters/not. Pass it back in search or bulk-operation requests.

json
{ "hashString": "abc123..." }

ValueFilterProxy

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

json
{
  "fieldName": "category",
  "value": "electronics",
  "isCaseSensitive": false
}

value may be a string, a number or a boolean. isCaseSensitive is optional and off by default; a facet count equals a filter count only for a case-sensitive filter, and a case-sensitive filter is answered by walking the documents rather than by the field's index, so it costs more.

The field must not hold numbers. A value filter compares text, so on a numeric field the request is answered 400 naming the filter to use instead — see RangeFilterProxy.


RangeFilterProxy

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

json
{
  "fieldName": "price",
  "lowerLimit": 10,
  "upperLimit": 100
}

Both limits are inclusive, and equal limits are numeric equality — that is how to match one value on a numeric field. The field must hold numbers; a number stored as a JSON string is text, and the request is answered 400 saying to store the values as numbers and load again.


BoostProxy

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

json
{
  "filterProxy": { "hashString": "abc123..." },
  "boostStrength": 2
}

boostStrength: 1 = Low, 2 = Med, 3 = High.

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
—