# Saved segments

> The API operations about saved segments, each with its input, its output and an example.

The operations about saved segments. Each one is a `POST` with a JSON object as its body: [Making a request](/docs/api#start) has the rules they share.

## Save a segment

`POST /api/v1/segments.create` · Write

Saves a set of filters under a name for one site. It appears in the Segments menu of the dashboard at once, where anyone who can see the site can apply it. A segment stores filters only, never a date range. The name must be unique on the site, ignoring case (409 taken), and a site holds at most 30 segments (409 limit_reached). Filters that leave nothing to filter by answer 400 invalid. Read the filters in the answer: they are the ones that were saved. Needs a token with the Write permission.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `siteId` | string | required | The site id, from sites.list. |
| `name` | string, 1 to 60 characters | required | The name of the segment, 1 to 60 characters. Unique on the site, ignoring case. |
| `filters` | object | required | The filters to save. An object such as { "country": "us", "path.has": "pricing" }: a plain key means "is", a key ending in .not means "is not" and a key ending in .has means "contains", joined with AND. At least one key, at most 10, of which at most 3 may end in .has. A region or a city needs a country that "is"; without one it is left out. [The filter keys are listed under Filters.](/docs/api#filters) |

### Output

| Field | Type | Present | Description |
| --- | --- | --- | --- |
| `id` | string | always | The segment id. Pass it to segments.update to change the segment. |
| `name` | string | always | The name the segment was saved under. |
| `filters` | object | always | The saved filters, ready to pass as the filters of any report: a plain key means "is", a key ending in .not means "is not" and a key ending in .has means "contains". A filter that stopped working since it was saved (a goal that was renamed, switched off or deleted) is left out. |
| `createdAt` | number | always | When the segment was created, milliseconds since 1970 UTC. |
| `updatedAt` | number | always | When the segment was last changed, milliseconds since 1970 UTC. |

### Example

**curl**

```bash
curl -s -X POST https://clearsaga.com/api/v1/segments.create \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","name":"From search","filters":{"channel":"organic_search"}}'
```

**CLI**

```bash
clearsaga segments create --input '{"siteId":"site_abc123def456","name":"From search","filters":{"channel":"organic_search"}}'
```

**MCP**

```text
Tool: segments_create
Arguments: {"siteId":"site_abc123def456","name":"From search","filters":{"channel":"organic_search"}}
```

Run `clearsaga help segments create` for one flag per field.

## Delete a segment

`POST /api/v1/segments.delete` · Write

Removes a saved segment from one site for good: its name and its filters. It leaves the Segments menu of the dashboard for everyone. This cannot be undone. To change a segment and keep it, call segments.update instead. The id comes from segments.list. A segment holds no numbers of its own, so no report changes. A dashboard link that already carries its filters keeps working, because applying a segment copies the filters into the address. An id the site does not have is not an error: the answer says deleted false and nothing was changed, so sending the same call twice is safe. Needs a token with the Write permission.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `siteId` | string | required | The site id, from sites.list. |
| `id` | string, at least 1 characters | required | The id of the segment to remove, from segments.list. |

### Output

| Field | Type | Present | Description |
| --- | --- | --- | --- |
| `id` | string | always | The id that was sent. |
| `deleted` | boolean | always | true when the saved segment was there and this call removed it. false when the site has no saved segment with that id, because it was removed before or the id is wrong: nothing was changed, and that is not an error. |
| `name` | string \| null | always | The name the segment had, so it is clear what was removed. Null when deleted is false. |

### Example

**curl**

```bash
curl -s -X POST https://clearsaga.com/api/v1/segments.delete \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","id":"SEGMENT_ID"}'
```

**CLI**

```bash
clearsaga segments delete --input '{"siteId":"site_abc123def456","id":"SEGMENT_ID"}'
```

**MCP**

```text
Tool: segments_delete
Arguments: {"siteId":"site_abc123def456","id":"SEGMENT_ID"}
```

Run `clearsaga help segments delete` for one flag per field.

## List saved segments

`POST /api/v1/segments.list` · Read

The saved segments of one site, by name: each a name and a set of filters that people use to slice the dashboard, such as "Paid traffic from Germany". Get the siteId from sites.list first. The whole list comes at once (a site holds at most 30 segments); there is no paging and no range. A segment holds no numbers of its own. To get numbers for one, pass its filters as the filters of a report such as overview.kpis. Keeps working while the workspace is locked.

Needs a token with the Read permission. Keeps answering while the dashboards of the workspace are locked.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `siteId` | string | required | The site id, from sites.list. |

### Output

| Field | Type | Present | Description |
| --- | --- | --- | --- |
| `rows` | array of object | always | The saved segments of the site, by name: id, name, the filters to pass to a report, and createdAt and updatedAt in milliseconds since 1970 UTC. |

### Example

**curl**

```bash
curl -s -X POST https://clearsaga.com/api/v1/segments.list \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456"}'
```

**CLI**

```bash
clearsaga segments list --input '{"siteId":"site_abc123def456"}'
```

**MCP**

```text
Tool: segments_list
Arguments: {"siteId":"site_abc123def456"}
```

Run `clearsaga help segments list` for one flag per field.

## Update a segment

`POST /api/v1/segments.update` · Write

Replaces the name and the filters of a saved segment. Send both in full: a filter that is left out is removed. The id comes from segments.list or segments.create. To rename, send the new name with the filters as segments.list gave them. The name must be unique on the site, ignoring case (409 taken). Filters that leave nothing to filter by answer 400 invalid, and an unknown id answers 404. Sending the same input twice leaves the segment as it is. Needs a token with the Write permission.

### Input

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `siteId` | string | required | The site id, from sites.list. |
| `id` | string, at least 1 characters | required | The id of the segment to change, from segments.list. |
| `name` | string, 1 to 60 characters | required | The new name of the segment, 1 to 60 characters. Unique on the site, ignoring case. Send the current name to keep it. |
| `filters` | object | required | The new filters, replacing the old ones. An object such as { "country": "us", "path.has": "pricing" }: a plain key means "is", a key ending in .not means "is not" and a key ending in .has means "contains", joined with AND. At least one key, at most 10, of which at most 3 may end in .has. A region or a city needs a country that "is"; without one it is left out. [The filter keys are listed under Filters.](/docs/api#filters) |

### Output

| Field | Type | Present | Description |
| --- | --- | --- | --- |
| `id` | string | always | The segment id. Pass it to segments.update to change the segment. |
| `name` | string | always | The name the segment was saved under. |
| `filters` | object | always | The saved filters, ready to pass as the filters of any report: a plain key means "is", a key ending in .not means "is not" and a key ending in .has means "contains". A filter that stopped working since it was saved (a goal that was renamed, switched off or deleted) is left out. |
| `createdAt` | number | always | When the segment was created, milliseconds since 1970 UTC. |
| `updatedAt` | number | always | When the segment was last changed, milliseconds since 1970 UTC. |

### Example

**curl**

```bash
curl -s -X POST https://clearsaga.com/api/v1/segments.update \
  -H "Authorization: Bearer $CLEARSAGA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"siteId":"site_abc123def456","id":"SEGMENT_ID","name":"From search","filters":{"channel":"organic_search"}}'
```

**CLI**

```bash
clearsaga segments update --input '{"siteId":"site_abc123def456","id":"SEGMENT_ID","name":"From search","filters":{"channel":"organic_search"}}'
```

**MCP**

```text
Tool: segments_update
Arguments: {"siteId":"site_abc123def456","id":"SEGMENT_ID","name":"From search","filters":{"channel":"organic_search"}}
```

Run `clearsaga help segments update` for one flag per field.
