Overview
The searchConversations query allows clients to:
-
Filter conversations using flexible nested
AND/ORlogic -
Apply pagination to control the number of returned results
-
Sort results by specific fields
-
Select specific fields to minimize payload size
Getting Started
-
Audience: Intended for developers integrating with CX via GraphQL.
-
Minimal query: Here is a sample query A very small example that simply returns
idandcreationTimeof the latest 10 conversations.-
GraphQL
query SearchConversations { searchConversations(sort: { sortBy: "creationTime", sortOrder: DESC }) { docs { id creationTime } limit offset totalDocs } }
-
Default Behavior
If no query parameters are provided, the API will return the top 10 most recent conversations based on creationTime in descending order (latest first).
This default behavior helps:
-
Quickly fetch the latest activity without crafting specific filters
-
Serve lightweight queries for basic use cases like recent history views
Query Structure
query {
searchConversations(
filter: {
or: [
{
and: [
{ key: "customer._id", operator: equal_to, value: "abc123" },
{ key: "conversationDirection", operator: equal_to, value: "INBOUND" }
]
}
]
},
pagination: { limit: 10, offset: 0 },
sort: { sortBy: "creationTime", sortOrder: DESC }
) {
docs {
id
customer {
id
}
creationTime
endTime
}
totalDocs
limit
offset
}
}
Supported Operators
|
Operator |
Description |
|---|---|
|
|
Matches values that are exactly equal |
|
|
Matches values that are not equal |
|
|
Matches values greater than the input |
|
|
Matches values greater than or equal |
|
|
Matches values less than the input |
|
|
Matches values less than or equal |
|
|
Matches strings that start with the value |
|
|
Matches strings that end with the value |
|
|
Matches strings that contain the value |
What is a partial text match?
Partial text matches allow searching within string fields using patterns. For example:
-
starts_with:"Ali"matches"Ali Raza"but not"Raza Ali" -
contains:"Ali"matches"Raza Ali"and"Ali Raza"
Partial text matches (using operators like starts_with, ends_with, and contains) are case insensitive. For example, contains: "alex" will match "Alex", "ALEX", or "alexander" equally.
Allowed Filter Fields
Only the following fields can be used in the filter input:
- id
- creationTime
- endTime
- conversationDirection
- customer._id
- customer.firstName
- agentParticipants.id
- agentParticipants.username
- agentParticipants.teamName
- wrapUps.value
- durationInSeconds
- conversationData.key
- conversationData.type
- conversationData.value
- conversationData.value.formId
- conversationData.value.type
- participants.participant.channel.name
- participants.participant.channel.channelType.name
- participants.participant.channelData.channelCustomerIdentifier
Any attempt to filter using other fields will result in a validation error.
Allowed Search Fields
Only the following fields will be searched upon for the value passed in the searchTerm input:
- customer.firstName
Result Shaping
Pagination
Pagination is applied using the pagination input:
pagination: { limit: 10, offset: 0 }
-
limit: Maximum number of results to return -
offset: Number of results to skip
Sorting
Results can be sorted using the sort input:
sort: { sortBy: "creationTime", sortOrder: DESC }
-
sortBy: Must be one of the allowed filter fields -
sortOrder: EitherASCorDESC
Usage of Timestamps in Filters
Timestamp fields like creationTime and endTime can be filtered using various operators (equal_to, greater_than, less_than, etc.). These fields expect values in ISO 8601 format.
You can specify timestamps in two ways:
-
UTC with 'Z' suffix: This indicates Coordinated Universal Time.
-
Example:
"2025-07-01T00:00:00Z"
-
-
With a timezone offset: This specifies the time and its offset from UTC.
-
Example:
"2025-07-01T05:00:00+05:00"(For PKT, which is UTC+5) -
Example:
"2025-07-01T10:00:00-04:00"(For Eastern Daylight Time, which is UTC-4)
-
Limitations
Filtering on conversationData.value when type is STRING_LIST
If conversationData.type is STRING_LIST, filtering using conversationData.value is not supported. This is due to how the data is stored: the value becomes a list of lists of strings (e.g., [[“a”, “b”]]), which cannot be indexed in MongoDB. As a result, filters on conversationData.value of this type may return incorrect or unexpected results rather than failing outright.
For such cases, you can:
-
Filter using
conversationData.keyandconversationData.type -
Avoid using
conversationData.valuein the filter when its type isSTRING_LIST
Example Queries
Filter by customer Id and direction
query {
searchConversations(
filter: {
and: [
{ key: "customer._id", operator: equal_to, value: "0278c5ad-8d7d-4a9f-a2c3-31d336503c1b" },
{ key: "conversationDirection", operator: equal_to, value: "INBOUND" }
]
},
pagination: { limit: 5, offset: 0 }
) {
docs { id }
totalDocs
}
}
Filter by creation time and end time range
query {
searchConversations(
filter: {
and: [
{ key: "creationTime", operator: greater_than_equal_to, value: "2024-01-01T00:00:00Z" },
{ key: "endTime", operator: less_than_equal_to, value: "2024-01-01T00:59:59Z" }
]
},
sort: { sortBy: "creationTime", sortOrder: ASC },
pagination: { limit: 10, offset: 0 }
) {
docs {
id
creationTime
}
totalDocs
}
}
Search via searchTerm (partial search):
partial search via searchTerm is enabled by default for customer.fistName attribute in CX-4.10.5, CX-5.1 and upcoming releases on top.
query SearchConversations {
searchConversations(searchTerm: "ahsan") {
totalDocs
docs {
customer {
_id
firstName
phoneNumber
isAnonymous
additionalDetail
}
}
limit
offset
}
}
Filter by agent username (partial match)
query {
searchConversations(
filter: {
and: [
{ key: "agentParticipants.username", operator: contains, value: "john" }
]
}
) {
docs {
id,
agentParticipants {
username
}
}
}
}
Combined filters: creation range + wrapUp + direction
query {
searchConversations(
filter: {
and: [
{ key: "creationTime", operator: greater_than_equal_to, value: "2024-04-01T00:00:00Z" },
{ key: "creationTime", operator: less_than_equal_to, value: "2024-04-30T23:59:59Z" },
{ key: "wrapUps.value", operator: equal_to, value: "CLOSED" },
{ key: "conversationDirection", operator: equal_to, value: "OUTBOUND" }
]
}
) {
docs { id, creationTime, wrapUps { value }, conversationDirection }
}
}
Best Practices
-
Use field projections: Only request fields you need to reduce response size.
-
Combine
AND/ORfilters wisely for efficient querying. -
Always refer to the allowed filter fields list when designing queries.
-
Prefer indexed fields (like
creationTime,customer._id) in filters for performance. -
Avoid using
containson high-cardinality fields in very large datasets unless necessary. -
Use narrow time ranges when filtering on timestamps to reduce scan size.
-
Try not to include too many nested
AND/ORoperations in the filter.