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

# Run a cost-change diff tree

> Returns a `GROUP BY ROLLUP` tree of current vs previous cost per node for exactly one `cost` or `usage` series. Requires an enabled comparison period, a non-hourly `aggBy`, and at least one `groupBy` axis on that series. Pre-condition failures return `400 INVALID_QUERY` with today's message in `reason`. There is no Hour entitlement gate — hourly is rejected for every organization.



## OpenAPI

````yaml /api-reference/openapi.json post /queries/diff-tree
openapi: 3.0.0
info:
  title: Costory
  version: '1.0'
  description: API Documentation
servers:
  - url: ''
    description: Production server
security: []
paths:
  /queries/diff-tree:
    post:
      tags:
        - Query Costs
      summary: Run a cost-change diff tree
      description: >-
        Returns a `GROUP BY ROLLUP` tree of current vs previous cost per node
        for exactly one `cost` or `usage` series. Requires an enabled comparison
        period, a non-hourly `aggBy`, and at least one `groupBy` axis on that
        series. Pre-condition failures return `400 INVALID_QUERY` with today's
        message in `reason`. There is no Hour entitlement gate — hourly is
        rejected for every organization.
      operationId: runQueryDiffTree
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/QueryDiffTreeRequest'
      responses:
        '200':
          description: Diff-tree rollup rows
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/DiffTreeResponse'
        '400':
          description: >-
            Invalid query (strict CEL contract, formula refs, period, group-by,
            or other request rules)
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvalidQueryError'
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Unauthorized'
        '404':
          description: >-
            Scope or external-metric integration absent or not visible to this
            organization
          content:
            application/json:
              schema:
                anyOf:
                  - $ref: '#/components/schemas/ScopeNotFoundOrForbiddenError'
                  - $ref: >-
                      #/components/schemas/ExternalMetricIntegrationNotFoundError
        '500':
          description: Unexpected server error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InternalServerError'
      security:
        - bearerAuth: []
components:
  schemas:
    QueryDiffTreeRequest:
      type: object
      properties:
        queries:
          type: array
          items:
            oneOf:
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - cost
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  groupBy:
                    anyOf:
                      - type: string
                      - type: array
                        items:
                          type: string
                          minLength: 1
                      - nullable: true
                        type: string
                        enum:
                          - null
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  filterCel:
                    type: string
                    nullable: true
                    description: >-
                      Optional scope filter as CEL (Common Expression Language).
                      Examples: cos_service_name in ["AmazonEC2"]; cos_provider
                      in ["AWS"] && cos_environment in ["prod"]. Label
                      dimensions use the cos_ prefix; native provider fields
                      omit it. Unlabelled/untagged resources have null values;
                      use == null to match them (e.g. cos_environment == null)
                      and != null to exclude them. Omit or pass empty string for
                      no filter.
                  metricId:
                    type: string
                    enum:
                      - cost
                      - effective_cost
                      - list_cost
                      - contracted_cost
                      - unblended_cost
                      - net_unblended_cost
                      - amortized_cost
                      - net_amortized_cost
                    default: cost
                    description: >-
                      Cost column to query (e.g. "cost", "effective_cost",
                      "amortized_cost"). Defaults to "cost".
                  currency:
                    type: string
                    enum:
                      - USD
                      - EUR
                      - GBP
                      - CNY
                    default: USD
                    description: >-
                      Currency for cost values (USD, EUR, GBP). Defaults to
                      "USD".
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                  aggregator:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                    description: Aggregation over the bucket. Defaults to SUM.
                  reducer:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                  shiftAmount:
                    type: integer
                  shiftUnit:
                    type: string
                    enum:
                      - DAY
                      - WEEK
                      - MONTH
                required:
                  - type
                  - name
                additionalProperties: false
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - metric
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  groupBy:
                    anyOf:
                      - type: string
                      - type: array
                        items:
                          type: string
                          minLength: 1
                      - nullable: true
                        type: string
                        enum:
                          - null
                  metricId:
                    type: string
                    description: >-
                      Saved Costory metric id from list_metrics metrics[].id.
                      This is the query identity — not list_metrics
                      `datasourceId` (that filter only returns groupBy
                      dimensions for telemetry).
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                  aggregator:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                    description: Aggregation over the bucket. Defaults to SUM.
                  reducer:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                  shiftAmount:
                    type: integer
                  shiftUnit:
                    type: string
                    enum:
                      - DAY
                      - WEEK
                      - MONTH
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                  rawMetric:
                    type: string
                  unitOverride:
                    type: string
                required:
                  - type
                  - metricId
                  - name
                additionalProperties: false
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - usage
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  groupBy:
                    anyOf:
                      - type: string
                      - type: array
                        items:
                          type: string
                          minLength: 1
                      - nullable: true
                        type: string
                        enum:
                          - null
                  metricId:
                    type: string
                    description: >-
                      Usage metric id (from suggest_usage_metrics). Distinct
                      from cost metricId and from list_metrics datasourceId.
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  filterCel:
                    type: string
                    nullable: true
                    description: >-
                      Optional scope filter as CEL (Common Expression Language).
                      Examples: cos_service_name in ["AmazonEC2"]; cos_provider
                      in ["AWS"] && cos_environment in ["prod"]. Label
                      dimensions use the cos_ prefix; native provider fields
                      omit it. Unlabelled/untagged resources have null values;
                      use == null to match them (e.g. cos_environment == null)
                      and != null to exclude them. Omit or pass empty string for
                      no filter.
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                  aggregator:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                    description: Aggregation over the bucket. Defaults to SUM.
                  reducer:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                  shiftAmount:
                    type: integer
                  shiftUnit:
                    type: string
                    enum:
                      - DAY
                      - WEEK
                      - MONTH
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                required:
                  - type
                  - metricId
                  - name
                additionalProperties: false
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - formula
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  formula:
                    type: string
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                  shiftAmount:
                    type: integer
                  shiftUnit:
                    type: string
                    enum:
                      - DAY
                      - WEEK
                      - MONTH
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                required:
                  - type
                  - formula
                  - name
                additionalProperties: false
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - budget
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  budgetId:
                    type: string
                  virtualDimensionValue:
                    type: string
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                required:
                  - type
                  - budgetId
                  - name
                additionalProperties: false
              - type: object
                properties:
                  type:
                    type: string
                    enum:
                      - externalMetric
                    description: >-
                      Required series discriminator — always set explicitly,
                      never omit. One of: "cost" | "metric" | "usage" |
                      "formula" | "budget" | "externalMetric".
                  integrationId:
                    type: string
                    minLength: 1
                    description: >-
                      External metric integration ID from
                      list_metrics(includeExternal: true).
                  metricName:
                    type: string
                    minLength: 1
                  aggregator:
                    type: string
                    enum:
                      - SUM
                      - AVG
                      - MAX
                      - MIN
                  groupByFields:
                    type: array
                    items:
                      type: string
                      minLength: 1
                    maxItems: 7
                    default: []
                  conditions:
                    type: string
                  dateColumn:
                    type: string
                    minLength: 1
                  metricColumn:
                    type: string
                    minLength: 1
                  gapFillingMethod:
                    type: string
                    enum:
                      - ZERO
                      - FORWARD_FILL
                      - LINEAR_INTERPOLATION
                      - SPREAD
                  rollingAggregation:
                    type: object
                    properties:
                      aggregator:
                        type: string
                        enum:
                          - SUM
                          - AVG
                          - MAX
                          - MIN
                      window:
                        type: object
                        properties:
                          preset:
                            type: string
                            enum:
                              - MONTH
                              - WEEK
                          relativeDays:
                            type: integer
                            minimum: 1
                    required:
                      - aggregator
                      - window
                  provider:
                    type: string
                    enum:
                      - tsuga
                      - bigquery
                      - datadog
                      - cloudwatch
                    default: tsuga
                    description: >-
                      External metric provider. Defaults to "tsuga" when omitted
                      for backward compatibility with existing Tsuga MCP
                      clients.
                  name:
                    type: string
                    pattern: ^[a-z]$
                    description: >-
                      Required single-letter query identifier (a, b, c…). Never
                      use a descriptive phrase here — put human labels in alias
                      instead. Formula queries reference other queries by this
                      letter (e.g. formula: "a / b").
                  alias:
                    type: string
                    minLength: 1
                    maxLength: 50
                    description: >-
                      Optional human-readable label (e.g. "Cost by environment",
                      "AWS spend"). Use name for the single letter required by
                      formulas; never put descriptive text in name.
                  chartType:
                    type: string
                    enum:
                      - BAR
                      - LINE
                      - AREA
                      - WATERFALL
                      - TABLE
                    description: >-
                      Explorer chart for this series: BAR, LINE, AREA,
                      WATERFALL, or TABLE. Omit to use LINE.
                required:
                  - type
                  - integrationId
                  - metricName
                  - aggregator
                  - name
                additionalProperties: false
            discriminator:
              propertyName: type
          minItems: 1
          maxItems: 26
        datePreset:
          type: string
          enum:
            - TRAILING_90_DAYS
            - TRAILING_30_DAYS
            - TRAILING_45_DAYS
            - TRAILING_7_DAYS
            - TRAILING_3_DAYS
            - TRAILING_14_WEEKS
            - MTD
            - QTD
            - YTD
            - LAST_WEEK
            - LAST_MONTH
            - LAST_6_MONTHS
            - LAST_12_MONTHS
            - LAST_4_YEARS
            - LAST_3_MONTHS
            - LAST_INVOICE_MONTH
        from:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        to:
          type: string
          pattern: ^\d{4}-\d{2}-\d{2}$
        aggBy:
          type: string
          enum:
            - Hour
            - Day
            - Week
            - Month
            - Period
          default: Month
        forecastDays:
          type: integer
          minimum: 0
        compare:
          type: object
          properties:
            enabled:
              type: boolean
              default: true
            from:
              type: string
              pattern: ^\d{4}-\d{2}-\d{2}$
            to:
              type: string
              pattern: ^\d{4}-\d{2}-\d{2}$
            chartType:
              type: string
              enum:
                - WATERFALL
                - TABLE
                - KPI_BREAKDOWN
              default: WATERFALL
          additionalProperties: false
        limit:
          type: integer
          minimum: 1
          maximum: 1000
        scopeId:
          type: string
          nullable: true
      required:
        - queries
      additionalProperties: false
    DiffTreeResponse:
      type: array
      items:
        type: object
        properties:
          dimensions:
            type: array
            items:
              type: object
              properties:
                key:
                  type: string
                value:
                  type: string
              required:
                - key
                - value
              additionalProperties: false
          cost:
            type: number
          previous_cost:
            type: number
          diff:
            type: number
        required:
          - dimensions
          - cost
          - previous_cost
          - diff
        additionalProperties: false
    InvalidQueryError:
      type: object
      properties:
        error:
          type: string
          enum:
            - INVALID_QUERY
        reason:
          type: string
        details:
          type: array
          items:
            type: object
            properties:
              path:
                type: array
                items:
                  anyOf:
                    - type: string
                    - type: number
              message:
                type: string
              code:
                type: string
            required:
              - path
              - message
              - code
            additionalProperties: false
      required:
        - error
      additionalProperties: false
    Unauthorized:
      type: object
      properties:
        error:
          type: string
          description: Unauthorized error message
      required:
        - error
    ScopeNotFoundOrForbiddenError:
      type: object
      properties:
        error:
          type: string
          enum:
            - SCOPE_NOT_FOUND_OR_FORBIDDEN
      required:
        - error
      additionalProperties: false
    ExternalMetricIntegrationNotFoundError:
      type: object
      properties:
        error:
          type: string
          enum:
            - EXTERNAL_METRIC_INTEGRATION_NOT_FOUND
      required:
        - error
      additionalProperties: false
    InternalServerError:
      type: object
      properties:
        error:
          type: string
          enum:
            - INTERNAL_SERVER_ERROR
      required:
        - error
      additionalProperties: false
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT or Clerk ak_* API key
      description: >-
        Send `Authorization: Bearer <credential>` using either a Clerk session
        JWT or a Clerk API key (`ak_*`). API keys may identify a user (`user_*`)
        or organization (`org_*`) principal and are generated in the Clerk
        Dashboard under API keys.

````