> ## Documentation Index
> Fetch the complete documentation index at: https://api-docs.select.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Add a block to a dashboard

> Adds a block to a dashboard. Supply a position to place the block on the dashboard grid in the same request; omit it to add the block unplaced and set the dashboard's layout separately.



## OpenAPI

````yaml https://api.select.dev/v2/openapi.json post /dashboards/{dashboard_id}/blocks
openapi: 3.1.0
info:
  title: SELECT API (v2)
  version: 0.1.0
servers:
  - url: https://api.select.dev/v2
    description: SELECT API v2
security: []
tags:
  - name: metrics
    description: >-
      Query cost and usage data across Snowflake, BigQuery, Databricks and
      Tableau. Each route is `POST /v2/metrics/<model>/query` for one semantic
      model. Every route takes the same body shape and returns the same response
      shape. Each route page gives guidance on when to use the route, and worked
      examples.


      ## Body shape


      | Field | Meaning |

      | --- | --- |

      | `measures` | Aggregates to compute, for example `sum_spend`. |

      | `dimensions` | Fields to group by. Each one is returned on every row. |

      | `filter_expression` | An `and`/`or` tree of filters on dimensions,
      applied before aggregation. |

      | `measure_filters` | Filters on measures, applied after aggregation. |

      | `sort` | The order of the rows: `[{"field": "sum_spend", "direction":
      "desc"}]`. |

      | `limit` | The maximum number of rows. Results are not paginated: `limit`
      cuts the result short, and there is no next page. Omit `limit` to get all
      rows. |

      | `aggregate` | Set `false` to list the rows with no grouping. See
      "Listing rows". |


      v2 accepts only `filter_expression`. The body refuses the legacy `filters`
      list.


      ## Filter on dates


      Filter on the `day` field. Use two filters (both bounds are inclusive):


      ```json

      {"operator": "and", "filters": [
        {"field": "day", "operator": ">=", "value": "2026-08-01"},
        {"field": "day", "operator": "<=", "value": "2026-08-31"}], "limit": 1000}
      ```


      Or use one relative filter: `{"field": "day", "operator": "in range",
      "value": "30D"}`. The values are `{N}D` and `{N}M` (the last N days or
      months, today included), `WTD`, `MTD`, `QTD`, `YTD`, and `LMTD` (the whole
      previous calendar month).


      - Do not filter on `hour`, `week`, `month` or `quarter` to bound a range.
      Filter on `day`, and use the coarser fields as dimensions.

      - A timestamp such as `start_time <= "2026-08-31"` compares to midnight
      and drops most of that day. Use `day`, or `start_time < "2026-09-01"`.

      - A snapshot route (for example `snowflake-storage-summary`) describes the
      current state, and a `day` filter does not bound its size and cost fields.
      On routes that join the snapshot to activity, `day` bounds only the
      activity fields. Each route page says which fields these are.


      ## Which measure is cost


      - `sum_spend` (or `spend`, or `cost` on some routes) is the dollar cost in
      the filtered period. Use it for "how much did we spend".

      - `*_annualized` measures extend the spend of the filtered period to a
      year: a `7D` range gives that week's spend times 365 / 7. They are
      projections, not spend.

      - On snapshot routes, `annual_cost`, `*_monthly_cost` and `*_annual_cost`
      are the current rate extended to a month or a year. A date range does not
      bound them.

      - Do not present any of these run-rates as spend in a period.

      - Databricks routes also give DBUs (for example `sum_task_usage`). DBUs
      are not dollars.


      The `spend` route is the consolidated cost of every platform. Use it for
      totals, trends and breakdowns by service. Use a platform route to explain
      what inside the platform caused the cost.


      ## Text values are case-sensitive


      Filter values must match the stored case. A value in the wrong case
      matches no rows, with no error. For example:


      - On `spend`, `connection_type` is `Snowflake`, `Bigquery` or
      `Databricks`, and `"snowflake"` matches nothing.

      - On `search`, `data-freshness` and `workload-metadata-suggestions`,
      `connection_type` is lowercase: `snowflake`, `bigquery`, `databricks`.

      - On `snowflake-workloads`, most `resource_type` values are lowercase keys
      (`query_pattern`, `dbt`), but the AI types are title case (`Cortex
      Analyst`).


      ## Usage groups


      A usage group set divides cost into named groups, such as departments or
      teams. To group by the groups of one set, name the set in `path`:


      ```json

      {"dimensions": [{"field": "usage_group", "path": ["Department"]}],
      "limit": 1000}

      ```


      `path[0]` is the name of the set, not its ID. A plain `"usage_group"`
      dimension groups by every set at once. The same `{"field": ..., "path":
      [...]}` form reads keys of other semi-structured fields, for example
      workload metadata.


      ## Period over period


      Some routes publish `<measure>_previous_period`, `change_<measure>` and
      `percent_change_<measure>`. These measures need one bounded date range on
      `day`, at the top level of `filter_expression`:


      - Use two bounds on `day`, or one `in range` filter. Do not mix the two
      forms.

      - Do not nest the date filter in a sub-expression, and do not bound the
      range with `month` or `quarter`.

      - The previous period is the same number of days, just before the range.
      For `QTD` on 2026-09-28 (2026-07-01 to 2026-09-28, 90 days), the previous
      period is 2026-04-02 to 2026-06-30, not the previous calendar quarter.


      ## Listing rows


      Set `"aggregate": false` and name only `dimensions` to get the rows as
      they are, for example the individual queries that ran longer than ten
      minutes. If the body also names `measures` or `measure_filters`, the route
      aggregates, with no error. Always set a `limit` on a listing.


      ## Default scoping filters


      Some tables hold more than one kind of row, and the SELECT app filters to
      one kind by default. Each route page names these filters. For example:


      - `snowflake-query-patterns`: `{"field": "resource_type", "operator":
      "in", "values": ["query_pattern"]}`. `bigquery-query-patterns` filters
      `workload_type` to `bigquery_query_pattern`, and
      `databricks-query-patterns` filters `resource_type` to
      `databricks_query_pattern`.

      - `snowflake-dbt`: `{"field": "dbt_node_resource_type", "operator": "=",
      "value": "model"}`. Without it, tests, seeds and snapshots rank with
      models. The same filter applies to `bigquery-dbt-queries` and
      `databricks-dbt-queries`.


      ## Teams


      Send `X-Team-Id` to evaluate a query as a team you belong to. The rows are
      then limited to what the team's roles can reach.


      ## Which route answers which question


      | Question | Route |

      | --- | --- |

      | Total spend, spend trend, spend by platform, service or usage group |
      `spend` |

      | Most expensive Snowflake warehouses | `snowflake-workloads` (or
      `snowflake-warehouses` for metering spend) |

      | Warehouse utilization, idle spend, cluster usage |
      `snowflake-warehouses`, `snowflake-warehouse-clusters` |

      | Query latency, spillage and bytes scanned on a warehouse |
      `snowflake-warehouse-query-performance` |

      | Most expensive recurring queries | `snowflake-query-patterns` |

      | Individual queries | `snowflake-queries` |

      | Cost of dbt models, and of dbt runs | `snowflake-dbt`,
      `snowflake-dbt-invocations` |

      | Cost of tasks, stored procedures, dynamic tables | `snowflake-tasks`,
      `snowflake-stored-procedures`, `snowflake-dynamic-tables` |

      | Cost of BI tools (Looker, Mode, Hex, Sigma, Periscope, Tableau) |
      `snowflake-looker`, `snowflake-mode`, `snowflake-hex`, `snowflake-sigma`,
      `snowflake-periscope`, `tableau-queries` |

      | Cost of Fivetran, and of workloads defined by query tags |
      `snowflake-fivetran`, `snowflake-custom-workloads` |

      | Serverless, automatic clustering and Snowpipe cost |
      `snowflake-serverless`, `snowflake-automatic-clustering`,
      `snowflake-snowpipe` |

      | Storage cost in a period | `snowflake-storage`, `bigquery-storage-spend`
      |

      | Largest or unused tables now | `snowflake-storage-summary`,
      `bigquery-storage-summary` |

      | Which workloads read or write a table | `lineage-workloads`,
      `lineage-tables`, `lineage-edges` |

      | BigQuery cost by project, job or query pattern | `bigquery-projects`,
      `bigquery-jobs`, `bigquery-query-patterns` |

      | BigQuery reservations and commitments | `bigquery-reservation-timeline`,
      `bigquery-commitments`, `bigquery-commitment-scopes` |

      | Databricks cost by job, query, SQL warehouse or cluster |
      `databricks-jobs`, `databricks-queries`, `databricks-sql-warehouses`,
      `databricks-clusters` |

      | Savings from SELECT actions | `action-realized-savings` |

      | How current the data is | `data-freshness` |
paths:
  /dashboards/{dashboard_id}/blocks:
    post:
      tags:
        - dashboards
      summary: Add a block to a dashboard
      description: >-
        Adds a block to a dashboard. Supply a position to place the block on the
        dashboard grid in the same request; omit it to add the block unplaced
        and set the dashboard's layout separately.
      operationId: create_dashboard_block_route_dashboards__dashboard_id__blocks_post
      parameters:
        - name: dashboard_id
          in: path
          required: true
          schema:
            type: string
            title: Dashboard Id
        - name: x-tenant-id
          in: header
          required: true
          schema:
            type: string
            description: The organization ID the request is scoped to.
            title: X-Tenant-Id
          description: The organization ID the request is scoped to.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/BlockCreate'
      responses:
        '201':
          description: Successful Response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/BlockV2'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '403':
          $ref: '#/components/responses/Forbidden'
        '404':
          $ref: '#/components/responses/NotFound'
        '405':
          $ref: '#/components/responses/MethodNotAllowed'
        '408':
          $ref: '#/components/responses/RequestTimeout'
        '409':
          $ref: '#/components/responses/Conflict'
        '422':
          $ref: '#/components/responses/ValidationFailed'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - HTTPBearer: []
components:
  schemas:
    BlockCreate:
      properties:
        config:
          oneOf:
            - $ref: '#/components/schemas/BigNumberBlockConfig-Input'
            - $ref: '#/components/schemas/ChartBlockConfig-Input'
            - $ref: '#/components/schemas/BarListBlockConfig-Input'
            - $ref: '#/components/schemas/TableBlockConfig-Input'
            - $ref: '#/components/schemas/FeedBlockConfig-Input'
            - $ref: '#/components/schemas/TextBlockConfig'
            - $ref: '#/components/schemas/EntityCardBlockConfig'
          title: Config
          description: What the block shows and how it is displayed.
          discriminator:
            propertyName: block_type
            mapping:
              bar_list:
                $ref: '#/components/schemas/BarListBlockConfig-Input'
              big_number:
                $ref: '#/components/schemas/BigNumberBlockConfig-Input'
              chart:
                $ref: '#/components/schemas/ChartBlockConfig-Input'
              entity_card:
                $ref: '#/components/schemas/EntityCardBlockConfig'
              feed:
                $ref: '#/components/schemas/FeedBlockConfig-Input'
              table:
                $ref: '#/components/schemas/TableBlockConfig-Input'
              text:
                $ref: '#/components/schemas/TextBlockConfig'
        position:
          anyOf:
            - oneOf:
                - $ref: '#/components/schemas/AppendRowPosition'
                - $ref: '#/components/schemas/FreeformBlockPosition'
              discriminator:
                propertyName: kind
                mapping:
                  append_row:
                    $ref: '#/components/schemas/AppendRowPosition'
                  freeform:
                    $ref: '#/components/schemas/FreeformBlockPosition'
            - type: 'null'
          title: Position
          description: >-
            Where to place the block on the dashboard grid. Omit to add the
            block without placing it and set `freeform_layout` on the dashboard
            instead.
      additionalProperties: false
      type: object
      required:
        - config
      title: BlockCreate
      description: A block to add to a dashboard.
    BlockV2:
      properties:
        id:
          type: string
          title: Id
          description: The unique identifier of the block.
          readOnly: true
          x-terraform-computed: true
        config:
          oneOf:
            - $ref: '#/components/schemas/BigNumberBlockConfig-Output'
            - $ref: '#/components/schemas/ChartBlockConfig-Output'
            - $ref: '#/components/schemas/BarListBlockConfig-Output'
            - $ref: '#/components/schemas/TableBlockConfig-Output'
            - $ref: '#/components/schemas/FeedBlockConfig-Output'
            - $ref: '#/components/schemas/TextBlockConfig'
            - $ref: '#/components/schemas/EntityCardBlockConfig'
          title: Config
          description: What the block shows and how it is displayed.
          discriminator:
            propertyName: block_type
            mapping:
              bar_list:
                $ref: '#/components/schemas/BarListBlockConfig-Output'
              big_number:
                $ref: '#/components/schemas/BigNumberBlockConfig-Output'
              chart:
                $ref: '#/components/schemas/ChartBlockConfig-Output'
              entity_card:
                $ref: '#/components/schemas/EntityCardBlockConfig'
              feed:
                $ref: '#/components/schemas/FeedBlockConfig-Output'
              table:
                $ref: '#/components/schemas/TableBlockConfig-Output'
              text:
                $ref: '#/components/schemas/TextBlockConfig'
        create_time:
          type: string
          title: Create Time
          description: When the block was created, as an RFC 3339 UTC timestamp.
          readOnly: true
          x-terraform-computed: true
        update_time:
          type: string
          title: Update Time
          description: When the block was last changed, as an RFC 3339 UTC timestamp.
          readOnly: true
          x-terraform-computed: true
        etag:
          type: string
          title: Etag
          description: >-
            Opaque strong ETag. Supply it in an If-Match header when changing or
            deleting the block.
          readOnly: true
          x-terraform-computed: true
      type: object
      required:
        - id
        - config
        - create_time
        - update_time
        - etag
      title: Block
      description: >-
        A single unit of content on a dashboard, such as a chart, table, or
        note.
    BigNumberBlockConfig-Input:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: big_number
          title: Block Type
        display:
          $ref: '#/components/schemas/BigNumberDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: BigNumberBlockConfig
    ChartBlockConfig-Input:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: chart
          title: Block Type
        display:
          $ref: '#/components/schemas/ChartDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: ChartBlockConfig
    BarListBlockConfig-Input:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: bar_list
          title: Block Type
        display:
          $ref: '#/components/schemas/BarListDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: BarListBlockConfig
    TableBlockConfig-Input:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: table
          title: Block Type
        display:
          $ref: '#/components/schemas/TableDisplayConfig'
          default:
            columns: []
            pivot_columns: []
            pivot_col_limit: 50
            row_limit: 1000
            cell_rules: []
            collapsible_rows: false
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
      title: TableBlockConfig
    FeedBlockConfig-Input:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: feed
          title: Block Type
        display:
          anyOf:
            - oneOf:
                - $ref: '#/components/schemas/FeedDisplayConfig'
                - $ref: '#/components/schemas/MonitorFeedDisplayConfig'
              discriminator:
                propertyName: kind
                mapping:
                  insights:
                    $ref: '#/components/schemas/FeedDisplayConfig'
                  monitor:
                    $ref: '#/components/schemas/MonitorFeedDisplayConfig'
            - type: 'null'
          title: Display
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
      title: FeedBlockConfig
    TextBlockConfig:
      properties:
        block_type:
          type: string
          const: text
          title: Block Type
        content:
          type: string
          title: Content
          default: ''
      additionalProperties: false
      type: object
      required:
        - block_type
      title: TextBlockConfig
    EntityCardBlockConfig:
      properties:
        block_type:
          type: string
          const: entity_card
          title: Block Type
        entity_type:
          type: string
          enum:
            - monitor
            - budget
          title: Entity Type
        entity_id:
          type: string
          title: Entity Id
      additionalProperties: false
      type: object
      required:
        - block_type
        - entity_type
        - entity_id
      title: EntityCardBlockConfig
    AppendRowPosition:
      properties:
        kind:
          type: string
          const: append_row
          title: Kind
        height_px:
          type: integer
          exclusiveMinimum: 0
          title: Height Px
        col_span:
          anyOf:
            - type: integer
              maximum: 12
              exclusiveMinimum: 0
            - type: 'null'
          title: Col Span
      additionalProperties: false
      type: object
      required:
        - kind
        - height_px
      title: AppendRowPosition
    FreeformBlockPosition:
      properties:
        x:
          type: integer
          exclusiveMaximum: 12
          minimum: 0
          title: X
        'y':
          type: integer
          minimum: 0
          title: 'Y'
        w:
          type: integer
          maximum: 12
          exclusiveMinimum: 0
          title: W
        h:
          type: integer
          exclusiveMinimum: 0
          title: H
        kind:
          type: string
          const: freeform
          title: Kind
        after_block_id:
          anyOf:
            - type: string
              format: uuid
            - type: 'null'
          title: After Block Id
      additionalProperties: false
      type: object
      required:
        - x
        - 'y'
        - w
        - h
        - kind
      title: FreeformBlockPosition
    BigNumberBlockConfig-Output:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: big_number
          title: Block Type
        display:
          $ref: '#/components/schemas/BigNumberDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: BigNumberBlockConfig
    ChartBlockConfig-Output:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: chart
          title: Block Type
        display:
          $ref: '#/components/schemas/ChartDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: ChartBlockConfig
    BarListBlockConfig-Output:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: bar_list
          title: Block Type
        display:
          $ref: '#/components/schemas/BarListDisplayConfig'
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
        - display
      title: BarListBlockConfig
    TableBlockConfig-Output:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: table
          title: Block Type
        display:
          $ref: '#/components/schemas/TableDisplayConfig'
          default:
            columns: []
            pivot_columns: []
            pivot_col_limit: 50
            row_limit: 1000
            cell_rules: []
            collapsible_rows: false
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
      title: TableBlockConfig
    FeedBlockConfig-Output:
      properties:
        query_class:
          type: string
          title: Query Class
        title:
          type: string
          title: Title
        description:
          type: string
          title: Description
          default: ''
        tooltip:
          type: string
          title: Tooltip
          default: ''
        query_scope:
          $ref: '#/components/schemas/QueryScope'
          default:
            filters: []
        block_type:
          type: string
          const: feed
          title: Block Type
        display:
          anyOf:
            - oneOf:
                - $ref: '#/components/schemas/FeedDisplayConfig'
                - $ref: '#/components/schemas/MonitorFeedDisplayConfig'
              discriminator:
                propertyName: kind
                mapping:
                  insights:
                    $ref: '#/components/schemas/FeedDisplayConfig'
                  monitor:
                    $ref: '#/components/schemas/MonitorFeedDisplayConfig'
            - type: 'null'
          title: Display
      additionalProperties: false
      type: object
      required:
        - query_class
        - title
        - block_type
      title: FeedBlockConfig
    ProblemDetail:
      additionalProperties: true
      description: >-
        RFC 9457-style error payload, served as ``application/problem+json``.


        ``code`` is the stable, machine-readable identifier — consumers branch
        on it,

        never on ``title``. ``type`` stays ``about:blank``: we keep no per-error

        documentation pages. There is no ``instance``/request-id member (we
        don't run

        access logs). See the flat error-code catalogue in §4 of the standards
        doc.
      properties:
        type:
          default: about:blank
          title: Type
          type: string
        title:
          type: string
          title: Title
        status:
          title: Status
          type: integer
        detail:
          title: Detail
          type: string
        code:
          title: Code
          type: string
        retryable:
          title: Retryable
          type: boolean
        details:
          anyOf:
            - items:
                additionalProperties: true
                type: object
              type: array
            - type: 'null'
          default: null
          title: Details
      required:
        - title
        - status
        - detail
        - code
        - retryable
      title: ProblemDetail
      type: object
    QueryScope:
      properties:
        filters:
          items:
            additionalProperties: true
            type: object
          type: array
          title: Filters
          default: []
        date_range:
          anyOf:
            - $ref: '#/components/schemas/DateRange'
            - type: 'null'
        time_grain:
          anyOf:
            - type: string
              enum:
                - day
                - week
                - month
            - type: 'null'
          title: Time Grain
      additionalProperties: false
      type: object
      title: QueryScope
    BigNumberDisplayConfig:
      properties:
        metric:
          type: string
          title: Metric
        previous_period_comparison:
          type: string
          enum:
            - none
            - value
            - value_and_percentage
          title: Previous Period Comparison
          default: none
      additionalProperties: false
      type: object
      required:
        - metric
      title: BigNumberDisplayConfig
    ChartDisplayConfig:
      properties:
        chart_type:
          type: string
          title: Chart Type
        metric:
          type: string
          title: Metric
        group_by:
          type: string
          title: Group By
          default: None
        legend_type:
          type: string
          title: Legend Type
          default: None
        selected_action_types:
          items:
            $ref: '#/components/schemas/ActionTypeKey'
          type: array
          title: Selected Action Types
      additionalProperties: false
      type: object
      required:
        - chart_type
        - metric
      title: ChartDisplayConfig
    BarListDisplayConfig:
      properties:
        metric:
          type: string
          title: Metric
        group_by:
          type: string
          title: Group By
        limit:
          type: integer
          title: Limit
          default: 10
      additionalProperties: false
      type: object
      required:
        - metric
        - group_by
      title: BarListDisplayConfig
    TableDisplayConfig:
      properties:
        columns:
          items:
            type: string
          type: array
          title: Columns
          default: []
        table_mode:
          anyOf:
            - type: string
              enum:
                - table
                - pivot
            - type: 'null'
          title: Table Mode
        pivot_columns:
          items:
            type: string
          type: array
          title: Pivot Columns
          default: []
        pivot_col_limit:
          type: integer
          title: Pivot Col Limit
          default: 50
        pivot_sort_key:
          anyOf:
            - type: string
            - type: 'null'
          title: Pivot Sort Key
        pivot_sort_order:
          anyOf:
            - type: string
              enum:
                - asc
                - desc
            - type: 'null'
          title: Pivot Sort Order
        row_limit:
          type: integer
          title: Row Limit
          default: 1000
        sort_key:
          anyOf:
            - type: string
            - type: 'null'
          title: Sort Key
        sort_order:
          anyOf:
            - type: string
              enum:
                - asc
                - desc
            - type: 'null'
          title: Sort Order
        cell_rules:
          items:
            additionalProperties: true
            type: object
          type: array
          title: Cell Rules
          default: []
        collapsible_rows:
          type: boolean
          title: Collapsible Rows
          default: false
      additionalProperties: false
      type: object
      title: TableDisplayConfig
    FeedDisplayConfig:
      properties:
        kind:
          type: string
          const: insights
          title: Kind
          default: insights
        row_limit:
          type: integer
          maximum: 100
          minimum: 1
          title: Row Limit
          default: 20
        sort_key:
          type: string
          enum:
            - effective_annualized_potential_savings_lower_bound
            - first_generated_at
          title: Sort Key
          default: effective_annualized_potential_savings_lower_bound
        sort_order:
          type: string
          enum:
            - asc
            - desc
          title: Sort Order
          default: desc
      additionalProperties: false
      type: object
      title: FeedDisplayConfig
    MonitorFeedDisplayConfig:
      properties:
        kind:
          type: string
          const: monitor
          title: Kind
          default: monitor
        sort_key:
          type: string
          enum:
            - severity
            - recent
            - frequency
          title: Sort Key
          default: severity
      additionalProperties: false
      type: object
      title: MonitorFeedDisplayConfig
    DateRange:
      properties:
        relative_shortcut:
          anyOf:
            - type: string
            - type: 'null'
          title: Relative Shortcut
        start_date:
          anyOf:
            - type: string
            - type: 'null'
          title: Start Date
        end_date:
          anyOf:
            - type: string
            - type: 'null'
          title: End Date
      additionalProperties: false
      type: object
      title: DateRange
    ActionTypeKey:
      type: string
      enum:
        - warehouse
        - query-pattern
        - task
        - stored-procedure
        - dynamic-table
        - snowpipe
        - dbt
        - storage
        - view
        - custom-workload
        - databricks-query-pattern
        - databricks-job
        - databricks-task
        - databricks-sql-warehouse
        - databricks-all-purpose
        - databricks-submit-run-job
        - databricks-dbt
        - looker-dashboard
        - looker-explore
        - mode-report
        - hex-project
        - periscope-dashboard
        - sigma-type
        - sigma-kind
        - tableau-workbook
        - tableau-data-source
        - tableau-user
        - fivetran-table
        - global
      title: ActionTypeKey
      description: |-
        Canonical SRN resource-type slugs for savings actions.

        Single source of truth for the set: this enum is surfaced in the OpenAPI
        spec, so the frontend's `ActionTypeKey` type is generated from it (see
        web/frontend/src/utils/savings/actionTypes.ts).
  responses:
    BadRequest:
      description: Bad request
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    Unauthorized:
      description: Unauthorized
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
      headers:
        WWW-Authenticate:
          description: Authentication challenge for the requested resource.
          required: true
          schema:
            type: string
    Forbidden:
      description: Forbidden
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    NotFound:
      description: Not found
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    MethodNotAllowed:
      description: Method not allowed
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
      headers:
        Allow:
          description: HTTP methods supported by the requested resource.
          required: true
          schema:
            type: string
    RequestTimeout:
      description: Request Timeout
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    Conflict:
      description: Conflict
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    ValidationFailed:
      description: Validation failed
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    RateLimited:
      description: Rate limited
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request.
          required: true
          schema:
            type: integer
            minimum: 0
    InternalError:
      description: Internal error
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
    ServiceUnavailable:
      description: Service unavailable
      content:
        application/problem+json:
          schema:
            $ref: '#/components/schemas/ProblemDetail'
      headers:
        Retry-After:
          description: Number of seconds to wait before retrying the request.
          required: true
          schema:
            type: integer
            minimum: 0
  securitySchemes:
    HTTPBearer:
      type: http
      description: Organization API key (sl_…).
      scheme: bearer

````