Socotra
Feature Guide

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.
EntityAdditional searchable system properties
Policyproduct_name, account_locator, start_time, statuses, proxy_payer_locator, segment locator, staticLocator, and type; element locator and type
Quoteproduct_name, account_locator, policy_locator, start_time, element locator and type
Accounttype, account_state
Contactstatic_locator, type, region
Diarycontents, reference_locator
FNOLtype (without the Fnol suffix), account_locator, policy_locator
Paymenttype, amount, targets (text values only)
Tasktype, task_state, assigned_to, creation_time, deadline_time, tag, source, labels, reference_type, reference_locator
User Associationuser_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 searchTerm strings, separated by whitespace.

  • Each searchTerm string has the following form:

    • Form: [+|-][fieldName:]string[*]

      • The fieldName slug determines whether the match should be against a specific field name or any field.

      • The fieldName can 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-level lastName data extension string on an account can be searched like this: +data.lastName:Swerski, while a firstName data 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.
    • The default match behavior is fuzzy.

      • Appending * to the term sets matching to startsWith.
      • Enclosing the term in (escaped) double quotes sets matching to exact. Searches with spaces cannot be fuzzy searches.
      • Only exact matching is case-sensitive.

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.

PropertyDescriptionSearch string equivalent
searchTermThe value to matchstring
fieldNameThe field to match againstfieldName:
matchfuzzy (default), exact, startsWith, lessThan, or greaterThanNo suffix (fuzzy), \"...\", *, <, or >
absoluterequired, 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_time for the task entity
  • deadline_time for the task entity

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:

  1. The initial query
  2. A second query, along with the searchToken and offset as 25
  3. A final query , along with the searchToken and offset as 50

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 0 to 1.0, where 1.0 is 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 fuzzy match and a startsWith match, 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 of 0.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-DEF is matched as one term. An entity number of "ABC-DEF" is an exact match, scoring 200 (100 from each pass, as in the POL-12345 example).
  • Against any other fields, ABC and DEF are searched separately. If ABC partially matches a data extension value of "ABCD" (e.g. 0.8) and DEF exactly matches a data extension value of "DEF" (1.0), the result scores 1.8 for 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 static property.
  • Quotes will also have a state property.
  • All other searchable entities will include all string-type data extension field values in the data property.
  • 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 Driver has a searchable field firstName, 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, date or datetime data extension fields, which are not searchable).

See Also

On this page