Endpoints
All endpoints are prefixed with /api/ and require JWT Bearer authentication unless noted.
Dataset endpoints are scoped to a team and a dataset:
/api/teams/{teamName}/datasets/{dataSetName}/{operation}The tables below list the {operation} for each dataset endpoint. Endpoints that are not dataset-scoped (listing datasets, account) show their full path.
The current API version is 2.0-beta. It is the default — no version header is needed for standard use. If you want to be explicit, pass it as a header or query string:
api-version: 2.0-beta # header
?api-version=2.0-beta # query stringAuthentication
Create an API key in the console (Account → API keys, /account/api-key), then send it as a Bearer header on every request.
curl -H "Authorization: Bearer <key>" https://your-host/api/...Every key is limited to one team, optionally to some of its datasets, and to an access level:
| Level | Can call | Use it for |
|---|---|---|
Search only | search, search/vector, search/hybrid, documents/lookup, events/select, events/convert, filters/value, filters/range, filters/combine, filters/not, boosts/from-filter, fields/facetable, fields/filterable, fields/sortable, fields/searchable, GET fields/configuration, status, and PUT on an existing dataset | Websites and apps — the key is visible in the browser, and this is all it can do |
Read only | Every read: adds export, fields/configuration, synonyms, boosts, statistics/*, counts, dataset lists | Exports, reporting, agents, back-ups — keep it on a server |
Full access | Everything your team role allows, including loading, changing and deleting data | Your own servers and pipelines |
A key never exceeds its owner's role in the team: a Viewer can create Search and Read keys, not Full ones. Keys cannot be changed after they are created — create a new one and revoke the old. A key outside its limits gets the same answer as a missing team or dataset (404 teamNotFound / datasetNotFound); a call above its level gets 403 insufficientKeyScope. Keys created before access levels existed are unscoped and reach every team you belong to — replace them.
Personal keys and team keys
There are two kinds of key, with the same access levels:
| Personal key | Team key | |
|---|---|---|
Created under | Account → API keys | Manage team → API keys, by a team Admin |
Acts as | You: never more than your role in the team | The team: its access level alone. Full access writes as an Editor does; deleting datasets and managing the team stay with people ( 403 insufficientRole) |
If its creator leaves the team | Stops working | Keeps working |
Seen and revoked by | You | Every Admin of the team |
Use it for | Your own scripts and AI agents | A production website, a shared server, CI |
For anything deployed, use a team key, so it does not depend on one person's account.
Showing a key again. Search only and Read only keys can be shown again from the key list (Show key): a personal key to its owner, a team key to the team's Admins. Full access keys are shown once, when they are created; lost one? Create a new key and revoke the old. A Read only key created before October 2026 was not stored and cannot be shown again either. Every key is listed with its last four characters (…a1b2), so you can match the key in a config file to its row.
Expiry. Keys last 30, 90, 180 or 365 days. A team Search only key can also be set to never expire. The team's Admins are notified 30 and 7 days before a team key expires.
Rotating a key without downtime. Create the new key, deploy it, check that traffic works, then revoke the old one. Revoking takes effect at once.
Error responses
Every error is an RFC 9457 ProblemDetails served as application/problem+json, with a machine-readable code extension — branch on code (or the status), never on the detail text.
| Status | code | Meaning |
|---|---|---|
400 | invalidArgument, invalidDatasetName, loadFailed, operationFailed | The request or its payload can't be served — see detail |
400 | unknownFilter | A referenced filter hashString could not be resolved — re-create the filter and retry with the new token |
401 | — (body-less) | Missing, expired, or invalid bearer token |
401 | invalidCredentials, userNotFound | Login failed |
403 | insufficientRole | You are a member, but your team role is too low (needs Editor/Admin) |
403 | insufficientKeyScope | Your role allows it, but the API key's access level does not (a Search key calling a write, say) |
404 | teamNotFound | The team doesn't exist or you are not a member (identical on purpose, so team names can't be enumerated) |
404 | datasetNotFound, documentNotFound | The addressed dataset or document key doesn't exist |
404 | statisticsDisabled | Statistics are switched off on this instance — the events and statistics routes are unavailable |
409 | invalidState, shadowBusy | Wrong lifecycle state, or a background rebuild is already running |
429 | rateLimited | A rate limit or capacity cap was hit — always retryable after retryAfterSeconds |
500 | internalError | Unexpected server error — report the included traceId |
Batch document operations are all-or-nothing: a bad key or record rejects the whole batch (missing keys are all named in one documentNotFound problem) and nothing is applied. The single-document routes POST documents/{documentKey} and PUT documents/{documentKey} require the route key to match the body's key field.
A 409 invalidState is returned when a request is valid but the dataset's systemState can't serve it — for example calling search before the dataset is Ready, or wakeup when it is already up:
{
"status": 409,
"detail": "The dataset is being indexed. Try again in a moment.",
"code": "invalidState",
"currentState": "Indexing",
"allowedStates": ["Ready"],
"retryable": true
}When retryable is true (states Loading / Indexing) the response also carries a Retry-After header (seconds): poll GET status until Ready, then retry. When retryable is false (e.g. Created, Error), take the corrective step from detail first — Created with recordsOnDisk > 0 in the status is a hibernated dataset, so POST wakeup; Created with nothing stored → POST load then POST index. Resending the same request without changing the state will keep returning 409.
A 429 rateLimited means nothing is wrong with the request; the server is asking you to slow down. It carries retryAfterSeconds and a matching Retry-After header, and is always retryable — wait that long, then send the same request again:
{
"status": 429,
"title": "Rate limit exceeded",
"detail": "This API key exceeded 50 requests per second (burst 200). Try again in 1 seconds.",
"code": "rateLimited",
"retryAfterSeconds": 1
}Three limits share this response. Which one you hit is in detail, but the handling is the same:
| Limit | Applies to | Default |
|---|---|---|
Login attempts | POST /api/login and the dashboard's login and password forms, per client address | 10 per minute |
Per API key | All authenticated calls, per key — only where the operator enabled it | 50 requests/s, burst 200 |
No valid token | Calls to /api or /mcp whose bearer token is missing, expired or invalid, per client address | 30 per minute |
To stay clear of them: send documents in batches (the documents endpoints take arrays) rather than one call per record. The operator's side of these limits is in Server Setup.
Note that a busy dataset is a 409, not a 429: a rebuild that is already running does not queue another behind it.
Datasets
| Method | Path / Operation | Description |
|---|---|---|
GET | /api/me/datasets | List every dataset across the teams you belong to (each with its team and your role) |
GET | /api/teams/{teamName}/datasets | List the datasets owned by one team |
PUT | /api/teams/{teamName}/datasets/{dataSetName} | Create or open a dataset — 201 if it was created, 200 if it already existed |
GET | status | Get current engine state and counters |
DELETE | /api/teams/{teamName}/datasets/{dataSetName} | Permanently delete the dataset and all its data (team Admin) — 204 |
Data Loading
| Method | Operation | Description |
|---|---|---|
POST | analyze | Discover fields from a streamed JSON body |
POST | analyze/text | Discover fields from a JSON string ( text/plain) |
POST | load | Load documents from a streamed JSON body — 204 |
POST | load/text | Load documents from a JSON string ( text/plain) — 204 |
POST | replace | Atomically replace the whole dataset, preserving config + boost rules (zero-downtime) |
POST | load/from-database | Reload documents from the persisted database — 204 |
POST | index | Start the index build — 202 Accepted at once, with the status; the build runs in the background. First build: poll GET status until Ready. Rebuild of a Ready dataset: poll until shadowBuildInProgress is false, then read shadowBuildError |
GET | documents/count | Count documents stored in the database — {"count": n} |
Field Configuration
| Method | Operation | Description |
|---|---|---|
PUT | fields/configuration | Set field roles, weights and BM25 parameters, for any number of fields in one call — 204 when applied at once, 202 when it started a rebuild (see below) |
GET | fields/configuration | Get current configuration for all fields |
GET | fields | List all discovered field names |
GET | fields/searchable | List searchable fields |
GET | fields/filterable | List filterable fields |
GET | fields/facetable | List facetable fields |
GET | fields/sortable | List sortable fields |
GET | fields/word-indexing | List word-indexed fields |
GET | fields/embeddable | List vector (embeddable) fields |
GET / PUT | fields/key | Get / set the key field ( PUT returns needsReloadToReKey in the body) |
Roles are written in one place. The role lists above are read-only. Until October 2026 each also had a
PUT(PUT fields/searchableand the rest, andPUT fields/embeddable); those are removed and answer405. Send the same change toPUT fields/configuration: one object per field, with only the properties you want changed.
What PUT fields/configuration answers
The whole request is checked before anything is changed. A request that is refused — an unknown field, a negative weight, a vector field given another role — is a 400 and changes nothing.
An accepted request answers in one of two ways:
| Answer | Meaning | What to do |
|---|---|---|
204 | The change is applied. Every change before the dataset is indexed, and a change of query-time roles (filterable, facetable, sortable, weight) on fields already in use | Nothing |
202 + status | The change needs the index rebuilt and the dataset is Ready. A rebuild has been started on a shadow engine; the dataset keeps serving with the old configuration until it is swapped in | Poll GET status until shadowBuildInProgress is false. shadowBuildError is then null if the new configuration is in use, or says why the rebuild failed (the old configuration is still in use) |
{
"systemState": 4,
"shadowBuildInProgress": false,
"shadowBuildStartedUtc": null,
"shadowBuildFinishedUtc": "2026-10-05T07:12:44.103Z",
"shadowBuildError": null
}While a rebuild runs, a second configuration change, a POST index and a bulk document change are refused with 409 shadowBusy: retry when shadowBuildInProgress is false. Until October 2026 the request waited for the rebuild — minutes on a large dataset, past the timeout of most HTTP clients.
A vector field has no other role: a field marked embeddable cannot also be searchable, filterable, facetable, sortable or word-indexed, and only an array of numbers can be marked embeddable.
Search
| Method | Operation | Description |
|---|---|---|
POST | search | Full-text search |
POST | search/vector | Embedding-based nearest-neighbour search |
POST | search/hybrid | Blended text + embedding search |
POST | documents/lookup | Retrieve full JSON documents by key (body: key array) |
Dynamic Operations
| Method | Operation | Description |
|---|---|---|
POST | documents/{documentKey} | Insert a single document — 201 |
POST | documents | Batch insert documents — 201 |
PUT | documents/{documentKey} | Replace a single document — 204 |
PUT | documents | Batch replace documents — 204 |
PATCH | documents/{documentKey} | Update one field on one document — 204 |
POST | documents/update-by-filter | Update a field on all documents matching a filter — {"count": n} |
DELETE | documents/{documentKey} | Delete a single document — 204 |
DELETE | documents | Delete multiple documents by key array — 204 |
POST | documents/delete-by-filter | Delete all documents matching a filter — 204 |
Filters
| Method | Operation | Description |
|---|---|---|
POST | filters/value | Create a filter matching a specific field value |
POST | filters/range | Create a filter matching a field value range |
POST | filters/combine | Combine two filters with AND or OR |
POST | filters/not | Negate a filter: every document it does not match |
POST | filters/load | Pre-load all registered filters into memory — 204 |
GET | filters/count | Count currently cached filters — {"count": n} |
POST | filters/delete | Release a cached filter (filter key in the body) — 204 |
DELETE | filters | Release all cached filters — 204 |
Boosts
| Method | Operation | Description |
|---|---|---|
GET | boosts | List the dataset's saved boost rules |
PUT | boosts | Replace the dataset's saved boost rules — 204 |
DELETE | boosts | Delete all saved boost rules — 204 |
POST | boosts/from-filter | Create a score boost for documents matching a filter |
Statistics and Events
Searches are counted by the server itself; the client reports selects and conversions. The
search response's Indx-Query-Id header (CORS-exposed) is what joins them — full detail on the
Statistics page.
| Method | Operation | Description |
|---|---|---|
POST | events/select | The user chose a result ( queryId?, documentKey, 1-based position, subject?, count?) — Search key → 202 |
POST | events/convert | A conversion ( type, optional value/currency/quantity, optional queryId/subject/count) — Search key → 202 |
GET | statistics/overview | The window's totals and rates ( ?days=30) — Read key |
GET | statistics/timeseries | One row per UTC day, zero rows included — Read key |
GET | statistics/queries | Top queries ( ?order=); uncoveredOnly=true = the misspelled searches fuzzy search answered or missed. Read key |
GET | statistics/queries/documents | For one query ( ?text=): the documents chosen from its results. Read key |
GET | statistics/documents | Top documents by selects, with conversions. Read key |
GET | statistics/subjects/{subject} | One subject's lifetime top documents — Read key |
DELETE | statistics | Purge the dataset's statistics (Full key, team Admin) — 204 |
DELETE | statistics/subjects/{subject} | GDPR erasure of one subject (Full key, team Admin) — 204 |
Lifecycle
| Method | Operation | Description |
|---|---|---|
POST | hibernate | Release memory while preserving the document store — 204 |
POST | wakeup | Restore from hibernation — 204 |
Teams
Access is governed by team membership — a user is an Admin, Editor, or Viewer of every dataset their team owns. Membership is managed from the account portal's team pages, not the API. The only cross-team API operation is moving a dataset:
| Method | Operation | Description |
|---|---|---|
POST | transfer | Move the dataset to another team (body: { "targetTeamName": "..." }; caller must be Admin of both teams) |
Account
| Method | Path | Description |
|---|---|---|
POST | /api/change-password | Change password |
API tokens are created on the API Key page of the account portal (
/Account/ApiKey), not via an API call.
BoostRules
CreateBoost will create a Boost setup which may be passed to any search.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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).
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object[] |
Clears all boost rules for the dataset.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
DatasetExport
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
progress | query | uuid | No |
api-version | header | string | No |
api-version | query | string | No |
Datasets
As Analyze but handles a stream as input text.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
DeleteDataSet, will delete the entire dataSet including all contained Documents. Requires team Admin.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetStatus will return the status of the dataSetName in the search engine.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
api-version | header | string | No |
api-version | query | string | No |
Lists the datasets owned by a single team.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Loads the jsonData into search engine from the database.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Loads the jsonData into search engine as a stream.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Loads the jsonData into search engine as a string.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
DemoDatasets
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Documents
Deletes a document from the dataset by its key.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
documentKey | path | int64 | Yes |
api-version | header | string | No |
api-version | query | string | No |
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).
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
documentKey | path | int64 | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string |
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).
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
documentKey | path | int64 | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string |
Updates a single field on a document identified by its key.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
documentKey | path | int64 | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Deletes documents from the dataset by their keys.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | int64[] |
Inserts new JSON records into the dataset.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string[] |
Updates existing JSON records in the dataset.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string[] |
Returns the raw json records as string[] for the keys.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | int64[] |
Returns the number of JSON records in the database for the given dataset.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Deletes all documents matching the given filter.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Updates a field on all documents matching the given filter. Returns the number of updated documents.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Events
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Fields
GetAllFields will return the fields found during analyze.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetFacetableFields will return the array of facetable field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetFilterableFields will return the array of filterable field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetSearchableFields will return the array of searchable field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetSortableFields will return the array of sortable field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetWordIndexingFields will return the array of word-indexing field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
GetEmbeddableFields will return the array of embeddable (vector) field names.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object[] |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | string |
Filters
CombineFilters will combine two filters using AND or OR operation.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
CreateRangeFilter will create a RangeFilter which may be passed to any search.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Deletes a single filter from the filter cache.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Deletes all filters from the filter cache.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Pre-loads all registered filters in the background.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Returns the number of filters currently registered in the filter cache.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
QueryParameters
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Clears the dataset's query parameters: searches get the engine defaults again.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Search
Search will validate the search query and return the search result.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Searches a single embedding field using approximate nearest-neighbour search.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Combines text search with embedding nearest-neighbour search and blends scores.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
SearchOrAsk
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Replaces the dataset's settings. Applies from the next call; no reindex.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
Removes the dataset's settings: the feature is off and every value back to its default.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
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
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).
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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).
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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).
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
days | query | int32 | No |
api-version | header | string | No |
api-version | query | string | No |
One subject's lifetime top documents — the personalization read ("top 10 per user"). The subject is whatever the customer sent on the events.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
subject | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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").
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
days | query | int32 | No |
api-version | header | string | No |
api-version | query | string | No |
The dataset's statistics settings. `recordFilters`: whether each search's filter is stored, which is what the Browsing report counts. On by default.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
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.
| Name | In | Type | Required |
|---|---|---|---|
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
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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`.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
WebhookReceiver
| Name | In | Type | Required |
|---|---|---|---|
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
The full set, replacing the dataset's documents: a list of documents, or `{ "documents": [...] }`, signed like any call.
| Name | In | Type | Required |
|---|---|---|---|
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Webhooks
The sources a webhook can have, with their settings.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
The dataset's webhooks, with how many calls wait to be applied and how many batches the brake holds.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
| Content Type | Schema |
|---|---|
application/json | object |
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
A new secret, shown once; the old one stops working at once.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
The latest calls, newest first: what each applied, ignored and refused, and why.
| Name | In | Type | Required |
|---|---|---|---|
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 |
The batches the brake holds, waiting for an admin to apply or discard them.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Discards every held batch: nothing in them is applied.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Applies a held batch as it came, past the brake.
| Name | In | Type | Required |
|---|---|---|---|
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 |
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.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Applies every held batch, oldest first. A busy dataset stops it (409); the batches not yet applied stay held, in their order.
| Name | In | Type | Required |
|---|---|---|---|
teamName | path | string | Yes |
dataSetName | path | string | Yes |
webhookId | path | string | Yes |
api-version | header | string | No |
api-version | query | string | No |
Discards a held batch: nothing in it is applied.
| Name | In | Type | Required |
|---|---|---|---|
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 |