---
title: "List charts"
method: GET
path: "/api/v3/charts"
tags: ["V3 Charts"]
---

# List charts

`GET /api/v3/charts`

## Request

- Base URL: `https://app.formbricks.com`
- URL: `https://app.formbricks.com/api/v3/charts`
- Auth: one of:
  - API key in cookie `next-auth.session-token`
  - API key in header `x-api-key`
  - HTTP bearer

Lists a workspace's charts, newest first, page by page. Each chart embeds the dashboards that
hold it. Needs read access to the workspace. Session cookie, `x-api-key`, or a Bearer token.

## Query parameters

- `workspaceId` string, cuid2, required
- `limit` integer
- `cursor` string
- `filter[name][contains]` string
- `filter[datasetId][eq]` string, cuid2

## Response `200`

A page of charts

- object
  - `data` ChartResource[], required
    - `id` string, cuid2, required
    - `workspaceId` string, cuid2, required
    - `datasetId` string, cuid2, required: The Feedback Dataset the chart reads. Fixed when the chart is created.
    - `name` string, required: Unique within the workspace.
    - `type` 'area' | 'bar' | 'pie' | 'big_number' | 'matrix', required
    - `query` ChartQuery, required: What a chart computes, in Cube's query format (ADR 0001): measures, dimensions, time dimensions, filters, order and limit over its Feedback Dataset's fields. Every field must come from the field catalog (`GET /api/v3/charts/fields`), named with its data-source prefix. Display settings are separate (`config`). Refused with **422** (`invalid_params` names each problem): a field that is not in the catalog; Cube options the app does not use (`ungrouped`, `segments`, `renewQuery`, `joinHints`, `total`, `compareDateRange`); a `timezone` (every range is read in the organization's display time zone); more than 15 fields across `measures`, `dimensions` and `timeDimensions`; more than 25 filter conditions or filters nested deeper than three levels; a date range that is not a preset, `all-time` or two ISO calendar dates; on a chart grouped by time alone, a date range that spans more than 10,000 buckets of its `granularity` (code `limit_exceeded`).
      - `measures` string[]
      - `dimensions` string[]
      - `timeDimensions` object[]
        - `dimension` string, required: A field of kind `timeDimension`.
        - `granularity` 'hour' | 'day' | 'week' | 'month' | 'quarter' | 'year'
        - `dateRange` union: A date range on a time dimension: a named preset from the field catalog's `datePresets` (`last 7 days`, `this month`, …), `all-time` (no range), or a pair of ISO calendar dates `[from, to]`, both inclusive, `from` not after `to`. Every range is read in the organization's display time zone; a `timezone` cannot be supplied. Charts saved before ranges were limited to presets may hold a relative range Cube reads itself (`last 3 months`, `this week`). Such a chart still renders and can be previewed, within the bucket limit below, and can be saved with that same range kept; a new chart, or an update to another range, must use a preset or a pair. A chart grouped by time alone (one time dimension with a `granularity`, no other dimensions) gets one row per bucket in its range, empty or not, so its range may span at most 10,000 buckets: about 13 months by the hour, or 27 years by the day. A wider range is refused with **422** `limit_exceeded`; use a coarser granularity or a shorter range. An older chart's relative range is measured back from now (`last 999 years` spans 999 years). Every preset fits at every granularity, and a chart with other dimensions returns only its real rows, so it is not limited.
          - string: A preset name from `datePresets`, or `all-time`.
          - string[]
      - `filters` ChartQueryFilter[]
        - union: A filter: either one condition on a field, or an `and` / `or` group of filters. Filters nest at most three levels: a group, a group inside it, and conditions inside that. A chart query holds at most 25 conditions in all.
          - object
            - `member` string, required: A field name from the field catalog.
            - `operator` 'equals' | 'notEquals' | 'contains' | 'notContains' | 'set' | 'notSet' | 'gt' | 'gte' | 'lt' | 'lte', required: One of the field's `filterOperators` in the catalog.
            - `values` string[]: The values to compare against. Required by every operator except `set` and `notSet`, which take none.
          - object
            - `and` ChartQueryFilter[], required
          - object
            - `or` ChartQueryFilter[], required
      - `order` union: Sort order: `[field, direction]` pairs, or an object mapping a field to its direction. At most 10 entries.
        - array[]
          - unknown[]
            - unknown
        - object
      - `limit` integer
      - `offset` integer
    - `config` ChartConfig, required: Display settings, kept apart from the chart query. Every key is optional; each applies to the chart types named in its description and is ignored by the others.
      - `barOrientation` 'vertical' | 'horizontal': Bar charts. Defaults to `vertical`.
      - `pieDisplay` 'pie' | 'breakdown': Pie charts. Defaults to `pie`.
      - `areaDisplay` 'filled' | 'line': Area charts. Defaults to `filled`.
      - `matrixCellValue` 'percent' | 'count' | 'both': Matrix charts. Defaults to `percent`.
      - `matrixColorScale` boolean: Matrix charts. Defaults to `true`.
      - `matrixShowTotals` boolean: Matrix charts. Defaults to `false`.
      - `matrixTranspose` boolean: Matrix charts. Swaps rows and columns on screen; the query is unchanged.
      - `colors` string[]
      - `xAxisLabel` string
      - `yAxisLabel` string
      - `showLegend` boolean
      - `legendPosition` 'top' | 'bottom' | 'left' | 'right'
      - `stacked` boolean
      - `showGrid` boolean
      - `showValues` boolean
      - `numberFormat` string
      - `dateFormat` string
      - `prefix` string
      - `suffix` string
    - `creator` object, nullable, required: Who created the chart, for display only; `null` once that user is gone.
      - `name` string, required
    - `dashboards` object[], required: The dashboards that hold the chart, by name.
      - `id` string, cuid2, required
      - `name` string, required
    - `createdAt` string, date-time, required
    - `updatedAt` string, date-time, required
  - `meta` CursorPaginationMeta, required: The pagination half of a v3 list's `meta`, shared by every paginated collection. Deliberately open, and never an endpoint's `meta` by itself: an endpoint composes it with `allOf` and closes the result with `unevaluatedProperties: false`. A base that closed itself could not be extended — inside an `allOf`, `additionalProperties: false` sees a sibling branch's properties as additional and rejects them. An endpoint that adds nothing still wraps it, so no `meta` anywhere is open. Every field here is `required`. A shared envelope that makes its fields optional is how v3's predecessor stopped honouring its own pagination contract without the schema gate noticing (ENG-2622): `meta: {}` — or no `meta` at all — validated cleanly while the endpoint returned nothing.
    - `limit` integer, required: The page size actually applied. Carries no `maximum`: it echoes what the server used, it does not bound what may be asked for. The request-side bound is the `limit` query parameter on the operation itself and differs per collection — read it there. A shared description cannot state it without being wrong for some of the operations that compose this base.
    - `nextCursor` string, nullable, required: Opaque cursor for the next page. `null` when there are no more results — the only reliable end-of-collection signal, since the server may return fewer items than `limit` without the collection being exhausted. Pass it back verbatim: the encoding is deliberately unspecified and may change without notice, so a client that decodes or constructs one is relying on something this contract does not promise.

## Other responses

- `400`: Bad Request — malformed JSON, invalid query/body/params, duplicate name, or unsupported field.
- `401`: Not authenticated (no valid session or API key).
- `403`: Forbidden. `code: forbidden` when the caller has no access to the workspace, the Feedback Dataset or the resource (which may also not exist; 404 is not used, to avoid leaking existence). `code: dashboards_plan_required` when the caller is authorized but the organization does not have the Dashboards add-on or a license that includes it — checked after authorization, so a caller without access never learns the organization's plan.
- `429`: Rate limit exceeded.
- `500`: Internal Server Error.

## Changes

- **2026-10-28** `84820a01e550`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/formbricks/apis/formbricks-api-v3/changes/api/v3/charts/get.md)

---

[API](https://skmtc.dev/formbricks/apis/formbricks-api-v3.md) - [All operations](https://skmtc.dev/formbricks/apis/formbricks-api-v3/llms.txt) - [OpenAPI document](https://skmtc.dev/formbricks/apis/formbricks-api-v3/revisions/25335c959a13?raw)
