---
title: "Fetch Segment"
method: GET
path: "/segments/{id}"
tags: ["Segment"]
---

# Fetch Segment

`GET /segments/{id}`

## Request

- Base URL: `https://myworkspace.myclickfunnels.com/api/v2`
- URL: `https://myworkspace.myclickfunnels.com/api/v2/segments/{id}`
- 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/segments/:id/get.ts> (a function with typed inputs; its response is checked against the schema)

Fetch a named contact audience. Requires contacts:read.

## Path parameters

- `id` string, required

## Query parameters

- `results` union: Return projected matches inline. Pass `true` for ids only; omit for the filter definition alone.
  - boolean
  - object
    - `fields` string[]: Fields to project. Defaults to `["id"]`.
    - `limit` integer: Caller-set row limit. Defaults to 500.
    - `max_bytes` integer: Caller-set row byte budget. Defaults to 3072 and is capped at 4194304.
    - `after` string: Positive-integer cursor from `results.next_after`.
    - `count` boolean: Include the bounded total count. May require another filter evaluation.

## Response `200`

Success

- SegmentAttributes: A named contact audience visible in Contacts > Segments. The filter is a stored copy; editing or deleting the source saved filter does not change this audience.
  - `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

- `401`: Unauthorized
- `403`: Forbidden - the access token's scopes or workspace grant do not cover this request
- `404`: Not Found
- `422`: Unprocessable Entity - invalid results request
- `429`: Too Many Requests — two filtered reads are already active for this token and workspace
- `503`: Service Unavailable — retryable. Two conditions land here: * **Transient dependency** — a database connection, the model behind filter generation, or another dependency was briefly unavailable. * **Request budget exhausted** — the request's own wall clock ran out before the filter could be given a fair slice, so no records were read. The time went elsewhere in the same request: a slow generation call, or earlier pages of the same projection. The second case is the OPPOSITE of the 422 that says the filter "took longer than 10s to evaluate". That 422 is a statement timeout and is deterministic — the filter selects more than can be evaluated, and an unchanged retry fails identically. This 503 makes no such claim about the filter, so retrying is worth doing; if it recurs, narrow the filter or ask for fewer records per call.

## Changes

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

[Operation history](https://skmtc.dev/myclickfunnels/apis/clickfunnels-api/changes/segments/:id/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)
