Search

Full-text search, result export, index management, saved searches, and search profiles.

Search

Overview

The Search API provides endpoints for querying the search index, exporting results, and managing the index itself. The portal API extends this with saved searches and search profiles for personalized search experiences.

Integration Developer Guide

Before diving into the endpoint reference, here are the key concepts you need to know to use search effectively in an integration:

Search Spans All Content Definitions

A search query without filters returns results across all content definitions simultaneously — assets, committee records, meeting records, and everything else in the system. In most integration scenarios, you will want to filter to a specific content type:

{ "fieldName": "contentDefinitionId", "value": "<your-content-def-id>" }

Field Names Come From the Content Definition Designer

The fieldName values used in filters and sortFields must exactly match the property name of the field as configured in the Site Manager content definition designer. The property name is set when creating or editing a field — it becomes the field's permanent key in the search index.

Use GET /admin/search/mappingFieldNames to retrieve all currently indexed field names.

Start With Filters and Sort Fields

For the majority of integration use cases — syncing records, looking up items by external ID, listing content by type — the two most important SearchModel parameters are:

  • filters — narrow results to the records you care about
  • sortFields — control ordering for consistent pagination

All other parameters (distinct values, AI-based search, deep search) are advanced options for specific use cases.

Pagination — Keyset Cursor, Not Numeric Offset

The nextPageOffset value returned in each search response is a keyset cursor (a sort-key array used as a search_after token), not a page number or record count. Pass it verbatim as pageOffset in the next request. Do not construct offsets manually.

The practical pagination loop is:

let pageOffset = null;
while (true) {
  const result = await search(filters, pageOffset);
  for (const item of result.items) process(item);
  pageOffset = result.nextPageOffset ?? null;
  if (!pageOffset || result.items.length < PAGE_SIZE) break;
}

The totalItemCount reported on the first page reflects the index state at query time and can diverge from actual items fetched if documents are added or removed during a paginated sweep.

Search Index Consistency

The search index is eventually consistent. Assets created, moved, renamed, or deleted via the API are durable in the primary store immediately, but may not appear in (or disappear from) paginated search results for several seconds to minutes afterward.

Practical consequences:

  • Verify a newly created folder or asset with a direct lookup (GET /admin/asset/{id} or a targeted url-filter search) rather than a full index sweep — direct lookups hit the primary store and are immediately consistent.
  • A bulk paginated scan taken shortly after a batch-create may silently miss some new items. This is not a bug in the pagination cursor; it is index ingest lag.
  • Deleted assets may continue to appear in search results briefly after deletion (404 on fetch confirms the true state).

Equals Operator on the url Field — Prefix Match, Not Exact

Filtering on { fieldName: "url", operator: "Equals", values: "Content/Photo/Events/" } returns all assets whose URL starts with that string, not just the folder asset itself. This means a url-Equals search for a folder path will also return every file and sub-folder beneath it.

To look up a specific folder by path, navigate the system tree using parentId instead:

// ✗ Returns the folder AND everything inside it
{ fieldName: "url", operator: "Equals", values: "Content/Photo/Events/" }

// ✓ Returns only direct children of a known parent
{ fieldName: "parentId", operator: "Equals", values: "<parent-folder-id>" }

filter_binder — AND vs OR

By default (null or omitted), all filters in a request are AND-combined. Setting filter_binder: 1 switches the combination to OR, so any filter match returns the record. This is intentional for cases like "display name starts with X OR contains X", but applying it accidentally to an assetType filter alongside other filters will return every record that matches any single predicate — often the entire dataset.

// AND (default) — asset must match ALL filters
{ filters: [assetTypeFilter, parentIdFilter] }

// OR — asset matches if it satisfies ANY filter (use deliberately)
{ filters: [prefixFilter, containsFilter], filter_binder: 1 }

Use Search for Bulk Lookups

Rather than fetching records one at a time via GET /admin/content/{defId}/{id}, use a single POST /admin/search call with a filter to retrieve many records at once. This is significantly more efficient for sync operations. See Data Synchronization for the recommended pattern.

Base Routes

APIRoute PrefixDescription
Admin/admin/searchFull search, export, index management
Portal/portal/searchSearch queries, saved searches, search profiles, export

Searching

Full Search (POST)

POST /admin/search
POST /portal/search
Request body: SearchModel { searchQuery, filters, sortFields, pageSize, pageOffset, ... }
Query: ?includeInternalFieldsInResults=false
Response: ListResultModel<SearchResultModel> { items, totalItemCount }

The POST-based search accepts a full SearchModel in the request body with complete control over filters, sorting, pagination, and field selection.

Simple Search (GET - Admin Only)

GET /admin/search?searchQuery=...&pageSize=...&pageOffset=...&sortField=...&sortOrder=...
Query string parameters override any values in the optional body SearchModel.
Additional query parameters are extracted as filters.
Response: ListResultModel<SearchResultModel>

Get Document by ID

GET /admin/search/{id}
GET /portal/search/{id}
Query: ?includeInternalFieldsInResults=false
Response: SearchResultModel

Retrieves a single document from the search index. In the Portal API, only Asset and Live Channel documents are accessible; other content types return 404.

Exporting

POST /admin/search/export
POST /portal/search/export
Request body: SearchModel
Query: ?background=false
Response: Excel file (XLSX) download, or 204 if no results

Exports search results as an Excel spreadsheet. If no sort fields are specified, results default to sorting by masterId.

When background=true, the export is queued as a batch job and the response returns immediately with 204. The completed file is delivered via email.

Index Management (Admin Only)

Get Field Names

GET /admin/search/mappingFieldNames
Response: string[] (list of indexed field names)

Returns all field names available in the search index schema for use in filters, sorts, and field selection.

Rebuild Index

POST /admin/search/rebuild-index/{type}

Triggers a search index rebuild. Supported types:

TypeDescription
$ALL$Rebuild index from all data sources
$ALL_CLEAR$Clear the index completely, then rebuild from all sources
$MONGO$Rebuild from MongoDB source only
$DYNAMO$Rebuild from DynamoDB source only

Warning: $ALL_CLEAR$ makes search temporarily unavailable during the rebuild.

Saved Searches (Portal)

Saved searches persist search criteria for later re-execution.

EndpointMethodDescription
/portal/savedsearchPOSTCreate a new saved search
/portal/savedsearchGETList all saved searches for the current user
/portal/savedsearch/{id}GETGet a saved search by ID
/portal/savedsearch/{id}PATCHPartially update a saved search (name, sequence, featured, bookmarked)
/portal/savedsearch/{id}PUTFully replace a saved search
/portal/savedsearch/{id}DELETEDelete a saved search

Executing Saved Searches

GET /portal/search-saved/{id}?returnedFieldNames=...
Executes the saved search by ID

POST /portal/search-saved
Request body: SavedSearchModel
Executes an ad-hoc saved search model without persisting changes

Both return ListResultModel<SearchResultModel>.

Search Profiles (Portal)

Search profiles store default search configurations such as filters, display columns, and sort preferences.

EndpointMethodDescription
/portal/searchprofilePOSTCreate a new search profile
/portal/searchprofileGETList all search profiles for the current user
/portal/searchprofile/{id}GETGet a search profile by ID
/portal/searchprofile/{id}PUTReplace a search profile
/portal/searchprofile/{id}DELETEDelete a search profile

Common Error Responses

Status CodeDescription
400Bad Request - Missing or invalid search parameters
401Unauthorized - Missing or invalid Bearer token
404Not Found - Document or saved search not found

Did this page help you?