Data Search Step

Search and retrieve records from your organization's datasets, with filters, sorting, and optional user selection.

The Data Search step lets you query one or more of your organization's datasets during a workflow. You define what to search for, how results are selected (automatically or by the user), and which fields to display. The selected record is then available for mapping in later steps.

You can also keep every matching record instead of a single one (see Repeating Records), and retrieve files linked to the found records (see File search).

Datasets

A Data Search step contains one or more dataset configurations.

nametyperequireddescription
datasetIdstringyesThe id of the dataset to search, as returned by the Data Set Management endpoints.
setupobjectyesSearch configuration. See Setup below.
resultsobjectyesResults display configuration. See Results below.

Setup

The setup object defines how the dataset is queried and how a result is selected.

nametyperequiredconstraintsdescription
requiredbooleanyesWhether a selection is mandatory for the workflow to continue.
selectionModestringyesAUTOMATIC or MANUALHow results are selected. See Selection modes.
primarySearchCriteriaobjectyesMain search criteria. See Search criteria below.
linkedEntitiesFiltersobjectyesFilters for entities linked to the primary entity in this dataset. See Linked entity filters below. Pass an empty object {} if the dataset has no linked entities or you do not need to filter them.
repeatedRecordsbooleannoWhen true, keeps every matching primary record as Repeating Records instead of a single record. See Repeating Records. Default: false.
maxResultsinteger or nullnoWhole number from 1 to 1000Maximum number of primary records to keep. null means no limit. Only used when repeatedRecords is true.

Selection modes

  • AUTOMATIC: The first matching record is selected without user input.
  • MANUAL: The user chooses from the matching results before the workflow continues.

Search criteria

Search criteria define how results are filtered and sorted.

nametyperequireddescription
sortFieldIdstringyesThe id of the field to sort results by, as returned by the Data Catalog field endpoints.
sortDirectionstringyesASCENDING (A–Z, 0–9) or DESCENDING (Z–A, 9–0).
joinLogicstringyesAND (all filters must match) or OR (any filter can match).
filtersarrayyesFilter conditions. Use an empty array [] to match every record. See Filters below.
fileToEntityConfigsarraynoFiles to retrieve for the records found by these criteria. See File search below.

Linked entity filters

Datasets can include more than one entity — for example, an "Account & Contacts" dataset might have Accounts as the primary entity and Contacts as a linked entity. primarySearchCriteria filters the primary entity. linkedEntitiesFilters lets you apply additional search criteria to each linked entity in the dataset.

linkedEntitiesFilters is a plain object where:

  • Each key is the linkId of a linked entity, as found in the dataset's linkAliases array (returned by GET /v1/activation/dataset/{datasetId}).
  • Each value is a search criteria object with the same structure as primarySearchCriteria — sortFieldId, sortDirection, joinLogic, filters, and optionally fileToEntityConfigs. The fieldId values inside filters must belong to that linked entity, not the primary entity.

Each linked entity also accepts its own Repeating Records settings:

nametyperequiredconstraintsdescription
repeatedRecordsbooleannoWhen true, keeps every matching linked record (for example, every Contact of the selected Account) as Repeating Records. Default: false.
maxResultsinteger or nullnoWhole number from 1 to 1000Maximum number of linked records to keep for each primary record. null means no limit. Only used when repeatedRecords is true.

If the dataset has no linked entities, or you do not need to filter them, pass an empty object: "linkedEntitiesFilters": {}.

Filters

Each filter narrows the search to records that match a specific condition.

nametyperequireddescription
fieldIdstring or nullyesThe id of the field to filter on, as returned by the Data Catalog field endpoints.
operatorstring or nullyesComparison operator. See Operators below.
valuestring or nullyesThe value to filter by. Supports mapping placeholders (e.g. {{Form.email}}).
valueTypestringnoSTATIC or MAPPED. Streamline sets this automatically when the step runs, based on whether value is a literal or a mapped value. Any value you send is replaced.

fieldId, operator, and value accept null so a filter can be saved before it is fully set up. A filter needs all three to narrow the search.

Operators

The available operators depend on the scalar type of the field being filtered. You can check the field's type from the Data Catalog field endpoints.

  • EQUALS: Exact match. Available for all field types.
  • NOT_EQUALS: Not equal to the value. Available for all field types.
  • CONTAINS: Field value contains the string as a substring. Available for text fields only.
  • STARTS_WITH: Field value begins with the string. Available for text fields only.
  • ENDS_WITH: Field value ends with the string. Available for text fields only.
  • GREATER_THAN: Field value is greater than the filter value. Available for number, date, and time fields.
  • GREATER_THAN_OR_EQUALS: Greater than or equal. Available for number, date, and time fields.
  • LESS_THAN: Field value is less than the filter value. Available for number, date, and time fields.
  • LESS_THAN_OR_EQUALS: Less than or equal. Available for number, date, and time fields.

Repeating Records

By default, a Data Search step passes a single record to later steps. Set repeatedRecords to true to keep every matching record instead. The results become Repeating Records that later steps can map as a collection — for example, to write one record per result in a Deliver Data step, or to build an array in an Outbound Webhook body.

You can enable Repeating Records at two levels:

  • Primary entity — setup.repeatedRecords keeps every matching primary record.
  • Linked entity — repeatedRecords inside a linkedEntitiesFilters entry keeps every matching linked record for each primary record.

Use maxResults to cap how many records are kept. maxResults is accepted even when repeatedRecords is false, but it has no effect in that case.

File search

Use fileToEntityConfigs to retrieve files linked to the records the step finds — for example, documents attached to a patient record. You can add file searches to primarySearchCriteria (files linked to the primary entity) or to any linkedEntitiesFilters entry (files linked to that linked entity).

Each enabled file search becomes a file field (array<file>) that later steps can map. The field's id is the config's rowId, and its label is mappingLabel.

nametyperequireddescription
rowIdstringyesA unique identifier you assign to this file search. Later steps use it as the id of the file field.
enabledbooleanyesWhether this file search runs. Disabled file searches are kept in the configuration but produce no field.
mappingLabelstringyesLabel of the file field shown when mapping it in later steps.
searchConfigobjectyesWhich file entity to search and how. See below.

File search configuration

nametyperequireddescription
entityobjectyesThe file entity to search: entityId (the file entity's id) and linkId (the dataset relationship that connects the record to its files). Both are strings.
filtersarrayyesGroups of file filter conditions. Use [] to retrieve all linked files.
sortsarrayyesSort order for the files. Each item has fieldId and direction (ASCENDING or DESCENDING). Use [] for no sorting.
pageSizenumbernoMaximum number of files to retrieve.

Each item in filters combines one or more conditions:

nametyperequireddescription
operatorstringyesAND (all conditions must match) or OR (any condition can match).
conditionsarrayyesConditions on file fields. Each item has fieldId, operator (any value from Operators), and value. All three are required, non-null strings.

Results

The results object controls how matching records are presented.

nametyperequireddescription
showConfirmationPagebooleanyesWhether to display a confirmation page after a record is selected.
tableModestringyesDEFAULT shows all fields; CUSTOM shows only the fields listed in fields.
fieldsarrayyesFields to display in the results table when tableMode is CUSTOM. Always include the array; use [] when tableMode is DEFAULT.
shareNotificationSettingsobjectnoDefault email and SMS content used when a participant shares the session from this step. See Share notifications.

Results fields

nametyperequireddescription
fieldIdstring or nullyesThe id of the field to display, as returned by the Data Catalog field endpoints.
customLabelstringyesDisplay label for the field in the table.

Share notifications

A participant can share the session by email or SMS from the Data Search step — for example, to send the search results page to a colleague. shareNotificationSettings sets the default content of those messages. When the participant provides their own subject, message, or button text, theirs is used instead. Any setting you leave out falls back to Streamline's default.

nametyperequireddescription
emailobjectnoDefaults for shares sent by email.
smsobjectnoDefaults for shares sent by SMS.

The email object accepts:

nametyperequiredconstraintsdescription
subjectstringnoEmail subject line.
messagestringnoEmail body.
buttonTextstringnoLabel of the button that opens the session.
fromNamestringnoSender display name.
replyTostringnoValid email addressReply-to address.
ccarray of stringsnoValid email addressesAccepted, but not currently applied to share emails.
bccarray of stringsnoValid email addressesAccepted, but not currently applied to share emails.

The sms object accepts a single optional message string: the text message body.

📘

If a Data Search step has more than one dataset, only the first dataset's shareNotificationSettings are used.

Examples

Let's start with the simplest valid setup: one dataset, automatic selection, no filters, and all fields shown by default.

{
  "datasets": [
    {
      "datasetId": "ds1b2c3d-e5f6-7890-1234-567890abcdef",
      "setup": {
        "required": true,
        "selectionMode": "AUTOMATIC",
        "primarySearchCriteria": {
          "sortFieldId": "f1b2c3d4-e5f6-7890-1234-567890abcdef",
          "sortDirection": "ASCENDING",
          "joinLogic": "AND",
          "filters": []
        },
        "linkedEntitiesFilters": {}
      },
      "results": {
        "showConfirmationPage": false,
        "tableMode": "DEFAULT",
        "fields": []
      }
    }
  ]
}

Building on that, here's a more complete example with multiple filters (including a mapped value from a previous form step), a linked entity filter, manual selection, a custom results table, and share notification defaults.

{
  "datasets": [
    {
      "datasetId": "ds2b3c4d-e5f6-7890-1234-567890abcdef",
      "setup": {
        "required": true,
        "selectionMode": "MANUAL",
        "primarySearchCriteria": {
          "sortFieldId": "f2b3c4d5-e5f6-7890-1234-567890abcdef",
          "sortDirection": "ASCENDING",
          "joinLogic": "AND",
          "filters": [
            {
              "fieldId": "f3c4d5e6-e5f6-7890-1234-567890abcdef",
              "operator": "EQUALS",
              "value": "{{`Form`.`email`}}"
            },
            {
              "fieldId": "f4d5e6f7-e5f6-7890-1234-567890abcdef",
              "operator": "EQUALS",
              "value": "active"
            },
            {
              "fieldId": "f5e6f7a8-e5f6-7890-1234-567890abcdef",
              "operator": "GREATER_THAN_OR_EQUALS",
              "value": "2024-01-01"
            }
          ]
        },
        "linkedEntitiesFilters": {
          "l1b2c3d4-e5f6-7890-1234-567890abcdef": {
            "sortFieldId": "f6f7a8b9-e5f6-7890-1234-567890abcdef",
            "sortDirection": "DESCENDING",
            "joinLogic": "OR",
            "filters": [
              {
                "fieldId": "f7a8b9c0-e5f6-7890-1234-567890abcdef",
                "operator": "NOT_EQUALS",
                "value": "cancelled"
              },
              {
                "fieldId": "f8b9c0d1-e5f6-7890-1234-567890abcdef",
                "operator": "GREATER_THAN",
                "value": "100"
              }
            ]
          }
        }
      },
      "results": {
        "showConfirmationPage": true,
        "tableMode": "CUSTOM",
        "fields": [
          {
            "fieldId": "f9c0d1e2-e5f6-7890-1234-567890abcdef",
            "customLabel": "Customer ID"
          },
          {
            "fieldId": "f0d1e2f3-e5f6-7890-1234-567890abcdef",
            "customLabel": "First Name"
          },
          {
            "fieldId": "f2b3c4d5-e5f6-7890-1234-567890abcdef",
            "customLabel": "Last Name"
          },
          {
            "fieldId": "f3c4d5e6-e5f6-7890-1234-567890abcdef",
            "customLabel": "Email Address"
          },
          {
            "fieldId": "f4d5e6f7-e5f6-7890-1234-567890abcdef",
            "customLabel": "Phone Number"
          }
        ],
        "shareNotificationSettings": {
          "email": {
            "subject": "Customer lookup results",
            "message": "Please review the customer record found for this request.",
            "buttonText": "Open results",
            "fromName": "Acme Support",
            "replyTo": "[email protected]"
          },
          "sms": {
            "message": "Customer lookup results are ready for review."
          }
        }
      }
    }
  ]
}

The next example finds one Account by name, keeps up to 50 of its Contacts as Repeating Records, and retrieves the five most recent contract files attached to the Account.

{
  "datasets": [
    {
      "datasetId": "ds3c4d5e-e5f6-7890-1234-567890abcdef",
      "setup": {
        "required": true,
        "selectionMode": "AUTOMATIC",
        "primarySearchCriteria": {
          "sortFieldId": "fa1b2c3d-e5f6-7890-1234-567890abcdef",
          "sortDirection": "ASCENDING",
          "joinLogic": "AND",
          "filters": [
            {
              "fieldId": "fa1b2c3d-e5f6-7890-1234-567890abcdef",
              "operator": "EQUALS",
              "value": "{{`Form`.`accountName`}}"
            }
          ],
          "fileToEntityConfigs": [
            {
              "rowId": "account-contracts",
              "enabled": true,
              "mappingLabel": "Account contracts",
              "searchConfig": {
                "entity": {
                  "entityId": "e9f8a7b6-e5f6-7890-1234-567890abcdef",
                  "linkId": "l9f8a7b6-e5f6-7890-1234-567890abcdef"
                },
                "filters": [
                  {
                    "operator": "AND",
                    "conditions": [
                      {
                        "fieldId": "fb2c3d4e-e5f6-7890-1234-567890abcdef",
                        "operator": "CONTAINS",
                        "value": "contract"
                      }
                    ]
                  }
                ],
                "sorts": [
                  {
                    "fieldId": "fc3d4e5f-e5f6-7890-1234-567890abcdef",
                    "direction": "DESCENDING"
                  }
                ],
                "pageSize": 5
              }
            }
          ]
        },
        "linkedEntitiesFilters": {
          "l1b2c3d4-e5f6-7890-1234-567890abcdef": {
            "sortFieldId": "fd4e5f6a-e5f6-7890-1234-567890abcdef",
            "sortDirection": "ASCENDING",
            "joinLogic": "AND",
            "filters": [],
            "repeatedRecords": true,
            "maxResults": 50
          }
        }
      },
      "results": {
        "showConfirmationPage": false,
        "tableMode": "DEFAULT",
        "fields": []
      }
    }
  ]
}

A few things to note:

  • The Account itself is a single record, because setup.repeatedRecords is not set.
  • Only the Contacts linked entity repeats. Later steps can map its fields as a collection.
  • Later steps can map the contract files through the Account contracts file field.

Did this page help you?