curl --request POST \
--url https://api.cludo.com/api/v4/{customerId}/{engineId}/search \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "*",
"page": 1,
"perPage": 10,
"filters": {},
"notFilters": {},
"postFilters": {},
"postFiltersOperator": "AND",
"sort": {},
"fields": [
"<string>"
],
"highlight": true,
"enableFacetFiltering": true,
"rangeFacets": {},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [
{
"boost": 200,
"values": [
"Featured"
]
}
]
}
],
"operator": "OR",
"enableRelatedSearches": false,
"enableHybridSearch": true
}
'import requests
url = "https://api.cludo.com/api/v4/{customerId}/{engineId}/search"
payload = {
"query": "*",
"page": 1,
"perPage": 10,
"filters": {},
"notFilters": {},
"postFilters": {},
"postFiltersOperator": "AND",
"sort": {},
"fields": ["<string>"],
"highlight": True,
"enableFacetFiltering": True,
"rangeFacets": {},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [
{
"boost": 200,
"values": ["Featured"]
}
]
}
],
"operator": "OR",
"enableRelatedSearches": False,
"enableHybridSearch": True
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '*',
page: 1,
perPage: 10,
filters: {},
notFilters: {},
postFilters: {},
postFiltersOperator: 'AND',
sort: {},
fields: ['<string>'],
highlight: true,
enableFacetFiltering: true,
rangeFacets: {},
valueBoost: [{fieldName: 'Category', boosts: [{boost: 200, values: ['Featured']}]}],
operator: 'OR',
enableRelatedSearches: false,
enableHybridSearch: true
})
};
fetch('https://api.cludo.com/api/v4/{customerId}/{engineId}/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '*',
page: 1,
perPage: 10,
filters: {},
notFilters: {},
postFilters: {},
postFiltersOperator: 'AND',
sort: {},
fields: ['<string>'],
highlight: true,
enableFacetFiltering: true,
rangeFacets: {},
valueBoost: [{fieldName: 'Category', boosts: [{boost: 200, values: ['Featured']}]}],
operator: 'OR',
enableRelatedSearches: false,
enableHybridSearch: true
})
};
fetch('https://api.cludo.com/api/v4/{customerId}/{engineId}/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"TypedDocuments": [
{
"ResultIndex": 1,
"Score": 12.84,
"TitleHasHighlight": true,
"Fields": {
"Title": {
"Field": "Title",
"Value": "Search API overview",
"Values": [
"Search API overview"
],
"Highlights": [
"<b>Search</b> API overview"
],
"IsArray": false
},
"Url": {
"Field": "Url",
"Value": "https://docs.example.com/search-api",
"Values": [
"https://docs.example.com/search-api"
],
"Highlights": [],
"IsArray": false
}
}
}
],
"TotalDocument": 847,
"Facets": {
"Category": {
"FieldName": "Category",
"Field": "Category",
"MissingCount": 14,
"AllCount": 847,
"Items": [
{
"Key": "Documentation",
"Count": 412
},
{
"Key": "Tutorial",
"Count": 235
}
]
}
},
"RangeFacets": {
"This year": [
42
]
},
"Banners": [
{
"id": 1001,
"name": "Featured promotion",
"websiteid": 12345
}
],
"Suggestions": [
"search api",
"search setup"
],
"Synonyms": [
"query",
"lookup"
],
"RelatedSearchDocuments": [
"getting started",
"api authentication"
],
"FixedQuery": "",
"ResponseTime": 96,
"QueryId": "a3f2c1b8-4e9d-4a1c-9b2e-7f4d6e8a1c3d",
"GenerativeAnswerAvailable": true
}{
"message": "The request could not be processed. Check the request body and required parameters."
}{
"message": "unauthorized"
}{
"status": "InternalServerError",
"code": 500,
"messages": [
"Error occur. Please contact support with error ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890"
]
}Search
Execute a full-text search query with filters, facets, and sorting.
curl --request POST \
--url https://api.cludo.com/api/v4/{customerId}/{engineId}/search \
--header 'Authorization: <api-key>' \
--header 'Content-Type: application/json' \
--data '
{
"query": "*",
"page": 1,
"perPage": 10,
"filters": {},
"notFilters": {},
"postFilters": {},
"postFiltersOperator": "AND",
"sort": {},
"fields": [
"<string>"
],
"highlight": true,
"enableFacetFiltering": true,
"rangeFacets": {},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [
{
"boost": 200,
"values": [
"Featured"
]
}
]
}
],
"operator": "OR",
"enableRelatedSearches": false,
"enableHybridSearch": true
}
'import requests
url = "https://api.cludo.com/api/v4/{customerId}/{engineId}/search"
payload = {
"query": "*",
"page": 1,
"perPage": 10,
"filters": {},
"notFilters": {},
"postFilters": {},
"postFiltersOperator": "AND",
"sort": {},
"fields": ["<string>"],
"highlight": True,
"enableFacetFiltering": True,
"rangeFacets": {},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [
{
"boost": 200,
"values": ["Featured"]
}
]
}
],
"operator": "OR",
"enableRelatedSearches": False,
"enableHybridSearch": True
}
headers = {
"Authorization": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '*',
page: 1,
perPage: 10,
filters: {},
notFilters: {},
postFilters: {},
postFiltersOperator: 'AND',
sort: {},
fields: ['<string>'],
highlight: true,
enableFacetFiltering: true,
rangeFacets: {},
valueBoost: [{fieldName: 'Category', boosts: [{boost: 200, values: ['Featured']}]}],
operator: 'OR',
enableRelatedSearches: false,
enableHybridSearch: true
})
};
fetch('https://api.cludo.com/api/v4/{customerId}/{engineId}/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));const options = {
method: 'POST',
headers: {Authorization: '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
query: '*',
page: 1,
perPage: 10,
filters: {},
notFilters: {},
postFilters: {},
postFiltersOperator: 'AND',
sort: {},
fields: ['<string>'],
highlight: true,
enableFacetFiltering: true,
rangeFacets: {},
valueBoost: [{fieldName: 'Category', boosts: [{boost: 200, values: ['Featured']}]}],
operator: 'OR',
enableRelatedSearches: false,
enableHybridSearch: true
})
};
fetch('https://api.cludo.com/api/v4/{customerId}/{engineId}/search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));{
"TypedDocuments": [
{
"ResultIndex": 1,
"Score": 12.84,
"TitleHasHighlight": true,
"Fields": {
"Title": {
"Field": "Title",
"Value": "Search API overview",
"Values": [
"Search API overview"
],
"Highlights": [
"<b>Search</b> API overview"
],
"IsArray": false
},
"Url": {
"Field": "Url",
"Value": "https://docs.example.com/search-api",
"Values": [
"https://docs.example.com/search-api"
],
"Highlights": [],
"IsArray": false
}
}
}
],
"TotalDocument": 847,
"Facets": {
"Category": {
"FieldName": "Category",
"Field": "Category",
"MissingCount": 14,
"AllCount": 847,
"Items": [
{
"Key": "Documentation",
"Count": 412
},
{
"Key": "Tutorial",
"Count": 235
}
]
}
},
"RangeFacets": {
"This year": [
42
]
},
"Banners": [
{
"id": 1001,
"name": "Featured promotion",
"websiteid": 12345
}
],
"Suggestions": [
"search api",
"search setup"
],
"Synonyms": [
"query",
"lookup"
],
"RelatedSearchDocuments": [
"getting started",
"api authentication"
],
"FixedQuery": "",
"ResponseTime": 96,
"QueryId": "a3f2c1b8-4e9d-4a1c-9b2e-7f4d6e8a1c3d",
"GenerativeAnswerAvailable": true
}{
"message": "The request could not be processed. Check the request body and required parameters."
}{
"message": "unauthorized"
}{
"status": "InternalServerError",
"code": 500,
"messages": [
"Error occur. Please contact support with error ID: a1b2c3d4-e5f6-7890-abcd-ef1234567890"
]
}responseType body field that controls the response format. See Autocomplete → responseType for the comparison; for Search, set it as a JSON body field rather than a query parameter.
Full search request example
A real-world search rarely sends just aquery. The example below exercises most body parameters at once — pagination, field selection, highlighting, facets, range facets, include/exclude filters, value boosting, sorting, and related searches — with representative values you can adapt.
# Use https://api-us1.cludo.com for the US region
curl -X POST "https://api.cludo.com/api/v4/{customerId}/{engineId}/search" \
-H "Authorization: SiteKey {token}" \
-H "Content-Type: application/json" \
-d '{
"query": "search api",
"operator": "AND",
"page": 1,
"perPage": 20,
"responseType": "JsonObject",
"fields": ["Title", "Url", "Description", "Category", "Language", "Date"],
"highlight": true,
"enableFacetFiltering": true,
"enableRelatedSearches": true,
"filters": {
"Category": ["Documentation", "Guides"],
"Language": ["en"]
},
"notFilters": {
"Status": ["Archived"]
},
"rangeFacets": {
"Published this year": {
"fieldName": "Date_date",
"ranges": [{ "from": "2026-01-01", "to": "2026-12-31" }]
},
"Published last year": {
"fieldName": "Date_date",
"ranges": [{ "from": "2025-01-01", "to": "2025-12-31" }]
}
},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [{ "boost": 200, "values": ["Featured"] }]
}
],
"sort": {
"Date_date": "Descending"
}
}'
import requests
# Use https://api-us1.cludo.com for the US region
url = "https://api.cludo.com/api/v4/{customerId}/{engineId}/search"
headers = {
"Authorization": "SiteKey {token}",
"Content-Type": "application/json",
}
payload = {
"query": "search api",
"operator": "AND",
"page": 1,
"perPage": 20,
"responseType": "JsonObject",
"fields": ["Title", "Url", "Description", "Category", "Language", "Date"],
"highlight": True,
"enableFacetFiltering": True,
"enableRelatedSearches": True,
"filters": {
"Category": ["Documentation", "Guides"],
"Language": ["en"],
},
"notFilters": {
"Status": ["Archived"],
},
"rangeFacets": {
"Published this year": {
"fieldName": "Date_date",
"ranges": [{"from": "2026-01-01", "to": "2026-12-31"}],
},
"Published last year": {
"fieldName": "Date_date",
"ranges": [{"from": "2025-01-01", "to": "2025-12-31"}],
},
},
"valueBoost": [
{
"fieldName": "Category",
"boosts": [{"boost": 200, "values": ["Featured"]}],
},
],
"sort": {
"Date_date": "Descending",
},
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())
// Use https://api-us1.cludo.com for the US region
const payload = {
query: "search api",
operator: "AND",
page: 1,
perPage: 20,
responseType: "JsonObject",
fields: ["Title", "Url", "Description", "Category", "Language", "Date"],
highlight: true,
enableFacetFiltering: true,
enableRelatedSearches: true,
filters: {
Category: ["Documentation", "Guides"],
Language: ["en"],
},
notFilters: {
Status: ["Archived"],
},
rangeFacets: {
"Published this year": {
fieldName: "Date_date",
ranges: [{ from: "2026-01-01", to: "2026-12-31" }],
},
"Published last year": {
fieldName: "Date_date",
ranges: [{ from: "2025-01-01", to: "2025-12-31" }],
},
},
valueBoost: [
{
fieldName: "Category",
boosts: [{ boost: 200, values: ["Featured"] }],
},
],
sort: {
Date_date: "Descending",
},
};
const response = await fetch(
"https://api.cludo.com/api/v4/{customerId}/{engineId}/search",
{
method: "POST",
headers: {
"Authorization": "SiteKey {token}",
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
},
);
const data = await response.json();
console.log(data);
// Use https://api-us1.cludo.com for the US region
const payload = {
query: "search api",
operator: "AND",
page: 1,
perPage: 20,
responseType: "JsonObject",
fields: ["Title", "Url", "Description", "Category", "Language", "Date"],
highlight: true,
enableFacetFiltering: true,
enableRelatedSearches: true,
filters: {
Category: ["Documentation", "Guides"],
Language: ["en"],
},
notFilters: {
Status: ["Archived"],
},
rangeFacets: {
"Published this year": {
fieldName: "Date_date",
ranges: [{ from: "2026-01-01", to: "2026-12-31" }],
},
"Published last year": {
fieldName: "Date_date",
ranges: [{ from: "2025-01-01", to: "2025-12-31" }],
},
},
valueBoost: [
{
fieldName: "Category",
boosts: [{ boost: 200, values: ["Featured"] }],
},
],
sort: {
Date_date: "Descending",
},
};
const response = await fetch(
"https://api.cludo.com/api/v4/{customerId}/{engineId}/search",
{
method: "POST",
headers: {
"Authorization": "SiteKey {token}",
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
},
);
const data: unknown = await response.json();
console.log(data);
Combining filters and facets (AND / OR)
Faceted search is driven by thefilters and notFilters objects. Each key is an indexed field name and each value is an array of values. The way they combine is fixed and predictable:
| Combination | Behaviour |
|---|---|
| Multiple values in the same field | Combined with OR — a document matches if it has any of the listed values |
| Multiple different fields | Combined with AND — a document must match every field’s condition |
notFilters | Combined with AND NOT — matching documents are excluded |
operator (AND / OR) is separate from facet filtering. It controls how the words in query are matched against the index — it does not change how filters are combined. Filters always follow the OR-within-field, AND-across-fields rules above.OR within a single field
Return documents in eitherDocumentation or Guides:
{
"query": "search api",
"filters": {
"Category": ["Documentation", "Guides"]
}
}
AND across multiple fields
Return documents that are inDocumentation and written in English and published — every field condition must hold:
{
"query": "search api",
"filters": {
"Category": ["Documentation"],
"Language": ["en"],
"Status": ["Published"]
}
}
Combining OR within fields and AND across fields
The two rules stack. The request below means: (Documentation OR Guides) AND (en OR da):
{
"query": "search api",
"filters": {
"Category": ["Documentation", "Guides"],
"Language": ["en", "da"]
}
}
Excluding values with notFilters
Keep the include filters above but exclude anything that isArchived or Draft (the exclusions are AND-NOT’d onto the result):
{
"query": "search api",
"filters": {
"Category": ["Documentation", "Guides"]
},
"notFilters": {
"Status": ["Archived", "Draft"]
}
}
"operator": "AND" for the text query and add your filters — they work together: the operator tightens the keyword match while filters apply the facet AND/OR logic.Filter value formats
filters, notFilters, and postFilters share the same value grammar. Each key is normally an indexed field name mapped to an array of allowed values. In addition, three reserved keys — range, date, and geo_distance — express numeric ranges, date ranges, and geo-distance filters. Each reserved key takes a flat array of positional arguments, and you can repeat the argument group to add several filters of that type at once.
Value
Match a field against one or more exact values (the common facet case):{
"filters": {
"Category": ["Publications", "Events"],
"DocumentType": ["PDF"]
}
}
Range (numeric)
Reserved keyrange, in groups of three: [field, min, max]. Bounds are inclusive (>= / <=); pass an empty string to leave a bound open. Use . as the decimal separator.
{
"filters": {
"range": ["Price", "20", "100", "WheelRimSize", "25.5", ""]
}
}
Date range
Reserved keydate, in groups of three: [field, from, to]. Values are ISO 8601 strings; an empty string leaves that side open. Date fields are the indexed date fields (typically _date-suffixed).
{
"filters": {
"date": ["PublishDate_date", "2025-01-01", "2025-12-31"]
}
}
2017-06-13, 2017-06-13T02:50:25Z, and 2017-06-13T02:50:25+00:00. When no time is given, the whole day is included.
Geo distance
Reserved keygeo_distance, exactly five items: [field, latitude, longitude, distance, unit]. The field is the _geo_point-suffixed geo field.
{
"filters": {
"geo_distance": ["Location_geo_point", "50.3453456", "-9.546456", "100", "Kilometers"]
}
}
unit is one of Inch, Feet, Yards, Miles, NauticalMiles, Kilometers, Meters, Centimeters, Millimeters.
range, date, and geo_distance are reserved keys inside the filter object — you cannot use them as literal field names. All four formats work identically in filters, notFilters, and postFilters.Post-filtering (narrow results without changing facet counts)
filters and notFilters run with the query, so they shape both the ranked results and the Facets counts. postFilters runs after the query as a post-filter: it narrows the documents returned without recomputing the facet counts.
This is what powers classic faceted navigation — when a user ticks one value in a facet you want the results to narrow, but the other counts in that facet should stay visible so they can broaden their selection again.
| Field | Type | Notes |
|---|---|---|
postFilters | object | Same { "Field": ["value", …] } shape as filters. Filters results, not facets. |
postFiltersOperator | string | AND (default) — every field must match. OR — any field may match. |
"enableFacetFiltering": true. postFilters cannot be combined with advancedPostFilter in the same request.{
"query": "search api",
"filters": {
"Category": ["Documentation", "Guides"]
},
"postFilters": {
"Language": ["en"]
},
"postFiltersOperator": "AND"
}
Boosting values at query time
Filters decide which documents come back.valueBoost changes what order they come back in: it promotes documents whose field matches values you name, for a single request, without removing anything from the result set.
It applies on top of the boosting rules configured on the engine rather than replacing them, so you can tune results per audience or per context without changing engine configuration.
{
"query": "search api",
"valueBoost": [
{
"fieldName": "Category",
"boosts": [
{ "boost": 300, "values": ["Featured", "Guides"] },
{ "boost": 200, "values": ["Documentation"] }
]
},
{
"fieldName": "Language",
"boosts": [{ "boost": 250, "values": ["en"] }]
}
]
}
| Field | Type | Notes |
|---|---|---|
fieldName | string | The indexed field to match against. |
boosts | array | One or more { boost, values } rules for that field. |
boost | integer | Weight applied when a value matches. 100 is neutral; higher values promote. |
values | array | Field values that trigger this weight. |
Choosing a weight
100 is neutral and leaves ranking unchanged. Raise it to promote: 200 is a moderate lift, 500 a strong one. Start low and increase — a high weight can promote loosely related documents above closely matching ones.
Use valueBoost to promote the content you want surfaced. It is not a reliable way to push content down; to remove documents from a result set, use notFilters or postFilters instead.
Matching
Values are matched exactly and case-sensitively."Featured" and "featured" are different values, and a value that matches nothing simply has no effect — no error is returned.
valueBoost does not use the field-name object shape that filters, notFilters, and postFilters share. It is an array of { fieldName, boosts } entries. Sending the object form returns 200 with the parameter ignored.valueBoost is also accepted on AI Chat, where it shapes the documents used to ground the answer. It is not accepted on AI Summary, which summarises sources you supply — apply the boost to the Search request that produces those sources instead.
Pagination
| Field | Type | Notes |
|---|---|---|
page | integer | |
perPage | integer |
TotalDocument in the response gives the total number of matching documents — use it together with perPage to compute how many pages exist. If you need result counts higher than the deep-pagination cap, narrow the query with filters instead of paginating further.Authorizations
SiteKey authentication. Pass the full value including the SiteKey prefix: SiteKey <base64(customerId:engineId:searchKey)>. Example: SiteKey dGVzdDoxMjM0NTY3Ojk4NzY1. See the Authentication guide for details.
Path Parameters
The search engine to query. Must match the engine ID in your SiteKey.
Body
Search text. Use * with operator: OR for match-all. Maximum 300 characters; longer queries are rejected with a 400 error.
"*"
Page to retrieve, starting at 1.
x >= 11
Results per page.
x >= 110
Include filter. Each key is an indexed field name mapped to allowed values ({"Category": ["Analytics"]}). The reserved keys range, date, and geo_distance express numeric, date, and geo-distance filters — see Filter value formats.
Show child attributes
Show child attributes
Exclude filter: same grammar as filters (value / range / date / geo_distance). Removes matching documents.
Show child attributes
Show child attributes
Post-filter: same field-name → values shape as filters (value / range / date / geo_distance — see Filter value formats). Unlike filters/notFilters (which run with the query and shape both ranking and facet counts), post-filters are applied after the query — they narrow the documents returned without changing the Facets counts. This is what powers faceted navigation: ticking one facet value filters the results while the other facet counts stay intact. Set enableFacetFiltering: true to also apply them to the returned facets. Cannot be combined with advancedPostFilter.
Show child attributes
Show child attributes
How multiple post-filter fields combine: AND (default) requires every field to match; OR requires any one.
AND, OR "AND"
Sort by field. Value: Ascending or Descending. Multiple entries apply secondary sorts in order.
Show child attributes
Show child attributes
JsonObject — structured TypedDocuments (recommended). JsonHtml — pre-rendered HTML fragments.
JsonObject, JsonHtml Limits which fields are returned on each hit. Only the fields listed here will appear in TypedDocument.Fields — all others are omitted from the response.
Wrap matching terms in <b>…</b> via each field's Highlights array.
When true, the request's postFilters (or advancedPostFilter) are also applied to the returned facet counts, so counts reflect the post-filtered result set. When false (default), facets show the full pre-post-filter distribution. This flag does not control whether facets are returned — that is driven by the engine's configured facet fields.
Count documents in date or numeric ranges. Each key becomes a label in the RangeFacets response with an array of counts per range. Example: {"This year": {"fieldName": "Date_date", "ranges": [{"from": "2024-01-01", "to": "2024-12-31"}]}}.
Show child attributes
Show child attributes
Promote documents whose field matches specific values, for this request only. Applies on top of the boosting rules configured on the engine. Note this is an array, not a field-name object like filters.
Show child attributes
Show child attributes
OR — any term matches (broader). AND — all terms required (narrower).
AND, OR "OR"
Populate RelatedSearchDocuments with suggested follow-up queries.
false
AI Search ranking is enabled by default on AI-enabled engines. Set to false to opt out and use keyword-only ranking for this request.
Response
Search results returned successfully.
Ranked hits for the current page (at most perPage items).
Show child attributes
Show child attributes
Total matching documents across all pages.
Per-field aggregation buckets for the engine's configured facet fields. enableFacetFiltering controls whether postFilters constrain these counts — not whether the object is present.
Show child attributes
Show child attributes
Document counts for each range bucket defined in the request's rangeFacets.
Show child attributes
Show child attributes
Promotional banners triggered by this query.
Spell-correction / "did you mean" strings.
Synonym terms applied for this query.
Suggested follow-up queries (when enableRelatedSearches is true).
Spell-corrected query string used for retrieval, or null if unchanged.
Server-side processing time in milliseconds.
ID for this search — pass to tracking and AI endpoints.
Whether AI Chat can answer this query.
Was this page helpful?

