Breadcrumbs

Conversation Search API using GraphQL - User Guide

Overview

The searchConversations query allows clients to:

  • Filter conversations using flexible nested AND/OR logic

  • 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.

  • Endpoint: https://<FQDN>/conversation-manager/graphql

  • Minimal query: Here is a sample query A very small example that simply returns id and creationTime of 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

GraphQL
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

equal_to

Matches values that are exactly equal

not_equal_to

Matches values that are not equal

greater_than

Matches values greater than the input

greater_than_equal_to

Matches values greater than or equal

less_than

Matches values less than the input

less_than_equal_to

Matches values less than or equal

starts_with

Matches strings that start with the value

ends_with

Matches strings that end with the value

contains

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: Either ASC or DESC


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:

  1. UTC with 'Z' suffix: This indicates Coordinated Universal Time.

    • Example: "2025-07-01T00:00:00Z"

  2. 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.key and conversationData.type

  • Avoid using conversationData.value in the filter when its type is STRING_LIST


Example Queries

Filter by customer Id and direction

GraphQL
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

GraphQL
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)

GraphQL
query {
  searchConversations(
    filter: {
      and: [
        { key: "agentParticipants.username", operator: contains, value: "john" }
      ]
    }
  ) {
    docs { 
      id, 
      agentParticipants { 
        username 
      } 
    }
  }
}

Combined filters: creation range + wrapUp + direction

GraphQL
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/OR filters 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 contains on 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/OR operations in the filter.