Filter Syntax
Typed field and relationship filters for the configurable record model, with examples for MCP and REST.
CRM lists, saved views, widgets, REST queries, and the query_crm_records MCP tool use the same record query model. Discover the type with discover_record_types and read its stable field and relationship IDs with get_record_model. Every list uses the same query shape, whether the AI workspace setup or a person created it. Messaging tools have separate filters.
Where do filters apply?
A record query identifies one typeId. Its filters test fields on that type; relationships test linked records; relatedFilters follow a declared relationship path. Rules within each array are combined with AND. search finds text across readable searchable fields. The backend applies workspace and record permissions to every query and related path.
How do I filter a list in the app?
Open the list, for example your deals list, and click Filters in its toolbar. Pick a field under Filter by or type its name in Add filter…; linked lists, such as an organizations list, are listed there too. Choose the condition, then the values, and the list updates right away. Active filters appear as chips at the top; remove one with its ×, or remove all with Clear. Ask Mate in the same popover turns a description in your own words into filters. Every list works the same way, and a saved view shows the same records rather than copying them.
What does a filter rule look like, and can I combine rules with OR?
Each field filter has a stable fieldId, an operator, a typed scalar value (or null), and optionally values for set or range operators. For example:
{
"typeId": "00000000-0000-4000-8000-000000000001",
"filters": [
{
"fieldId": "00000000-0000-4000-8000-000000000002",
"operator": "contains",
"value": { "kind": "text", "value": "Acme" }
}
]
}Use in to match any of several values of one field. To express OR across different fields, run separate queries or use an appropriate related-record query; the ordinary filter array is AND-combined. A query accepts up to 50 field rules and 500 characters of search.
Which operators exist?
The record query contract supports 16 field operators. The type and behavior of a field determine which are valid; the backend rejects incompatible combinations.
| Operators | Meaning |
|---|---|
eq, ne | Equal or unequal to one typed value |
contains, startsWith | Case-insensitive text matching; contains also tests whether a date lies inside a range |
gt, gte, lt, lte | Ordered comparison on supported numbers and dates |
in, notIn | Membership in values, at most 100 typed values |
all | Multiple choice fields only: the record holds every option in values |
between | Inclusive date interval supplied as two values |
inLastDays, notInLastDays | Relative window using a positive whole-day count; notInLastDays matches values strictly before that window |
empty, notEmpty | Missing versus present value; value is null |
eq on text is exact; contains and startsWith ignore case. Currency comparisons require a matching currency. Missing, zero, restricted, and calculation-error values are distinct; a restricted result cannot be used to infer hidden inputs through filtering or sorting.
Which date operators exist, for example for the last 7 days?
Date and date-time fields support appropriate ordered comparisons and between. System dates use system:createdAt and system:updatedAt as field IDs. inLastDays and notInLastDays take a decimal scalar without currency, such as {"kind":"decimal","value":"7","currency":null}. inLastDays includes values at or after UTC midnight N days before the query clock; notInLastDays (Older than… in the app) matches values strictly before that cutoff, so notInLastDays 3 plus inLastDays 7 finds values from three to seven days ago. Relative windows use the query clock; stored calculations do not silently change with time.
Which operators work on text fields?
Text, email, phone, and URL fields support the text operators appropriate to their value type. A field that stores multiple values is searched element by element. Search terms treat percent signs and underscores as literal characters, not SQL wildcards.
Which relationship operators exist, for example to find contacts without an organization?
Relationship filters are separate from field filters. Specify relationId, direction (outgoing or incoming), operator (any or none), and recordIds. Set recordIds to null for any accessible linked record, or to explicit IDs to test particular records. A none filter with recordIds: null finds records without an accessible link of that relationship. The relationship definition supplies the endpoint types and cardinality.
How do I filter by a custom field, and which operators work on it?
Use the field's ID from get_record_model, never its editable label. An input, formula, lookup, or rollup field can be filtered when its value type supports the operator and the reader may access the value. Select filters use stable option IDs. A multiple choice field takes in (has any of the options), all (has all of them), notIn (has none of them, including records without a value), empty, and notEmpty; it cannot be sorted. The same rule applies to the fields of every list.
Which field names can I use?
Use stable field IDs from get_record_model. The system keys system:createdAt, system:updatedAt, and system:assignedTo are available where supported. Relationships use their definition IDs in relationships rather than names such as organizationIds. A renamed field, type, or relationship keeps its ID, so saved views and AI queries remain valid.
Inbox lists also expose connectedAccountId, account-specific emailFolder, lastMessageDirection, lastMessageSentAt and lastMessageAt. First call get_messaging_threads without filters (or manage_data_views with action: "config", the Inbox surface and section: "filters"), then copy the exact filterableFields.options[].value for an account or folder. emailFolder accepts in and notIn; each folder reference includes its account. Folder options provide groupKey (account identity) and groupLabel (heading), allowing separate groups even when two accounts have the same display name. lastMessageDirection accepts inbound/outbound with in/notIn and ignores drafts, hidden/deleted messages and system events. lastMessageSentAt applies date filters to that same latest actual message. Combine notInLastDays with value 3 and inLastDays with value 7 on this field for messages three to seven days old; these may be combined with account, folder and direction filters. lastMessageAt filters last activity and includes draft activity. See Inbox filters.
Examples
Contacts linked to a particular organization:
{
"relationships": [{
"relationId": "00000000-0000-4000-8000-000000000003",
"direction": "outgoing",
"operator": "any",
"recordIds": ["00000000-0000-4000-8000-000000000004"]
}]
}Records with no accessible link through that relationship use "operator":"none" and "recordIds":null. For a date field before July 2024, use a typed date value with lt. For a select field, use in and its option IDs in values. Combine these in the same query to require both conditions.
Should I use searchTerm (free-text search) or a filter?
Use search when any readable searchable text field may contain the phrase. The current record query calls this property search; older entity APIs called it searchTerm. Use filters when the exact field or comparison matters. Search and filters are combined with AND. Identity channels can participate in search only for a type with the protected person-identity capability and with the reader's applicable access; they are not ordinary email fields.
Next
- Core concepts: configured fields and relationships.
- MCP tool catalog:
query_crm_recordsand schema discovery. - CRM Records: list filters and saved views.