Case list queries

The Action Management public API provides the ability to query for a filtered, sorted, and paginated list of Action Management cases. This is accomplished with the case query POST endpoint.

A basic example

The simplest case list query involves a POST request to the query endpoint for a hub.

Request
POST  https://<host>/v1/actionmanagement/hubs/6435/cases/query
Accept: application/json
Authorization: Bearer <access_token>

The above example requests a page of cases with default criteria. This returns the top 20 cases on a hub, sorted by date created in descending order. Below is the basic structure of the response.

Response
{
    "itemType" : "CaseListItem",
    "itemCount" : 20,
    "totalCount" : 154,
    "items" : [...]
}

In the above example, 20 cases have been returned from a total of 154 available. The items collection contains one CaseListItem object per case. See Definitions for more info on this data type.

The request can be modified by adding a request object in the body of the POST. Below is the basic structure of the request object.

Example 1
{
    "filters" : [],
    "include" : [],
    "orderBy" : {
        "property" : "dateDue"
    },
    "orderByAscending" : false,
    "top" : 50,
    "skip" : 0
}

The above example requests the top 50 cases on the hub, with no filters, including all case properties, sorted by the value of dateDue in descending order.

For filters and include, an empty collection produces the same result as leaving the property blank/null.

Pagination

The case list is paginated using a typical top/skip pattern. The top property of the request specifies how many cases to return. The skip property specifies how many cases to skip over.

The maximum value for top is 100. A value higher than 100 will result in a response of 400 (Bad Request) from the API.

In this example, we have a hub with 154 cases and we want to get 50 cases at a time, sorted by case ID ascending.

Example 2a
{
    "filters" : [],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

This request will return the first 50 cases. To get the next 50 cases, we increase skip to 50.

Example 2b
{
    "filters" : [],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 50
}

To get all available cases, we continue incrementing skip by 50 with each request. If we increase skip beyond the total case count of 154, the query will return zero cases.

Using this system, it is possible to get a large number of cases by breaking the result set up into many pages. You can obtain the total number of pages by dividing the value of totalCount in the response by the value of top. Alternately, you can simply increment skip by a preset amount each time, and stop querying when the number of cases returned is less than the value of top.

Filtering

The case list query can be filtered by one or more criteria, as specified in the filters collection on the request. Each filter is defined by a single instance of the CaseListQueryFilter type. See Definitions for more info on this data type.

Below is a basic example of a query that filters the list to only include cases with a workflowId of 8147.

Example 3
{
    "filters" : [ {
        "property" : "workflowId",
        "type" : "equal",
        "value" : 8147
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 150
}

The next example adds a date range filter to further limit the results to cases created in May 2021.

Example 4
{
    "filters" : [ {
        "property" : "workflowId",
        "type" : "equal",
        "value" : 8147
    },
    {
        "property" : "dateCreated",
        "type" : "range",
        "value" : {
            "min" : "2021-05-01T00:00:00",
            "max" : "2021-05-31T23:59:59"
        }
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
Filters are combined via logical and, meaning only the cases that satisfy the requirements of all filters will be returned.
A query that contains a large number of filters may take too long to process, resulting in a 408 (Timeout) response from the API. If this happens, remove one or more filters, or reduce the page size.

Filter types

Action Management case list query supports the following filter types, specified in the type property on the filter.

  • equal: case property value must be an exact match with the value on the filter

  • notEqual: case property value must not match the value on the filter

  • null: case property value must be null or empty (only valid for nullable/optional properties)

  • notNull: case property value must not be null or empty (only valid for nullable/optional properties)

  • in: case property value must match one of the values in a collection

  • range: case property value must fall within a range of values (only valid for date properties). See Date range filters

  • search: some or all of the case property value must match the filter value (only valid for string properties)

  • category: special filter for case category, includes category and subcategory values (only valid for the category list). See Category filters

If performance is a concern, avoid using in and search filters on string properties wherever possible.

Case properties that can be filtered

The following list contains all case properties that can be the subject of a filter, as defined on the property of the filter definition. The filter types available for the property are also listed.

  • id (equal, notEqual, in)

  • name (equal, notEqual, in, search)

  • workflowId (equal, notEqual, in)

  • cost (equal, notEqual, null, notNull, in)

  • triggerId (equal, notEqual, in)

  • dateDue (equal, notEqual, null, notNull, range)

  • dateCreated (equal, notEqual, range)

  • dateModified (equal, notEqual, range)

  • listItems.itemId (equal, notEqual, in)

  • roles.users.id (equal, notEqual, in)

  • dataFields.value (equal, notEqual, null, notNull, in, search)

  • source.responseId (equal, notEqual, null, notNull, in)

  • source.surveyId (equal, notEqual, null, notNull, in)

Filter values

For most filters, the value must correspond to the expected data type of the selected property. e.g if filtering on workflowId, the expected value is an integer. There are a few notable exceptions to this rule.

  • in filters expect the value to be a collection of valid property values

  • range filters expect an object with min and max properties matching the property’s data type. For more on this, see Date range filters.

  • category filters expect an object with categoryIds and subCategoryIds properties. For more on this, see Category filters

  • No value is required for null or notNull filters

Filtering on collection properties

There are three collection properties on a case which can be the subject of a filter: listItems, roles, and dataFields. It is possible to define a filter that targets a specific item in the collection using the propertyId on a filter definition.

The following example applies a search filter on the dataFields.value collection. This filter will be applied to the data fields as a whole, and will result in a postive match if any data field on the case is at least a partial match for the filter value.

Example 4
{
    "filters" : [ {
        "property" : "dataFields.value",
        "type" : "search",
        "value" : "customer service"
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

In practice, this filter may not be very useful since it’s not specific enough. In most situations we are only looking for a value in a small subset of data fields. To narrow this filter down further, add propertyId to the definition.

The next example targets the filter on a specific data field (id 3697) using propertyId.

Example 5
{
    "filters" : [ {
        "property" : "dataFields.value",
        "propertyId" : 3697,
        "type" : "search",
        "value" : "customer service"
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

The response will only contain cases where data field 3697 has at least a partial match with "customer service". No other data fields will be evaluated.

The same principle can be applied to roles or list items. The following example searches for a collection of list items on a specific list, and a user ID on a specific user role.

Example 6
{
    "filters" : [ {
        "property" : "listItems.itemId",
        "propertyId" : 2878,
        "type" : "in",
        "value" : [ 10201, 10202, 10206 ]
    },
    {
        "property" : "roles.users.id",
        "propertyId" : 9033,
        "type" : "equal",
        "value" : 301
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

Date range filters

The range filter type can be used on date properties to select values that fall within a defined range. The value of a range filter is an object with a min and max property. The value on the case must be equal to or greater than min, and equal to or less than max.

The following example filters dateDue with a three-day range, starting on July 15, 2021.

Example 7
{
    "filters" : [ {
        "property" : "dateDue",
        "type" : "range",
        "value" : {
            "min" : "2021-07-15T00:00:00",
            "max" : "2021-07-18T23:59:59"
        }
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
All Action Management date/time values are UTC (00:00).

Either of min or max can be excluded to perform an open-ended filter. The next example will return all cases created after August 25, 2021.

Example 8
{
    "filters" : [ {
        "property" : "dateCreated",
        "type" : "range",
        "value" : {
            "min" : "2021-08-25T00:00:00"
        }
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
A min value greater than the max value will result in a 400 (Invalid Request) response.

Category filters

An Action Management case can have a category and a subcategory selected. The category filter type enables filitering on category, or a combination of category and subcategory. This filter requires a special object type for the filter value, which has categoryIds and subCategoryIds collection properties.

The following example filters on a single category and a collection of three subcategories.

Example 9
{
    "filters" : [ {
        "property" : "listItems.itemId",
        "propertyId" : 8621,
        "type" : "category",
        "value" : {
            "categoryIds" : [ 10601 ],
            "subCategoryIds" : [ 12001, 12002, 12077 ]
        }
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

Filtering on a category ID with no subcategory ID will include all cases that have the category or any of its subcategories selected. The next example will include all cases that have one of two categories, or any of their subcategories.

Example 10
{
    "filters" : [ {
        "property" : "listItems.itemId",
        "propertyId" : 8621,
        "type" : "category",
        "value" : {
            "categoryIds" : [ 10601, 10603 ]
        }
    } ],
    "include" : [],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
The category filter type is only valid for the listItems.itemId property, and the propertyId must match the list ID of the category list. To find the correct propertyId value, call the GET Lists endpoint. See Overview for details.

Including and excluding case properties

By default, the response will include cases with all available properties returned. If only a small subset of properties are required, they can be specified in the include collection on the request.

The following example is a query whose response will only contain the case ID, name, and created date on the cases.

Example 11 query
{
    "filters" : [],
    "include" : [
    {
        "property" : "name"
    },
    {
        "property" : "dateCreated"
    } ],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
Example 11 response
{
    "itemType" : "CaseListItem",
    "itemCount" : 3,
    "totalCount" : 3,
    "items" : [ {
        "id" : 2009942,
        "name" : "first case",
        "dateCreated" : "2021-07-03T12:00:00-00:00",
        "links" : {
            "self" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009942",
            "notes" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009942/notes"
        }
    },
    {
        "id" : 2009943,
        "name" : "second case",
        "dateCreated" : "2021-07-03T13:00:00-00:00",
        "links" : {
            "self" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009943",
            "notes" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009943/notes"
        }
    },
    {
        "id" : 2009944,
        "name" : "third case",
        "dateCreated" : "2021-07-03T14:00:00-00:00",
        "links" : {
            "self" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009944",
            "notes" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009944/notes"
        }
    } ]
}
The id and links properties are always returned, even if not in the include list.

Including specific lists, roles, and data fields

As with filtering, it’s possible to include specific items inside collection properties using propertyId. This applies to listItems, roles, and dataFields.

It is not possible to include/exclude specific properties on the items in the listItems, roles, and dataFields collections. The entire item must be included or excluded as a whole.

The following example query will produce results with the category (list item 2587) and data field 6644 values only.

Example 12 query
{
    "filters" : [],
    "include" : [
    {
        "property" : "listItems",
        "propertyId" : 2587,
    },
    {
        "property" : "dataFields",
        "propertyId" : 6644
    } ],
    "orderBy" : {
        "property" : "id"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}
Example 12 response
{
    "itemType" : "CaseListItem",
    "itemCount" : 1,
    "totalCount" : 1,
    "items" : [ {
        "id" : 2009942,
        "listItems" : [ {
            "listId" : 2587,
            "id" : 10021,
            "name" : "Men's Shoes",
            "type" : "category",
            "subCategoryId" : 20074,
            "subCategoryName" : "Sneakers"
        } ],
        "dataFields" : [ {
            "id" : 6644,
            "caseId" : 2009942,
            "name" : "Overall satisfaction",
            "value" : "5",
            "questionName" : "q3"
        } ],
        "links" : {
            "self" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009942",
            "notes" : "http://<host>/v1/actionmanagement/hubs/96/cases/2009942/notes"
        }
    } ]
}

Sorting

The case list can be sorted using one of the case properties, and can be sorted in ascending or descending order. This is accomplished with the orderBy and orderByAscending properties on the request.

If not specified in the query, the default sort order is by dateCreated descending.

The following example query requests a case list sorted by trigger name in ascending order.

Example 13
{
    "filters" : [],
    "include" : [],
    "orderBy" : {
        "property" : "triggerName"
    },
    "orderByAscending" : true,
    "top" : 50,
    "skip" : 0
}

Any numeric, string, or date property can be used as a sort key.

To sort on a value in a collection property (listItems, roles, dataFields), the specific item’s ID must be specified with propertyId. The following example sorts the list by the value of a specific data field, in descending order.

Example 14
{
    "filters" : [],
    "include" : [],
    "orderBy" : {
        "property" : "dataFields.value",
        "propertyId" : 9205
    },
    "orderByAscending" : false,
    "top" : 50,
    "skip" : 0
}
Collection properties can only be used in orderBy if a propertyId is included, otherwise the API won’t know which item in the collection to use as a sort key.

Error responses

If a case list query is un-parseable, or does not conform to specifications, the API will respond with 400 (Bad Request).

Filter errors

Common errors found on filters:

  • property does not correspond to a real case property

  • specified property is on the case but not available for filtering (e.g. isClosed)

  • propertyId does not match any known IDs for items in the collection

  • filter type is not valid for the selected property (e.g. search type for the dateCreated property)

  • filter value is invalid for the selected filter type (e.g. a single string value for the in filter type)

Include errors

Common errors found on include:

  • property does not correspond to a real case property

  • propertyId does not match any known IDs for items in the collection

Sort errors

Common errors found on orderBy:

  • property does not correspond to a real case property

  • propertyId does not match any known IDs for items in the collection

  • specified property is on the case but not available for sorting (e.g. isClosed)