---
title: Search
url: https://www.tines.com/stories/docs/api/cases/search/
updated: 2026-10-12T10:57:43+00:00
description: Search and filter the cases visible to the calling token. Search supports composable filters, multi-key sorting, and cursor pagination.
---

*[tines.com](https://www.tines.com/llms.txt) › [Docs](https://www.tines.com/stories/docs/llms.txt) › [Tines API](https://www.tines.com/stories/docs/api/llms.txt) › [Cases](https://www.tines.com/llm/stories/docs/api/cases.md)*

# Search

*[View on tines.com](https://www.tines.com/stories/docs/api/cases/search/)*

## Description

Search and filter the cases visible to the calling token. Search supports composable filters, multi-key sorting, and cursor pagination.

**Note:** This endpoint is currently available only on Tines Cloud. It is not yet available for self-hosted deployments.

Use the [Get Cases API](/api/cases/get) to retrieve the full contents of an individual case.

## Request

HTTP Method: **POST**

URL: `https://<tenant-domain>/api/v3/cases/search`

The request body is a JSON object with the following fields. An empty object returns every case visible to the calling token.

| Body parameter | Required | Description                                                                                                              |
| -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| filter         | No       | A filter condition, group, or nested filter that narrows the returned cases (see [Filters](#filters)).                   |
| sort           | No       | Up to three sort keys, applied in priority order (see [Sort](#sort)).                                                    |
| page           | No       | Pagination object containing `size` and, after the first page, `token` (see [Pagination](#pagination)).                  |
| include_total  | No       | When `true`, include the total number of matching cases in the response. Defaults to `false`.                            |
| timezone       | No       | IANA time zone name, such as `America/New_York`, used to resolve relative and time-of-day date filters. Defaults to UTC. |

Unknown body parameters return a `400` instead of being ignored.

### Filters

The `filter` can be a single condition:

```json
{ "field": "status", "operator": "IS", "value": "open" }
```

or a group:

```json
{
  "op": "AND",
  "nodes": [
    { "field": "status", "operator": "IS", "value": "open" },
    {
      "field": "priority",
      "operator": "IS_ANY_OF",
      "value": ["high", "critical"]
    }
  ]
}
```

Groups support `AND`, `OR`, and `NOT`. `NOT` takes exactly one child. Groups may nest up to four levels deep, and a filter may contain up to 50 nodes.

Each condition contains:

| Key      | Required | Description                                                                                                                                                       |
| -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| field    | Yes      | A field from the tables below.                                                                                                                                    |
| operator | Yes      | An operator supported by that field. Operator names are case-insensitive.                                                                                         |
| value    | Depends  | The value to match. Use an array for `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`, and `BETWEEN`. Omit for `IS_EMPTY` and `IS_NOT_EMPTY`.                               |
| key      | Depends  | Identifies a metadata or case field. Required for `case_field`. For `metadata`, provide either `key` or `value`; omit `key` to search across all metadata values. |

#### Case fields

| Field               | Accepted value                                                                                                                             | Operators                                                                                                                            |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| search              | Free text searched across case names, descriptions, comments, notes, fields, metadata, and numeric case IDs.                               | `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE`                                                         |
| name                | Case name.                                                                                                                                 | `CONTAINS`, `NOT_CONTAINS`, `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE`, `STARTS_WITH`, `ENDS_WITH` |
| description         | Case description.                                                                                                                          | `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE`                                                         |
| status              | `open` or `closed` (case-insensitive).                                                                                                     | `IS`, `IS_NOT`                                                                                                                       |
| sub_status          | Sub-status ID, name, or slug.                                                                                                              | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_NONE_OF`                                                                                            |
| priority            | `critical`, `high`, `medium`, `low`, or `info` (case-insensitive).                                                                         | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_NONE_OF`                                                                                            |
| case_id             | Public case ID.                                                                                                                            | `IS`, `IS_NOT`, `IS_ANY_OF`                                                                                                          |
| team                | Team ID.                                                                                                                                   | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_NONE_OF`                                                                                            |
| created_at          | ISO 8601 timestamp, or a duration for `IN_THE_LAST`.                                                                                       | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                              |
| updated_at          | ISO 8601 timestamp, or a duration for `IN_THE_LAST`.                                                                                       | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                              |
| opened_at           | ISO 8601 timestamp, or a duration for `IN_THE_LAST`.                                                                                       | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                              |
| resolved_at         | ISO 8601 timestamp, or a duration for `IN_THE_LAST`.                                                                                       | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                              |
| tag                 | Tag ID or exact tag name.                                                                                                                  | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`                                                                               |
| assignee            | User ID, exact email address, or `@me`.                                                                                                    | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                   |
| subscriber          | User ID, exact email address, or `@me`.                                                                                                    | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`                                                                               |
| author              | User ID, exact email address, `@me`, or `@tines`. `@tines` matches cases without an identifiable user author.                              | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_NONE_OF`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                                |
| recorded_sla_status | `initial`, `warning`, or `exceeded` (case-insensitive).                                                                                    | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`                                                                               |
| applicable_sla_type | `resolution` or `response` (case-insensitive).                                                                                             | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_ALL_OF`, `IS_NONE_OF`                                                                               |
| sla                 | SLA status. Set `key` to `resolution` or `response`, or omit it to match either type. `key` is required for `IS_EMPTY` and `IS_NOT_EMPTY`. | `IS`, `IS_NOT`, `IS_ANY_OF`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                                              |
| metadata            | Metadata value. Optionally set `key` to a metadata key. Exact matching is case-insensitive.                                                | `IS`, `IS_EMPTY`, `IS_NOT_EMPTY`                                                                                                     |
| case_field          | Case field value, with the field ID or slug in `key`. Date operators require a timestamp case field.                                       | `IS`, `IS_NOT`, `IS_ANY_OF`, `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`                                 |

`BETWEEN` takes an array of two ISO 8601 timestamps. `IN_THE_LAST` takes a duration such as `30m`, `24h`, `7d`, `4w`, `6M`, or `1y`.

#### Collection fields

Collection conditions can use the prefixed fields below. A condition matches when any entry in the collection satisfies it.

| Field              | Accepted value                                     | Operators                                                                    |
| ------------------ | -------------------------------------------------- | ---------------------------------------------------------------------------- |
| comment.text       | Comment text.                                      | `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE` |
| comment.author     | User ID, exact email address, or `@me`.            | `IS`, `IS_NOT`, `IS_ANY_OF`                                                  |
| comment.created_at | ISO 8601 timestamp, or duration for `IN_THE_LAST`. | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`      |
| note.text          | Note text.                                         | `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE` |
| note.created_at    | ISO 8601 timestamp, or duration for `IN_THE_LAST`. | `BEFORE`, `AFTER`, `BETWEEN`, `IN_THE_LAST`, `IS_EMPTY`, `IS_NOT_EMPTY`      |
| record.value       | Linked record field value (case-insensitive).      | `IS`                                                                         |
| task.text          | Task text.                                         | `CONTAINS_ALL`, `NOT_CONTAINS_ALL`, `CONTAINS_PHRASE`, `NOT_CONTAINS_PHRASE` |
| task.completed     | `true` or `false`.                                 | `IS`, `IS_NOT`                                                               |
| task.assignee      | User ID, exact email address, or `@me`.            | `IS`, `IS_NOT`, `IS_ANY_OF`                                                  |

Separate collection conditions can match different entries. To require multiple conditions to match the same entry, use a `NESTED` filter. Its `path` is `comment`, `note`, `record`, or `task`, and fields inside its `filter` omit the path prefix:

```json
{
  "op": "NESTED",
  "path": "task",
  "filter": {
    "op": "AND",
    "nodes": [
      { "field": "assignee", "operator": "IS", "value": "analyst@example.com" },
      { "field": "completed", "operator": "IS", "value": false }
    ]
  }
}
```

### Sort

The optional `sort` array applies up to three keys in order. Each key contains a `field` and a case-insensitive `direction` of `ASC` or `DESC`.

The sortable fields are `priority`, `created_at`, `updated_at`, `opened_at`, and `resolved_at`. The API adds the case ID as a stable final tiebreaker. When `sort` is omitted, cases are ordered by case ID in ascending order.

```json
[
  { "field": "priority", "direction": "DESC" },
  { "field": "created_at", "direction": "DESC" }
]
```

### Example request

```bash
curl --proto '=https' --tlsv1.2 \
  -X POST \
  "https://<tenant-domain>/api/v3/cases/search" \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer <<CREDENTIAL.tines_api_key>>' \
  -d '{
    "filter": {
      "op": "AND",
      "nodes": [
        { "field": "status", "operator": "IS", "value": "open" },
        { "field": "priority", "operator": "IS_ANY_OF", "value": ["high", "critical"] }
      ]
    },
    "sort": [
      { "field": "updated_at", "direction": "DESC" }
    ],
    "page": { "size": 20 },
    "include_total": true
  }'
```

### Pagination

Search uses cursor pagination. Set `page.size` to a value from 1 to 50; it defaults to 20. When more results exist, the response includes `next_page_token`. Pass that value as `page.token` with the same `filter` and `sort` to retrieve the next page. The token is opaque and must not be modified.

```json
{
  "filter": {
    "op": "AND",
    "nodes": [
      { "field": "status", "operator": "IS", "value": "open" },
      {
        "field": "priority",
        "operator": "IS_ANY_OF",
        "value": ["high", "critical"]
      }
    ]
  },
  "sort": [{ "field": "updated_at", "direction": "DESC" }],
  "page": {
    "size": 20,
    "token": "<<next_page_token>>"
  }
}
```

## Response

A successful request returns a JSON object containing a `cases` array. `next_page_token` is present only when another page exists, and `total` is present only when `include_total` is `true`.

### Field description

| Field           | Description                                                                  |
| --------------- | ---------------------------------------------------------------------------- |
| cases           | Array of matching cases visible to the calling token.                        |
| next_page_token | Opaque forward cursor. Present only when another page exists.                |
| total           | Total number of matching cases. Present only when `include_total` is `true`. |

Each object in `cases` contains:

| Field       | Description                                                     |
| ----------- | --------------------------------------------------------------- |
| case_id     | Public case ID.                                                 |
| name        | Case name.                                                      |
| description | Case description, truncated to 1,000 characters. May be `null`. |
| status      | `OPEN` or `CLOSED`.                                             |
| sub_status  | `{ id, name }`, or `null` when the case has no sub-status.      |
| priority    | `CRITICAL`, `HIGH`, `MEDIUM`, `LOW`, or `INFO`.                 |
| url         | URL of the case in Tines.                                       |
| author      | User object, or `null`.                                         |
| opened_by   | User object, or `null`.                                         |
| resolved_by | User object, or `null`.                                         |
| assignees   | Array of user objects.                                          |
| tags        | Array of `{ id, name }` tag objects.                            |
| team        | `{ id, name }`, or `null`.                                      |
| opened_at   | UTC ISO 8601 timestamp, or `null`.                              |
| resolved_at | UTC ISO 8601 timestamp, or `null`.                              |
| created_at  | UTC ISO 8601 timestamp.                                         |
| updated_at  | UTC ISO 8601 timestamp.                                         |

User objects contain `id`, `email`, `first_name`, and `last_name`.

### Sample response

```json
{
  "cases": [
    {
      "case_id": 42,
      "name": "Suspicious login detected",
      "description": "Review the sign-in and confirm whether it was authorized.",
      "status": "OPEN",
      "sub_status": {
        "id": 3,
        "name": "Investigating"
      },
      "priority": "HIGH",
      "url": "https://<tenant-domain>/team/2/cases/42",
      "author": {
        "id": 7,
        "email": "analyst@example.com",
        "first_name": "Alex",
        "last_name": "Morgan"
      },
      "opened_by": null,
      "resolved_by": null,
      "assignees": [
        {
          "id": 7,
          "email": "analyst@example.com",
          "first_name": "Alex",
          "last_name": "Morgan"
        }
      ],
      "tags": [
        {
          "id": 9,
          "name": "login"
        }
      ],
      "team": {
        "id": 2,
        "name": "Security operations"
      },
      "opened_at": "2026-10-09T09:00:00Z",
      "resolved_at": null,
      "created_at": "2026-10-09T08:55:00Z",
      "updated_at": "2026-10-09T09:30:00Z"
    }
  ],
  "total": 1
}
```

## Errors

Errors are returned as a JSON object with an `error` field:

```json
{
  "error": {
    "type": "bad_request",
    "message": "field \"status\" does not support operation \"contains\"",
    "field": "filter.operator",
    "hint": "IS, IS_NOT"
  }
}
```

| Status | Meaning                                                                                                             |
| ------ | ------------------------------------------------------------------------------------------------------------------- |
| 400    | Invalid JSON, unknown parameter or field, unsupported operator, invalid sort, invalid time zone, or invalid cursor. |
| 403    | The tenant does not have access to Cases.                                                                           |

The `error` object includes `type` and `message`. Validation errors can also include a `field` pointer and a `hint` suggesting a correction.
