---
title: "Get chart"
method: GET
path: "/v0/boards/{boardId}/charts/{chartId}"
tags: ["Charts"]
---

# Get chart

`GET /v0/boards/{boardId}/charts/{chartId}`

## Request

- Base URL: `https://api.formo.so`
- URL: `https://api.formo.so/v0/boards/{boardId}/charts/{chartId}`
- Auth: HTTP bearer

## Path parameters

- `boardId` string, required
- `chartId` string, required

## Response `200`

Chart details

- Chart: A saved chart attached to a board.
  - `id` string, required
  - `chart_type` 'table' | 'number' | 'funnel' | 'bar' | 'line' | 'area' | 'pie' | 'stacked' | 'user_paths' | 'retention', required: Visualization type.
  - `title` string, required
  - `description` string, nullable
  - `query` string, required: SQL query powering the chart. For `funnel` and `retention` charts this is a system-managed placeholder.
  - `project_id` string, required
  - `board_id` string, required
  - `x_axis` string, nullable: Column used as the X axis.
  - `y_axis` string[], nullable: Column(s) used as Y axis metric(s).
  - `group_by` string, nullable: Column used to group/stack series.
  - `steps` FunnelStep[], nullable: Ordered list of funnel steps. Only present when `chart_type` is `funnel`.
    - `type` 'event' | 'track' | 'decoded_log', required: `event`: built-in page/connect/transaction events; `track`: custom tracked events; `decoded_log`: decoded smart-contract events.
    - `event` string, required: Event name (e.g. `page`, `connect`, `transaction`, or a custom track event name).
    - `events` FunnelStepEvent[]: Optional OR group (funnel steps only, max 10). When present and non-empty the step matches any of these events, e.g. `[{"type":"track","event":"Swap Initiated"},{"type":"track","event":"Limit Order Placed"}]`. The primary `type`/`event` is always included.
      - `type` 'event' | 'track' | 'decoded_log', required
      - `event` string, required
      - `filters` StepFilterCondition[]: Member-scoped predicates, AND-joined within this member.
        - `field` string, required: Column or property targeted by this filter.
        - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
        - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
          - string
          - number
          - boolean
          - union[]
            - union
              - …
    - `filters` StepFilterCondition[]
      - `field` string, required: Column or property targeted by this filter.
      - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
      - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
        - string
        - number
        - boolean
        - union[]
          - union
            - string
            - number
  - `settings` ChartSettings: Chart-type-specific configuration. The fields that apply depend on `chart_type`: - **funnel**: `funnelType`, `conversionWindow`, `breakdown` - **user_paths**: `anchors`, `maxSteps`, `nodesPerStep`, `conversionWindow`, `filters` - **retention**: `entryFilter`, `retentionFilter`, `retentionUserFilters`, `retentionSignalType`, `retentionLabelSignal` Fields are optional at the schema level except where the selected chart type requires them. User Paths require at least one `anchors` entry. Retention requests must explicitly include `entryFilter`; use `null` for any event.
    - `funnelType` 'closed' | 'open': **Funnel only.** `closed`: users must complete steps in strict order with no intervening events. `open`: users may complete steps in order but other events may occur between steps.
    - `conversionWindow` ConversionWindow: Time window within which a user must complete all funnel steps (measured from Step 1). Defaults to 2 hours if omitted.
      - `value` integer, required: Number of time units.
      - `unit` 'hour' | 'day' | 'week', required: Time unit. `week` = 7 days.
    - `breakdown` 'device' | 'browser' | 'os' | 'location' | 'referrer' | 'ref' | 'utm_source' | 'utm_medium' | 'utm_campaign' | 'utm_term' | 'utm_content' | 'builder_codes': **Funnel only.** Split each funnel bar by this dimension. The top categories are shown individually; the rest are collapsed into 'Others'.
    - `anchors` FunnelStep[]: **user_paths (required).** Ordered path anchors. The first entry starts the flow; the last entry ends it. A single entry creates an open-ended flow.
      - `type` 'event' | 'track' | 'decoded_log', required: `event`: built-in page/connect/transaction events; `track`: custom tracked events; `decoded_log`: decoded smart-contract events.
      - `event` string, required: Event name (e.g. `page`, `connect`, `transaction`, or a custom track event name).
      - `events` FunnelStepEvent[]: Optional OR group (funnel steps only, max 10). When present and non-empty the step matches any of these events, e.g. `[{"type":"track","event":"Swap Initiated"},{"type":"track","event":"Limit Order Placed"}]`. The primary `type`/`event` is always included.
        - `type` 'event' | 'track' | 'decoded_log', required
        - `event` string, required
        - `filters` StepFilterCondition[]: Member-scoped predicates, AND-joined within this member.
          - `field` string, required: Column or property targeted by this filter.
          - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
          - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
            - string
            - number
            - boolean
            - union[]
              - …
      - `filters` StepFilterCondition[]
        - `field` string, required: Column or property targeted by this filter.
        - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
        - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
          - string
          - number
          - boolean
          - union[]
            - union
              - …
    - `maxSteps` integer: **user_paths.** Maximum number of steps to show in the flow (2 to 5). Values above 5 are clamped to 5.
    - `nodesPerStep` integer: **user_paths.** Maximum number of unique event nodes visible per step (2 to 8). Values above 8 are clamped to 8.
    - `filters` string: **user_paths.** JSON-encoded string of additional filters applied to the path query.
    - `retentionFilter` FunnelStep: A single funnel or user-path step. Event-property predicates are stored in `filters`, using the same canonical `{field, op, value}` envelope as every other filter surface. Funnel steps (not user-path anchors or retention filters) may also carry `events`, an OR group: the step then matches any listed event. `type`/`event` stay the step's primary event and are always part of the group; `filters` apply to the whole group.
      - `type` 'event' | 'track' | 'decoded_log', required: `event`: built-in page/connect/transaction events; `track`: custom tracked events; `decoded_log`: decoded smart-contract events.
      - `event` string, required: Event name (e.g. `page`, `connect`, `transaction`, or a custom track event name).
      - `events` FunnelStepEvent[]: Optional OR group (funnel steps only, max 10). When present and non-empty the step matches any of these events, e.g. `[{"type":"track","event":"Swap Initiated"},{"type":"track","event":"Limit Order Placed"}]`. The primary `type`/`event` is always included.
        - `type` 'event' | 'track' | 'decoded_log', required
        - `event` string, required
        - `filters` StepFilterCondition[]: Member-scoped predicates, AND-joined within this member.
          - `field` string, required: Column or property targeted by this filter.
          - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
          - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
            - string
            - number
            - boolean
            - union[]
              - …
      - `filters` StepFilterCondition[]
        - `field` string, required: Column or property targeted by this filter.
        - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
        - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
          - string
          - number
          - boolean
          - union[]
            - union
              - …
    - `entryFilter` FunnelStep: A single funnel or user-path step. Event-property predicates are stored in `filters`, using the same canonical `{field, op, value}` envelope as every other filter surface. Funnel steps (not user-path anchors or retention filters) may also carry `events`, an OR group: the step then matches any listed event. `type`/`event` stay the step's primary event and are always part of the group; `filters` apply to the whole group.
      - `type` 'event' | 'track' | 'decoded_log', required: `event`: built-in page/connect/transaction events; `track`: custom tracked events; `decoded_log`: decoded smart-contract events.
      - `event` string, required: Event name (e.g. `page`, `connect`, `transaction`, or a custom track event name).
      - `events` FunnelStepEvent[]: Optional OR group (funnel steps only, max 10). When present and non-empty the step matches any of these events, e.g. `[{"type":"track","event":"Swap Initiated"},{"type":"track","event":"Limit Order Placed"}]`. The primary `type`/`event` is always included.
        - `type` 'event' | 'track' | 'decoded_log', required
        - `event` string, required
        - `filters` StepFilterCondition[]: Member-scoped predicates, AND-joined within this member.
          - `field` string, required: Column or property targeted by this filter.
          - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
          - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
            - string
            - number
            - boolean
            - union[]
              - …
      - `filters` StepFilterCondition[]
        - `field` string, required: Column or property targeted by this filter.
        - `op` 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'in' | 'nin' | 'startsWith' | 'endsWith' | 'contains' | 'notEmpty' | 'isEmpty', required: Canonical comparison operator token.
        - `value` union: Value to compare against. Omit for `notEmpty` and `isEmpty`. For `in` / `nin`, pass a non-empty array or a pipe-delimited string. Array string members cannot contain a literal `|`, which is reserved as the Tinybird membership separator.
          - string
          - number
          - boolean
          - union[]
            - union
              - …
    - `retentionUserFilters` RetentionUserFilter[]: **retention.** Zero or more user-segment filters that narrow the cohort (e.g. only desktop users, only users from a specific UTM source).
      - `value` union: The value to compare against. Omit for `notEmpty` and `isEmpty`.
        - string
        - number
      - `field` string, required: The user property to filter on (e.g. `device`, `browser`, `os`, `location`, `utm_source`, `utm_medium`, `utm_campaign`).
      - `op` 'eq' | 'neq' | 'in' | 'nin' | 'gt' | 'gte' | 'lt' | 'lte' | 'notEmpty' | 'isEmpty', required: Comparison operator. Only the canonical terse tokens are accepted (the retired long forms `greater`/`greaterOrEqual`/`less`/`lessOrEqual` are rejected). `notEmpty` ("is not empty") and `isEmpty` ("is empty") are value-less existence checks on a string user property; the `value` is ignored. Substring operators (`startsWith` / `endsWith` / `contains`) are not supported on retention user filters.
    - `retentionSignalType` 'event' | 'label': **retention.** `event` (default): cohort and retention are driven by events. `label`: driven by a label value over time (see `retentionLabelSignal`); when `label`, the event fields are ignored.
    - `retentionLabelSignal` RetentionLabelSignal: The label predicate for label-based retention. The cohort is wallets grouped by the week they FIRST crossed this predicate on their label value; a wallet is retained in a later week if its latest value as of that week's end still satisfies it (as-of / carry-forward, evaluated against label history).
      - `field` string, required: The label tag to evaluate (the value of `tag_id` set via `POST /v0/profiles/:address/labels`).
      - `op` 'gt' | 'gte' | 'lt' | 'lte' | 'eq', required: Comparison operator. Numeric operators coerce both sides via toFloat64OrZero, so a numeric op on a non-numeric value yields no match (not an error).
      - `value` string, required: The threshold/value to compare against. Always a string; numeric ops coerce it.
      - `chain_id` string: Optional chain scope. Empty string matches across all chains.
    - `retentionCohortLabelFilters` RetentionCohortLabelFilter[]: **retention.** Label predicates that restrict an event-based cohort.
      - `field` string, required: The label tag to evaluate.
      - `op` 'eq' | 'neq' | 'contains' | 'gt' | 'gte' | 'lt' | 'lte', required
      - `value` string, required
      - `chain_id` string: Optional chain scope. Empty string matches across all chains.

---

[API](https://skmtc.dev/formo/apis/formo-public-api.md) · [All operations](https://skmtc.dev/formo/apis/formo-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/formo/apis/formo-public-api/revisions/67ada57df63c?raw)
