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 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). |
| sort | No | Up to three sort keys, applied in priority order (see Sort). |
| page | No | Pagination object containing size and, after the first page, token (see 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:
{ "field": "status", "operator": "IS", "value": "open" }
or a group:
{
"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:
{
"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.
[
{ "field": "priority", "direction": "DESC" },
{ "field": "created_at", "direction": "DESC" }
]
Example request
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.
{
"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
{
"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:
{
"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.