---
title: "List Segments"
method: GET
path: "/workspaces/{workspace_id}/segments"
tags: ["Segment"]
---

# List Segments

`GET /workspaces/{workspace_id}/segments`

## Request

- Base URL: `https://myworkspace.myclickfunnels.com/api/v2`
- URL: `https://myworkspace.myclickfunnels.com/api/v2/workspaces/{workspace_id}/segments`
- Auth: one of:
  - HTTP bearer
  - OAuth 2
    - Authorization code: `https://accounts.myclickfunnels.com/oauth/authorize`
    - Token URL: `https://accounts.myclickfunnels.com/oauth/token`
- TypeScript: <https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/docs/workspaces/:workspace_id/segments/get.ts> (a function with typed inputs; its response is checked against the schema)

List the workspace's contact segments, including those created in the UI. Standard cursor pagination, ordered by id ascending. Requires contacts:read.

## Path parameters

- `workspace_id` string, required

## Query parameters

- `after` string
- `sort_order` 'asc' | 'desc'
- `filter` object
  - `name` string: Exact segment name. Separate several names with commas to match any of them; names are not unique, so one name can match several segments.

## Response `200`

Success

- SegmentAttributes[]
  - `id` integer
  - `public_id` string
  - `workspace_id` integer
  - `name` string
  - `filter` RefineFilterAttributes: A reusable workspace-scoped audience filter composed of one or more criteria joined by a single conjunction. Public API requests are validated against a [safe-condition whitelist](https://accounts.myclickfunnels.com/.well-known/refine-filters/skill.md#safe-condition-whitelist); criteria outside the whitelist return 422 with a pointer to the developer community.
    - `id` integer: Refine Filter ID
    - `public_id` string: Obfuscated Refine Filter ID
    - `workspace_id` integer: ID of the workspace this filter belongs to
    - `name` string, nullable: Optional human-readable name for the filter. Must be unique within the workspace when set.
    - `filter_class` string, nullable: The filter class recorded on the saved filter. This API authors `ContactsFilter` and applies `ContactsFilter` and `OrdersFilter`, but the list returns every saved filter in the workspace, and other ClickFunnels surfaces save their own classes here — `ContactsSegmentsFilter`, `ProductsFilter`, `FunnelsFilter` and `ContactUpsellsFilter` all appear in real workspaces. Treat this as an open set: match on the class you want rather than assuming the rest are absent. `null` for a legacy row whose stored state can no longer be decoded (such rows also return empty `criteria`; they can still be deleted).
    - `conjunction` 'and' | 'or': How the criteria are joined — `and` (all must match) or `or` (any must match).
    - `results` FilterResults: The records the filter matches, returned inline so selecting a set and reading it is one call instead of a filter plus a paginated crawl. **Column-oriented.** `fields` states the column order once and `rows` carries bare value arrays. Repeating every key on every record roughly doubles the payload for a projection of a few scalars, which defeats the purpose of asking for a projection. Zip `fields` with each row to reconstruct objects. `truncated` tells you whether `rows` is the whole set. A total `count` is present only when the request opts in with `results.count: true`, because counting a truncated set requires a second evaluation of the filter. Use the workspace stats endpoint when you need only a number. Saved contact and order filters support `results`. Other filter classes return 422 until the API defines an explicit projection allow-list for them. **You set the budget; the response tells you what it cost.** How much a client can absorb is not something this API can know, so `results.max_bytes` and `results.limit` are yours to set and their defaults (3 KB of rows, 500 rows) are only a conservative starting point. Every response reports estimated `bytes`, `bytes_per_record` and the `max_bytes` actually applied, so one call is enough to size every call after it. These estimates are measured before final response encoding, which can be slightly larger for values such as timestamps; leave headroom. When a response is `truncated`, `suggested_max_bytes` is the value to retry with to get the whole set in one call (extrapolated from the widest row RETURNED SO FAR, so it can still undershoot if later records are wider - check `truncated` again on the retry), and `guidance` spells out the alternatives. The only ceiling you cannot raise is the server's own (4 MB of rows per response), which protects the server rather than your context; past it, page with `next_after` or narrow the filter. **`max_bytes` bounds the ROWS, not the whole response.** Over MCP the payload is carried twice (structured plus text mirror) alongside the filter definition, which measured at 2.0x-2.9x the rows on the wire. So when sizing against a client tool-result cap, divide by ~3. The default is already sized that way. `suggested_max_bytes` comes back in the same rows units, so it can be passed straight back.
      - `fields` string[]: The projected field names, in the order the values appear in each row.
      - `rows` array[]: One array of values per matching record, ordered by id. Each value renders the way the resource's own serializer renders that column, so a money field such as `total_amount` arrives as a string at the currency's minor units (`"100.00"`) and can be compared with the same field read from the record endpoint. A `null` means the column has no value for that record.
        - unknown[]
          - unknown
      - `count` integer: Present only when `results.count` was true. Total records the filter matches, independent of the current page. Computed like the workspace stats count: exact, including past the 100,000-record scan cap, unless counting the whole set cannot finish within the time budget, in which case it reports the cap with `count_capped_at`. Counting a truncated result requires a second evaluation of the filter.
      - `count_capped_at` integer: Present only when `count` saturated at the scan cap the server applies and counting the whole set could not finish in time: the real total is HIGHER than `count`, so treat `count` as a floor rather than a total. Narrow the filter to get an exact number. Absent means `count` is exact. Same marker the workspace stats endpoint returns for the same case.
      - `count_unavailable_reason` string: Present only when `results.count` was true but its additional filter evaluation could not complete within the filtered-query time budget. The rows, truncation signal, and continuation cursor are still valid; narrow the filter or use the workspace stats endpoint for the count.
      - `truncated` boolean: True when `rows` is a page rather than the whole set, because the rows reached `limit` or `max_bytes`, or the request reached its filtered-query wall-clock budget.
      - `stop_reason` 'time_budget' | 'row_limit' | 'byte_budget' | 'record_exceeds_budget': Present only when `truncated`: which ceiling stopped us, so you do not have to parse `guidance` to find out. `row_limit` means raise your own `limit`; `byte_budget` means raise `max_bytes` or project fewer fields; `record_exceeds_budget` means a single record is larger than the whole budget, so project fewer fields. `time_budget` is the only one you cannot lift: the request reached its filtered-query wall-clock budget, so page with `next_after` or narrow the filter -- raising `max_bytes` or `limit` will not help, because neither is what stopped it.
      - `bytes` integer: Estimated serialized size of `rows`, measured before final response encoding. Values such as timestamps can make the wire representation slightly larger, so leave headroom.
      - `bytes_per_record` integer: Average estimated bytes per returned record, so you can size a later call for a different record count.
      - `max_bytes` integer: The pre-response row-cost budget applied — your `results.max_bytes` after clamping to the server ceiling, or the default when you didn't set one. It is not an exact wire-size ceiling; leave headroom.
      - `suggested_max_bytes` integer: Present only when `results.count` was true, the response is `truncated`, and the whole set could fit in one response: the `results.max_bytes` to retry with to get all `count` records in a single call. Extrapolated from the widest row returned SO FAR, not the average — so it is an estimate, and a later record wider than anything on this page can still make the retry truncate. Check `truncated` on the retry rather than assuming it is whole. Absent when the set is too large for any single response, when no exact total was requested or known, or when the wall-clock budget stopped the request — then page or narrow instead.
      - `next_after` string: Cursor to continue from, present only when `truncated` is true. Pass it back as `results[after]`. It is the id of the last row actually RETURNED, so paging never skips a record the budget dropped.
      - `guidance` string: Present only when `truncated` is true: what to do about it, cheapest-first — retry with `suggested_max_bytes` to get everything in one call, raise your own `limit`, narrow the filter, project fewer `fields`, page with `next_after` (including how many calls that will take at this size when `count` is available), export the full set as a CSV, or use the workspace stats endpoint if a number is all that was wanted. The export option is only offered when the filtered resource actually has a bulk export and the calling token could create one, so neither an order filter nor a read-only connection is pointed at something that would fail.
    - `criteria` RefineFilterCriterion[]: Ordered list of filter criteria.
      - `attribute` string: The contact attribute to filter on (e.g. `tags.id`, `created_at`, `email_address`). The public API restricts attributes to a [safe whitelist](https://accounts.myclickfunnels.com/.well-known/refine-filters/skill.md#safe-condition-whitelist) — see the [Refine Filters Skill](https://accounts.myclickfunnels.com/.well-known/refine-filters/skill.md) for the full reference.
      - `clause` string: The comparison operator for this criterion (e.g. `in`, `eq`, `gte`, `lte`, `st`, `nst`). Allowed clauses depend on the attribute. Text attributes (`email_address`, `first_name`, `last_name`) only accept `eq` and `sw` on the public API; see the [Refine Filters Skill](https://accounts.myclickfunnels.com/.well-known/refine-filters/skill.md#safe-condition-whitelist).
      - `value` union: The comparison value. Type depends on the attribute and clause: - **Option conditions** (tags, products, etc.): a single opaque public id string, or an array of public id strings. - **Date/datetime conditions**: an ISO 8601 date string (`"2026-01-01"`) or datetime string (`"2026-01-01T00:00:00Z"`). For `between`/`not_between` clauses supply an array of exactly two date strings. For relative `gt`, `lt`, or `exct` clauses supply an object with `days` and a `modifier` of `ago` or `from_now`. - **Text/numeric conditions**: a plain string or number. - **Set/not-set clauses**: omit `value` entirely. `null` when the criterion carries no value, as set/not-set clauses do.
        - string
        - string[]
        - object
          - `days` union: Number of days used by a relative date clause.
            - string
            - integer
          - `modifier` 'ago' | 'from_now'
      - `date_refinement` object: Additional event-date comparison for an attribute that supports date refinement. Preserve this object when reusing a returned criterion; it narrows the audience independently of the selected event IDs.
        - `clause` string: Date comparison operator, such as gte, btwn, or lt.
        - `value` union: ISO8601 date or datetime, two dates for btwn/nbtwn, or days and modifier for relative gt/lt/exct comparisons.
          - string
          - string[]
          - object
            - `days` union
              - …
            - `modifier` 'ago' | 'from_now'
    - `mixed_conjunctions` boolean: True when the saved filter joins its conditions with both `and` and `or`, as filters grouped in the UI can. `conjunction` and `criteria` then summarize it as one conjunction over all criteria rather than restating it; request `results` for its exact matches, and do not rebuild it from `criteria`.
    - `created_at` string, date-time: Created at
    - `updated_at` string, date-time: Updated at
  - `results` FilterResults: The records the filter matches, returned inline so selecting a set and reading it is one call instead of a filter plus a paginated crawl. **Column-oriented.** `fields` states the column order once and `rows` carries bare value arrays. Repeating every key on every record roughly doubles the payload for a projection of a few scalars, which defeats the purpose of asking for a projection. Zip `fields` with each row to reconstruct objects. `truncated` tells you whether `rows` is the whole set. A total `count` is present only when the request opts in with `results.count: true`, because counting a truncated set requires a second evaluation of the filter. Use the workspace stats endpoint when you need only a number. Saved contact and order filters support `results`. Other filter classes return 422 until the API defines an explicit projection allow-list for them. **You set the budget; the response tells you what it cost.** How much a client can absorb is not something this API can know, so `results.max_bytes` and `results.limit` are yours to set and their defaults (3 KB of rows, 500 rows) are only a conservative starting point. Every response reports estimated `bytes`, `bytes_per_record` and the `max_bytes` actually applied, so one call is enough to size every call after it. These estimates are measured before final response encoding, which can be slightly larger for values such as timestamps; leave headroom. When a response is `truncated`, `suggested_max_bytes` is the value to retry with to get the whole set in one call (extrapolated from the widest row RETURNED SO FAR, so it can still undershoot if later records are wider - check `truncated` again on the retry), and `guidance` spells out the alternatives. The only ceiling you cannot raise is the server's own (4 MB of rows per response), which protects the server rather than your context; past it, page with `next_after` or narrow the filter. **`max_bytes` bounds the ROWS, not the whole response.** Over MCP the payload is carried twice (structured plus text mirror) alongside the filter definition, which measured at 2.0x-2.9x the rows on the wire. So when sizing against a client tool-result cap, divide by ~3. The default is already sized that way. `suggested_max_bytes` comes back in the same rows units, so it can be passed straight back.
    - `fields` string[]: The projected field names, in the order the values appear in each row.
    - `rows` array[]: One array of values per matching record, ordered by id. Each value renders the way the resource's own serializer renders that column, so a money field such as `total_amount` arrives as a string at the currency's minor units (`"100.00"`) and can be compared with the same field read from the record endpoint. A `null` means the column has no value for that record.
      - unknown[]
        - unknown
    - `count` integer: Present only when `results.count` was true. Total records the filter matches, independent of the current page. Computed like the workspace stats count: exact, including past the 100,000-record scan cap, unless counting the whole set cannot finish within the time budget, in which case it reports the cap with `count_capped_at`. Counting a truncated result requires a second evaluation of the filter.
    - `count_capped_at` integer: Present only when `count` saturated at the scan cap the server applies and counting the whole set could not finish in time: the real total is HIGHER than `count`, so treat `count` as a floor rather than a total. Narrow the filter to get an exact number. Absent means `count` is exact. Same marker the workspace stats endpoint returns for the same case.
    - `count_unavailable_reason` string: Present only when `results.count` was true but its additional filter evaluation could not complete within the filtered-query time budget. The rows, truncation signal, and continuation cursor are still valid; narrow the filter or use the workspace stats endpoint for the count.
    - `truncated` boolean: True when `rows` is a page rather than the whole set, because the rows reached `limit` or `max_bytes`, or the request reached its filtered-query wall-clock budget.
    - `stop_reason` 'time_budget' | 'row_limit' | 'byte_budget' | 'record_exceeds_budget': Present only when `truncated`: which ceiling stopped us, so you do not have to parse `guidance` to find out. `row_limit` means raise your own `limit`; `byte_budget` means raise `max_bytes` or project fewer fields; `record_exceeds_budget` means a single record is larger than the whole budget, so project fewer fields. `time_budget` is the only one you cannot lift: the request reached its filtered-query wall-clock budget, so page with `next_after` or narrow the filter -- raising `max_bytes` or `limit` will not help, because neither is what stopped it.
    - `bytes` integer: Estimated serialized size of `rows`, measured before final response encoding. Values such as timestamps can make the wire representation slightly larger, so leave headroom.
    - `bytes_per_record` integer: Average estimated bytes per returned record, so you can size a later call for a different record count.
    - `max_bytes` integer: The pre-response row-cost budget applied — your `results.max_bytes` after clamping to the server ceiling, or the default when you didn't set one. It is not an exact wire-size ceiling; leave headroom.
    - `suggested_max_bytes` integer: Present only when `results.count` was true, the response is `truncated`, and the whole set could fit in one response: the `results.max_bytes` to retry with to get all `count` records in a single call. Extrapolated from the widest row returned SO FAR, not the average — so it is an estimate, and a later record wider than anything on this page can still make the retry truncate. Check `truncated` on the retry rather than assuming it is whole. Absent when the set is too large for any single response, when no exact total was requested or known, or when the wall-clock budget stopped the request — then page or narrow instead.
    - `next_after` string: Cursor to continue from, present only when `truncated` is true. Pass it back as `results[after]`. It is the id of the last row actually RETURNED, so paging never skips a record the budget dropped.
    - `guidance` string: Present only when `truncated` is true: what to do about it, cheapest-first — retry with `suggested_max_bytes` to get everything in one call, raise your own `limit`, narrow the filter, project fewer `fields`, page with `next_after` (including how many calls that will take at this size when `count` is available), export the full set as a CSV, or use the workspace stats endpoint if a number is all that was wanted. The export option is only offered when the filtered resource actually has a bulk export and the calling token could create one, so neither an order filter nor a read-only connection is pointed at something that would fail.
  - `created_at` string, date-time
  - `updated_at` string, date-time

## Other responses

- `400`: Bad Request - unsupported filter parameter
- `401`: Unauthorized
- `403`: Forbidden - the access token's scopes or workspace grant do not cover this request
- `404`: Not Found

## Changes

- **2026-11-03** `511d88b30aea`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/changes/workspaces/:workspace_id/segments/get.md)

---

[API](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api.md) - [All operations](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/llms.txt) - [OpenAPI document](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/revisions/511d88b30aea?raw)
