# Delete search folder by ID

> DELETE /v1/customers/searches/folders/{id} · Settings and configurations API

Source: https://developer.kustomer.com/api/settings-and-configurations/delete-search-folder-by-id

```http
DELETE https://{orgname}.api.kustomerapp.com/v1/customers/searches/folders/{id}
Authorization: Bearer <API key>
```

## Authorization

Requires any one of these roles: `org.permission.search.delete`; or legacy `org.admin.search.write`. The API key or user must hold at least one of them. Legacy roles predate permission sets and still work.

Deletes a searches folder based on the folder ID.

## About Saved searches

A saved search is a named, reusable search query, such as "Open VIP conversations" or "Unassigned email", that appears in the agent desktop's sidebar so agents can open the matching list in one click. Admins arrange saved searches into folders, and each user can pin up to five favorites.

Saved searches are how agents find their work in Kustomer. Each one stores a search query in `data`, in the same format as the [search API](https://developer.kustomer.com/docs/concepts/search): a `queryContext` that sets what it returns (customers, conversations, messages, custom objects and so on), `and`, `or` and `not` criteria, `sort`, and up to 20 `fields` to return. When an agent opens a saved search, Kustomer runs that query live, so the list is always current. Admins create and edit saved searches in the agent desktop or through these endpoints. Saved searches belong to the org rather than to one user, and deleting one removes it for everyone, along with its place in folders and any pins.

#### Who sees a search

`defaultVisibility` sets who sees the search, and `teamVisibilities` and `userVisibilities` (up to 10 entries each, as `{ id, visibility }`) add specific teams or users on top of that default. Each visibility value says where the search appears:

| Value | Shown |
| --- | --- |
| `all` | In the searches list and in autopilot. |
| `search` | In the searches list only. |
| `autopilot` | In autopilot only, the mode that opens a search's results for an agent one after another. |
| `none` | Nowhere, unless a team or user entry grants it. |

Older integrations use `private`, `accessTeams` and `accessUsers` instead. Kustomer keeps both forms in sync, but don't send both forms in the same request, or it fails with `422`. `icon`, `badgeColor` and `showBadge` control how the search looks in the sidebar; with `showBadge`, the sidebar shows a live count of matching results.

#### Folders, order and pins

The sidebar order is one list for the whole org, returned by the positions endpoint as `positions`: items with `type` `search` or `folder`, where a folder has `children` that are searches. Folders can't be nested, and a folder must be empty before you delete it. Create a search inside a folder by sending `folderId`.

Without `filter=all`, the positions endpoint returns only the searches the current user can see, and leaves out folders that would be empty for them.

Pinned searches are personal: each user can pin up to five searches for quick access, and pinning a sixth fails with `400`. Pinning the same search twice fails with `409`, and Kustomer removes a pin if the user loses access to the search.

#### Which endpoint to use

| To | Call |
| --- | --- |
| List the searches the current user can see | [`GET /v1/customers/searches`](https://developer.kustomer.com/api/settings-and-configurations/get-all-searches), with `filter=all` for every search in the org (admins only), or `filter=search` or `filter=autopilot` for one place |
| Create, read, update or delete a saved search | [`POST /v1/customers/searches`](https://developer.kustomer.com/api/settings-and-configurations/create-saved-search), [`GET`](https://developer.kustomer.com/api/settings-and-configurations/get-saved-search-by-id), [`PUT`](https://developer.kustomer.com/api/settings-and-configurations/update-search-by-id), [`DELETE /v1/customers/searches/{id}`](https://developer.kustomer.com/api/settings-and-configurations/delete-search-by-id) |
| See which attributes and operators a query can use | [`GET /v1/customers/searches/schema`](https://developer.kustomer.com/api/settings-and-configurations/get-schema-for-searches) |
| Read or change the sidebar order | [`GET`](https://developer.kustomer.com/api/settings-and-configurations/get-search-positions) or [`PUT /v1/customers/searches/positions`](https://developer.kustomer.com/api/settings-and-configurations/update-search-positions) |
| Create, rename or delete a folder | [`POST /v1/customers/searches/folders`](https://developer.kustomer.com/api/settings-and-configurations/create-search-folder), [`PUT`](https://developer.kustomer.com/api/settings-and-configurations/update-search-folder-by-id), [`DELETE /v1/customers/searches/folders/{id}`](https://developer.kustomer.com/api/settings-and-configurations/delete-search-folder-by-id) |
| List, add or remove the current user's pins | [`GET`](https://developer.kustomer.com/api/settings-and-configurations/get-all-pinned-searches), [`POST /v1/customers/searches/pinned`](https://developer.kustomer.com/api/settings-and-configurations/pin-search), [`DELETE /v1/customers/searches/pinned/{id}`](https://developer.kustomer.com/api/settings-and-configurations/delete-pinned-search-by-id) |

`PUT /v1/customers/searches/positions` only reorders: send the complete tree with every existing search and folder, or the request fails with `400`. Send the `rev` you last read to avoid overwriting someone else's change; if the order changed since then, the request fails with `409 Conflict`, so read it again and retry. Search names must be 3 to 256 characters, and the number of saved searches an org can have depends on its plan.

Related: [Search](https://developer.kustomer.com/docs/concepts/search), [Search recipes](https://developer.kustomer.com/docs/guides/search-recipes), [Teams](https://developer.kustomer.com/api/access-management#teams)

### Recipes

#### 1. Set up a team's searches in their own folder

Give a team a folder of saved searches that only they see, for example when onboarding a new support team.

**Step 1.** [`POST /v1/customers/searches/folders`](https://developer.kustomer.com/api/settings-and-configurations/create-search-folder.md). Create the folder. Folders can't be nested, so this sits at the top level of the sidebar.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v1/customers/searches/folders" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"name": "Billing team"}'
```

```bash title="kusty"
FOLDER_ID=$(kusty api POST /v1/customers/searches/folders --field "name=Billing team" | jq -r '.data.id')
```

**Step 2.** [`POST /v1/customers/searches`](https://developer.kustomer.com/api/settings-and-configurations/create-saved-search.md). Create each search with `folderId` so it lands in the folder. `defaultVisibility: "none"` hides it from everyone else, and the `teamVisibilities` entry shows it to the team in both the searches list and autopilot.

```bash title="cURL"
curl --request POST "https://api.kustomerapp.com/v1/customers/searches" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data "{
    \"name\": \"Urgent open conversations\",
    \"folderId\": \"$FOLDER_ID\",
    \"defaultVisibility\": \"none\",
    \"teamVisibilities\": [{\"id\": \"$TEAM_ID\", \"visibility\": \"all\"}],
    \"data\": {
      \"queryContext\": \"conversation\",
      \"and\": [
        {\"conversation_status\": {\"equals\": \"open\"}},
        {\"conversation_priority\": {\"gte\": 4}}
      ]
    }
  }"
```

```bash title="kusty"
kusty api POST /v1/customers/searches \
  --field "name=Urgent open conversations" \
  --field folderId=$FOLDER_ID \
  --field defaultVisibility=none \
  --field "teamVisibilities:=[{\"id\": \"$TEAM_ID\", \"visibility\": \"all\"}]" \
  --field 'data:={"queryContext": "conversation", "and": [{"conversation_status": {"equals": "open"}}, {"conversation_priority": {"gte": 4}}]}'
```

> Don't add `private`, `accessTeams` or `accessUsers` to the same request; mixing them with the visibility fields fails with `422`. To move an existing search into the folder instead, send `folderId` in a `PUT` to the search.

#### 2. Reorder the sidebar without overwriting someone else's change

Move a saved search to the top of the sidebar safely, even if an admin is rearranging searches at the same time.

**Step 1.** [`GET /v1/customers/searches/positions`](https://developer.kustomer.com/api/settings-and-configurations/get-search-positions.md). Read the whole tree with `filter=all`. Without it you only get the searches the token's user can see, and the update below needs every search and folder in the org. Keep `rev`.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/customers/searches/positions?filter=all" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/customers/searches/positions --query filter=all \
  | jq '.data.attributes | {positions, rev}' > positions.json
```

**Step 2.** Move the item locally. This puts one top-level search first and leaves the rest of the tree, including folder `children`, as it was.

```bash title="kusty"
jq --arg id "$SEARCH_ID" '.positions = ([.positions[] | select(.id == $id)] + [.positions[] | select(.id != $id)])' \
  positions.json > new-positions.json
```

**Step 3.** [`PUT /v1/customers/searches/positions`](https://developer.kustomer.com/api/settings-and-configurations/update-search-positions.md). Send the complete tree back with the `rev` you read. If it fails with `409 Conflict`, someone changed the order in the meantime: read it again and redo the move. A tree that leaves out any search or folder fails with `400`.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/customers/searches/positions" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data @new-positions.json
```

```bash title="kusty"
kusty api PUT /v1/customers/searches/positions --data @new-positions.json
```

#### 3. Change a search's criteria and keep its columns

Update what a saved search matches, such as adding a new channel, without resetting the columns and sort agents already rely on.

**Step 1.** [`GET /v1/customers/searches/{id}`](https://developer.kustomer.com/api/settings-and-configurations/get-saved-search-by-id.md). Read the current criteria.

```bash title="cURL"
curl "https://api.kustomerapp.com/v1/customers/searches/$SEARCH_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```

```bash title="kusty"
kusty api GET /v1/customers/searches/$SEARCH_ID | jq '.data.attributes.data.and'
```

**Step 2.** [`PUT /v1/customers/searches/{id}`](https://developer.kustomer.com/api/settings-and-configurations/update-search-by-id.md). Send only `data.and`. Kustomer updates `data` key by key, so `queryContext`, `fields` and `sort` keep their stored values. Send the full `and` list, though: the list you send replaces the old one.

```bash title="cURL"
curl --request PUT "https://api.kustomerapp.com/v1/customers/searches/$SEARCH_ID" \
  --header "Authorization: Bearer $KUSTOMER_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"data": {"and": [{"conversation_status": {"equals": "open"}}, {"conversation_priority": {"gte": 3}}]}}'
```

```bash title="kusty"
kusty api PUT /v1/customers/searches/$SEARCH_ID \
  --field 'data.and:=[{"conversation_status": {"equals": "open"}}, {"conversation_priority": {"gte": 3}}]'
```

> To take a search out of use for a while, send `deleted: true` instead: it leaves the sidebar and everyone's pins, and `deleted: false` brings it back. `DELETE` removes it for good.

### Example object

A real record from [`GET /v1/customers/searches/{id}`](https://developer.kustomer.com/api/settings-and-configurations/get-saved-search-by-id.md):

```json
{
  "type": "search",
  "id": "5dee4269de8d2e001bf16981",
  "attributes": {
    "name": "Open Conversations",
    "data": {
      "and": [
        {
          "conversation_status": {
            "not_equals": "done"
          }
        }
      ],
      "queryContext": "customer",
      "fields": [
        {
          "key": "activity"
        },
        {
          "key": "customer"
        },
        {
          "key": "lastMessage"
        }
      ]
    },
    "dataHash": "36cd156315f4366533e4c3078a9e91c7",
    "icon": "account-search",
    "badgeColor": null,
    "showBadge": false,
    "position": 1575895657384,
    "createdAt": "2019-12-09T12:47:37.384Z",
    "modifiedAt": "2019-12-09T12:47:37.384Z",
    "updatedAt": "2019-12-09T12:47:37.384Z",
    "defaultVisibility": "none",
    "teamVisibilities": [],
    "userVisibilities": [
      {
        "id": "57504f644c80120f00f3c378",
        "visibility": "all"
      }
    ],
    "private": true,
    "accessTeams": [],
    "accessUsers": [
      "57504f644c80120f00f3c378"
    ],
    "cacheable": true
  },
  "relationships": {
    "org": {
      "links": {
        "self": "/v1/orgs/57504f64d76808100089eb44"
      },
      "data": {
        "type": "org",
        "id": "57504f64d76808100089eb44"
      }
    },
    "createdBy": {
      "links": {
        "self": "/v1/users/57504f644c80120f00f3c378"
      },
      "data": {
        "type": "user",
        "id": "57504f644c80120f00f3c378"
      }
    },
    "modifiedBy": {
      "links": {
        "self": "/v1/users/57504f644c80120f00f3c378"
      },
      "data": {
        "type": "user",
        "id": "57504f644c80120f00f3c378"
      }
    }
  },
  "links": {
    "self": "/v1/customer/searches/5dee4269de8d2e001bf16981"
  }
}
```

Fields:

- `attributes.name` (string): The name shown in the sidebar, 3 to 256 characters.
- `attributes.data` (object): The stored query, in the same format as the [search API](https://developer.kustomer.com/docs/concepts/search). `PUT` updates it key by key, so sending only `data.and` changes the criteria and keeps the stored `fields`, `sort` and `queryContext`.
- `attributes.data.and` (array): Criteria that must all match, each an attribute and an operator such as `{ "conversation_status": { "not_equals": "done" } }`. `or` and `not` take the same form.
- `attributes.data.queryContext` (string): What the search returns, such as `customer`, `conversation`, `message` or `kobject_<klass>`.
- `attributes.data.fields` (array): The columns shown in the results, up to 20, each as `{ key }`.
- `attributes.dataHash` (string): Set by Kustomer from the `data` in the last create or update that included it. Because a `PUT` can send only part of `data`, don't use it to tell whether two searches run the same query.
- `attributes.icon` (string): The name of the icon shown next to the search in the sidebar.
- `attributes.badgeColor` (string): The color of the result-count badge, used when `showBadge` is `true`.
- `attributes.showBadge` (boolean): Whether the sidebar shows a live count of matching results. Turning it on fails with `422` for queries too slow to count or that join several object types.
- `attributes.position` (integer): A legacy sort value that defaults to the creation time in milliseconds. The sidebar order comes from the positions endpoint, not from this field.
- `attributes.defaultVisibility` (string): Where the search appears for users not covered by `teamVisibilities` or `userVisibilities`: `all`, `search`, `autopilot` or `none`.
- `attributes.teamVisibilities` (array): Up to 10 `{ id, visibility }` entries that give specific teams their own visibility on top of `defaultVisibility`.
- `attributes.userVisibilities` (array): Up to 10 `{ id, visibility }` entries that give specific users their own visibility on top of `defaultVisibility`.
- `attributes.private` (boolean): The older visibility form. When `true`, only the teams and users in `accessTeams` and `accessUsers` see the search. Kustomer keeps it in sync with the visibility fields, but don't send both forms in one request.
- `attributes.accessTeams` (array): The older form of `teamVisibilities`, as a list of team IDs that can see a private search.
- `attributes.accessUsers` (array): The older form of `userVisibilities`, as a list of user IDs that can see a private search.
- `attributes.cacheable` (boolean): Set by Kustomer. It's `false` when the query refers to whoever is viewing it, such as criteria on the current user or their teams, so the results differ from user to user.

### Relationships

- Points to **Teams** via `relationships.teamVisibilities` (list): The teams a saved search is shown to, from the `id` of each `teamVisibilities` entry. Each entry's `visibility` says whether the team sees it in the searches list, in autopilot, or both.
- Points to **Users** via `relationships.userVisibilities` (list): The users a saved search is shown to, from the `id` of each `userVisibilities` entry. These entries apply on top of the search's `defaultVisibility`.

### Permissions

Fewest roles for a read-only integration: `org.permission.search.read`, `org.permission.search_pinned.read`. For every endpoint: `org.permission.search.read`, `org.permission.search.update`, `org.permission.search.create`, `org.permission.search.delete`, `org.permission.search_pinned.create`, `org.permission.search_pinned.delete`, `org.permission.search_pinned.read`.

## Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `id` | string | yes | Search folder ID. |

## Responses

### 204

No Content

### 401

Unauthorized

### 403

Forbidden

### 404

Not Found

## Example request

```bash
curl --request DELETE \
  --url 'https://api.kustomerapp.com/v1/customers/searches/folders/6026aba3fcca5f03e5541cd6' \
  --header "Authorization: Bearer $KUSTOMER_API_KEY"
```
