Search
Socotra's search allows you to find and count records across key entities quickly and easily.
Overview
You can search against locators, entity numbers, static data, and data extensions of type string, along with some designated entity-specific properties, across all entity types or within a single type. Queries can be a simple string or can target specific fields and require or exclude terms, using either fuzzy, "starts with", or exact matching.
Results are ranked by relevance by default, with matches on locators, static data, and entity numbers ranked highest. You can also sort and filter results, return additional field values with each result, and get counts of matching records for each entity type. Which fields are indexed for search is controlled through configuration.
Example
If you have an account configured with a data extension field lastName, and there is at least one account with last name "Swerski" in your set of accounts, a search query for Swerski will return at least one result: the account record for "Swerski", with a high relative score.
Request
POST request body:
{
"searchString": "Swerski"
}Response
{
"searchToken": "eyJzZWFyY2hSZXF1ZXN0Ijp7InNlYXJjaFN0cmluZyI6IlN3ZXJza2kifX0=",
"offset": 0,
"count": 10,
"results": [
{
"score": 2.0,
"searchEntityType": "account",
"searchEntityLocator": "01JSH3DEPHHTRE6SQE8F9JH0J3",
"searchSummary": {
"account_number": "A223455",
"data": {
"firstName": "Bill",
"lastName": "Swerski"
},
"name": "ConsumerAccount",
"state": "validated"
},
"highlights": [
"Score:2.0 ,Document: 01JSH3DEPHHTRE6SQE8F9JH0J3,Highlight: {entity.data.lastName=[<em>Swerski</em>]}"
]
},
{
"score": 0.85714287,
"searchEntityType": "account",
"searchEntityLocator": "01JSH3E88RHZJTTVJNQX9XCAGK",
"searchSummary": {
"account_number": "B229455",
"data": {
"firstName": "Bill",
"lastName": "Swersky"
},
"name": "ConsumerAccount",
"state": "validated"
},
"highlights": [
"Score:0.85714287 ,Document: 01JSH3E88RHZJTTVJNQX9XCAGK,Highlight: {entity.data.lastName=[<em>Swersky</em>]}"
]
}
]
}A similar name, "Swersky", appears in the results, but with lower relevance than the more exact match on "Swerski". An exact match request with "Swerski" wrapped in (escaped) quotes would only return the "Swerski" account. Read on for details about search behavior and search string syntax.
Searchable Fields
The following entities are searchable:
- Policies (via policies, segments, or elements)
- Quotes (via quotes or elements)
- Accounts
- Contacts
- Diaries
- First Notice of Loss ("FNOL")
- Payments
- Tasks
- User Associations
The following fields are searchable across entities:
- Locators - All locators, and static locators where applicable.
- Entity numbers - Entity numbers, for entities that support numbering. See Entity Numbering for details.
- Static data - All static data fields on quotes and policies, regardless of the data type.
- Data extensions - Data extension fields of type
string. You can control which data extensions are indexed through configuration. - System fields - Certain entity-specific system properties, listed below.
| Entity | Additional searchable system properties |
|---|---|
| Policy | product_name, account_locator, start_time, statuses, proxy_payer_locator, segment locator, staticLocator, and type; element locator and type |
| Quote | product_name, account_locator, policy_locator, start_time, element locator and type |
| Account | type, account_state |
| Contact | static_locator, type, region |
| Diary | contents, reference_locator |
| FNOL | type (without the Fnol suffix), account_locator, policy_locator |
| Payment | type, amount, targets (text values only) |
| Task | type, task_state, assigned_to, creation_time, deadline_time, tag, source, labels, reference_type, reference_locator |
| User Association | user_locator, user_association_state, user_association_role, reference_type, reference_locator |
Requests
Requests can be sent as a single searchString or as a searchTerms array. See the API reference for details.
To restrict results to a single entity type, set searchEntityType on the SearchRequest (e.g. account or task). If searchEntityType is not provided, the search runs across all searchable entity types. Each result in the response indicates the type and locator of the matching record in its searchEntityType and searchEntityLocator properties.
Search String Syntax
A search request comprises search terms - an array of searchTerm items - and can be expressed as a searchString. searchString syntax allows you to express a complete query in a single string, such as one passed through a typical search form box.
A search string follows these rules:
-
A sequence one or more
searchTermstrings, separated by whitespace. -
Each
searchTermstring has the following form:-
Form:
[+|-][fieldName:]string[*]-
The
fieldNameslug determines whether the match should be against a specific field name or any field. -
The
fieldNamecan be qualified by the full path of the element to which it belongs, which allows for greater specificity in your query. For example, a top-levellastNamedata extensionstringon an account can be searched like this:+data.lastName:Swerski, while afirstNamedata extension on an exposure "insured" under some product can be searched as+insuredQuote.firstName:Veronica(for quotes) or+insuredPolicy.firstName:Veronica(for policies). -
Term relevance scoring:
- If the term is prefixed with a
+, the term is required for search result relevance. - If the term is prefixed with a
-, the term must be excluded for search result relevance. - Absence of
+or-before a term is interpreted as a suggestion: the presence of the term increases the relevance score, but does not require that the term be present or absent from a match candidate.
- If the term is prefixed with a
-
-
The default match behavior is
fuzzy.- Appending
*to the term sets matching tostartsWith. - Enclosing the term in (escaped) double quotes sets matching to
exact. Searches with spaces cannot be fuzzy searches. - Only
exactmatching is case-sensitive.
- Appending
-
Search Terms
As an alternative to searchString, you can provide each term as a SearchTermRequest in the searchTerms array. Each term sets the same options as the search string syntax, using explicit properties.
| Property | Description | Search string equivalent |
|---|---|---|
searchTerm | The value to match | string |
fieldName | The field to match against | fieldName: |
match | fuzzy (default), exact, startsWith, lessThan, or greaterThan | No suffix (fuzzy), \"...\", *, <, or > |
absolute | required, excluded, or none (default) | +, -, or no prefix |
For example, this search string:
{
"searchString": "+lastName:Swerski firstName:Bil*"
}is equivalent to these search terms:
{
"searchTerms": [
{
"searchTerm": "Swerski",
"fieldName": "lastName",
"match": "fuzzy",
"absolute": "required"
},
{
"searchTerm": "Bil",
"fieldName": "firstName",
"match": "startsWith",
"absolute": "none"
}
]
}Both requests return accounts whose lastName fuzzy matches "Swerski", and will rank accounts whose firstName starts with "Bil" higher.
Entity Numbering
Entity numbers have dedicated indexing to provide improved search performance for these key identifiers. The searchable entities that support numbering at this time are:
- Accounts
- Quotes
- Policies
- FNOLs
- Tasks
To match against a specific entity number using fieldName, the fieldName must be set to entity_number, regardless of the entity type. For example, a policyNumber or quoteNumber can be searched like this: entity_number:A00000-PA-SD.
Entity numbers may contain any number of non-alphanumeric symbols. To make searching for these numbers more flexible, all such symbols are ignored during fuzzy or startsWith searches. This enables users to find entities whether or not symbols are included in their search request. For example, A00000-PA-SD can be searched as A00000-PA-SD, A00000PA-SD, A00000-PASD or A00000PASD.
Relevancy scores are boosted for matches on entity numbers.
POST request body example:
{
"searchString": "entity_number:A00000-PA-SD"
}Filtering
You may restrict results to a creation time range using the optional endCreationTime or startCreationTime SearchRequest parameters.
Sorting
Results may be sorted using the sortField property. This may only be used for system-defined fields already returned in search results for a particular entity.
The order of search results may be controlled using the sortOrder property. To sort ascending, use a value of Asc, and to sort descending, use a value of Desc.
For example:
{
"searchString": "deadline_time:<2026-12-29T19:12:27+0000",
"searchEntityType": "task",
"sortField": "entity.deadline_time",
"sortOrder": "Asc"
}Date Field Operators for Tasks
Time-based operators are supported for a select group of searchable, non-data extension Task entity fields of type DATE. This can be used to answer questions such as "What is the list of tasks that are due within the next 5 days?".
These operators can be used via > and < for searchString and greaterThan and lessThan for searchTerms. The value to be compared against may be in date (2027-12-29) or datetime (2026-12-29T19:09:26Z) format; a value in date format will resolve to midnight.
The following DATE fields are currently supported:
creation_timefor thetaskentitydeadline_timefor thetaskentity
Field types can be retrieved using the Fetch Indexed Fields API. Fields with type DATE are timestamps in the format YYYY-MM-DDT00:00:00Z.
Search matching of exact, fuzzy, and startsWith are not supported for DATE fields.
Note that data extension fields of type date and datetime are not searchable; only entity system fields are supported.
Detailed highlights will not be returned in results using date field operators.
POST request body example using searchTerms:
{
"searchEntityType": "task",
"searchTerms": [
{
"searchTerm": "2026-10-01T12:09:26Z",
"fieldName": "entity.deadline_time",
"match": "greaterThan",
"absolute": "required"
},
{
"searchTerm": "2026-10-02T16:09:26Z",
"fieldName": "entity.deadline_time",
"match": "lessThan",
"absolute": "required"
}
]
}POST request body example using searchString:
{
"searchString": "deadline_time:<2026-12-01",
"searchEntityType": "task"
}Null Values
For the assigned_to field in the task entity, if the value is set to null, search results will display the string value "null".
Responses
The SearchServiceResponse provides a list of SearchResultResponse results, along with properties to assist in paging through results.
You can fetch up to 100 results at a time, and use the count, offset, and searchToken values to control pagination. If no count is set for the initial search request, it will be set to 100. The searchToken should be used in subsequent Fetch Additional Search Results By Token GET requests to page through the results, with count serving as the number of results to be returned in the page and offset as the starting index (beginning at 0) in the result list. For example, if you perform a search with a total of 70 results, and want to page through 25 results at a time, you can do it with three requests, all setting count to 25:
- The initial query
- A second query, along with the
searchTokenandoffsetas25 - A final query , along with the
searchTokenandoffsetas50
You'll know that you have exhausted the result set when the length of the result list is less than count. If there are no results beginning at some offset index, the service will return an empty result list. You can set the count to another value when fetching results; following the example above, if you decided you wanted all the results in a single response, just provide the searchToken with count at least 70. A provided count greater than 100 will be set to 100.
Relevance
The highlights and score properties provide additional context about the match. In highlights you will find one or more excerpts from text that matched the query, while score indicates the relative numerical value assigned for ranking.
You'll see very high score values for certain cases, such as exact matches on locator, static data, or entity number values. Results are ordered by score, from highest to lowest, unless sorting is applied.
Relevance scores are most meaningful for fuzzy match types, where the score reflects how closely a candidate matches the search term.
A result's score is calculated as follows:
- Each matching field for a search term is scored from
0to1.0, where1.0is an exact match. - Result scores are additive across both search terms and fields. When there are multiple search terms, and/or multiple fields match a given term, their scores are summed.
- Matches on locators, entity numbers, and static data are boosted by multiplying each field's score by
100. - Fuzzy searches run two passes, a
fuzzymatch and astartsWithmatch, and sum the scores from both.
Search Term Scoring
Each individual search term in a search request is scored from 0 to 1.0 based on how closely it matches a field value. If the term matches more than one field on an entity, the scores for each field are added together.
For example, an exact search for Garcia against an account with lastName set to "Garcia" and businessName set to "Garcia Landscaping LLC" scores 1.0 for the exact match on lastName, plus a partial score (e.g. 0.8) for businessName, for a total of 1.8.
If multiple search terms are provided in a request, or a single search term is executed as multiple terms due to the presence of symbols, then the scores for each term are added together to the final score provided in the response.
Boosting
Matches on locators, entity numbers, and static data have their scores multiplied by 100. This ensures that these matches typically rank above matches on data extension fields.
For example, an exact search for Riverside against static data with agencyName set to "Riverside" and branchName set to "Riverside Commercial" scores:
agencyName:1.0 x 100 = 100(exact match)branchName:0.75 x 100 = 75(partial match, using an example score of0.75)- Total:
175
Match Type
An exact search runs a single search on the entire term as is. A fuzzy search runs two searches - a fuzzy match and a startsWith match - and sums the scores from both.
For example, a fuzzy search for POL-12345 against a policy whose entity number is exactly "POL-12345" scores 1.0 x 100 (fuzzy) + 1.0 x 100 (startsWith) = 200.
This is also why the "Swerski" account in the example above has a score of 2.0: the exact match on lastName scores 1.0 in each pass. "Swersky" doesn't start with "Swerski", so it only scores in the fuzzy pass.
The greaterThan and lessThan date field operators have no partial scores. A date field scores 1.0 if the comparison is true, and 0 if it is not.
Symbols
In a fuzzy or startsWith search, a term containing non-alphanumeric symbols such as - is split into separate terms. Each term is matched and scored on its own, and the scores are added together. Entity numbers are the exception: when matching against entity numbers, the full term, symbols included, is matched as a single value.
For example, a fuzzy search for ABC-DEF is handled two ways:
- Against entity numbers,
ABC-DEFis matched as one term. An entity number of "ABC-DEF" is an exact match, scoring200(100from each pass, as in thePOL-12345example). - Against any other fields,
ABCandDEFare searched separately. IfABCpartially matches a data extension value of "ABCD" (e.g.0.8) andDEFexactly matches a data extension value of "DEF" (1.0), the result scores1.8for a single pass, with no boost.
Because a score depends on the number of matching terms and fields, the match type, and boosting, scores are meaningful for comparing results within the same search, not as an absolute measure of match quality across different searches. As a rough guide, a score of 100 or more indicates a match on a locator, entity number, or static data.
Search Summary
The searchSummary object serves as a digest about the entity, reducing the need for subsequent data fetches from the API in order to understand which entity is being referred to, or to display the search result in an effective way. The contents of searchSummary depends on the result entity type:
- Quotes and policies will have all static data fields in a
staticproperty. - Quotes will also have a
stateproperty. - All other searchable entities will include all string-type data extension field values in the
dataproperty. - Additional system-defined properties may be returned that are deemed relevant for that particular entity.
"<entity>_number" will also appear as a search summary property if the entity supports numbering, and a number is assigned. The account results shown in this guide include account_number, for example, even though any search request for that number using fieldName must refer to entity_number rather than account_number.
Field Augmentation
You can augment the searchSummary by supplying string values in the fields array of the SearchRequest. Any field (data extension) whose name matches one of the strings in fields will appear as an entry in the searchSummary map, with the full field name and dot-delimited path as the key.
For example, a search request with "fields": ["model", "vin"] could yield a searchSummary with entries like this:
{
// ...,
"searchSummary": {
"entity1.elements1.PersonalVehicleQuote.VIN": "4T1R11AK5MU610710",
"entity1.elements1.PersonalVehicleQuote.model": "Camry",
"entity1.elements2.PersonalVehicleQuote.VIN": "WAUV2AF20KN111732",
"entity1.elements2.PersonalVehicleQuote.model": "A7",
"state": "draft"
}
// ...
}Sample Responses
A SearchResultResponse for a "ConsumerAccount" account (search query was simply "Evans"):
{
"score": 2.0,
"searchEntityType": "account",
"searchEntityLocator": "01JSH42HR5MYXAZQSCR13WNJ5P",
"searchSummary": {
"account_number": "C229458",
"data": {
"firstName": "Bill",
"lastName": "Evans"
},
"name": "ConsumerAccount",
"state": "validated"
},
"highlights": [
"Score:2.0 ,Document: 01JSH42HR5MYXAZQSCR13WNJ5P,Highlight: {entity.data.lastName=[<em>Evans</em>]}"
]
}A SearchResultResponse for an account result when searched by locator using an exact match -- note the high relevancy score, since the search service boosts relevancy for exact matches on locators:
{
"score": 100.0,
"searchEntityType": "account",
"searchEntityLocator": "01JSH42HR5MYXAZQSCR13WNJ5P",
"searchSummary": {
"account_number": "C229458",
"data": {
"firstName": "Bill",
"lastName": "Evans"
},
"name": "ConsumerAccount",
"state": "validated"
},
"highlights": [
"Score:100.0 ,Document: 01JSH42HR5MYXAZQSCR13WNJ5P,Highlight: {entity.locator.keyword=[<em>01JSH42HR5MYXAZQSCR13WNJ5P</em>]}"
]
}Search Stats
The Fetch Search Stats endpoint returns the number of matching records for each entity type, without returning the results themselves. This is useful for showing a summary of matches, such as the number of accounts or policies matching certain criteria, before fetching results for a particular entity type.
The request body is the same SearchRequest used for a regular search. The SearchStatsResponse contains a list of SearchStatsResult results, each with a searchEntityType and a recordCount.
As with a regular search, you can use the searchToken returned by Fetch Search Stats with Fetch Additional Search Results By Token to page through the matching records, as described in Responses.
POST request body example:
{
"searchString": "Swerski"
}Response:
{
"searchToken": "eyJzZWFyY2hSZXF1ZXN0Ijp7InNlYXJjaFN0cmluZyI6IlN3ZXJza2kifX0=",
"results": [
{
"searchEntityType": "account",
"recordCount": 2
}
]
}Configuration
Search is enabled by default. See Searchable Fields for the types of fields that are indexed.
You may use the defaultSearchable and searchable configuration properties to more precisely control which string data extension fields are indexed for search. Static data is always indexed, regardless of configuration or data type. defaultSearchable can be set at several levels of the configuration, listed below. If defaultSearchable is not explicitly provided at the top level of the configuration, it is set to a default value of true. When defaultSearchable is true, all string data extension fields at that level and below are indexed. When defaultSearchable is false, then a string data extension field must have searchable set to true in order to be indexed for search. For a given field, the nearest defaultSearchable value when going up the configuration hierarchy applies.
The list below indicates where within configuration you may define search properties:
- Global/Tenant Configuration (
defaultSearchable) - Entities such as Accounts, Contacts, Payments, Tasks, etc. (
defaultSearchable) - Elements such as Products, Coverages, Exposures, etc. (
defaultSearchable) - Custom Data Types (
defaultSearchable) - Data Extensions (
searchable)
The order of application follows the configuration hierarchy. Given the possibility for inheritance of entities, elements, and custom data types as well as the element hierarchy, search resolution always walks up that field's specific path, checking each level's defaultSearchable value until one is explicitly set.
To optimize search performance, we recommend setting defaultSearchable to false at the top level of the configuration, then explicitly enabling search only for the data extension fields that actually need to be searchable.
Indexed Fields
The search index for a tenant reflects the resolved fields that are actually searchable based on both the configuration and the data that exists. Each entity's index may contain a combination of system fields for that entity (such as locators, entity numbers, static data, and other entity-specific fields) and searchable string data extensions.
While Socotra allows you to create draft entities with fields not specified in the configuration, the search service will only index fields on draft entities that are actually present in the configuration.
The Fetch Indexed Fields API provides visibility into the indexed fields for each entity along with their data types.
The index can differ from the searchable fields defined in your configuration in the following ways:
- Searchable fields that don't yet have data for a given tenant are not included in the index. For example, if no records currently have a value populated for a particular searchable data extension, that field won't appear in the index until a record does.
- Fields that can repeat across records - for example, a searchable field on a custom data type that is used by a repeatable element - are indexed once per occurrence, up to the highest number of occurrences found in any single record. For instance, if a custom data type called
Driverhas a searchable fieldfirstName, a product allows one or more drivers per policy, and the policy with the most drivers has five, the index will include five iterations of that field:driver1.firstName,driver2.firstName, and so on. - If the number of searchable fields in a configuration causes the index's storage limit to be exceeded, some fields may be excluded from the index.
To fetch the list of indexed fields for the account entity, provide the following request to the Fetch Indexed Fields API:
{
"searchEntityType": "account"
}This will return the following response:
[
{
"index": "accounts",
"fields": [
{
"name": "entity.data.address.state",
"type": "TEXT"
},
{
"name": "entity.data.fullName",
"type": "TEXT"
},
{
"name": "entity.entity_number",
"type": "TEXT"
},
{
"name": "entity.locator",
"type": "TEXT"
},
{
"name": "entity.type",
"type": "TEXT"
}
]
}
]You may also pass searchEntityType as unspecified to receive the full index for all indexed entities.
The Fetch Ignored Fields API provides visibility into fields that are not indexed, for any of the following reasons:
- The index exceeds its storage limit because too many searchable fields are defined, so some fields are excluded from the index.
- The field is defined in the configuration as searchable but doesn't yet have any records with data for it.
- The field appears in the data for a draft entity but is not declared in the configuration.
- The field has a data type that isn't supported by the index (for example,
dateordatetimedata extension fields, which are not searchable).