---
title: "POST /v1/reports"
method: POST
path: "/v1/reports"
tags: ["reports"]
---

# POST /v1/reports

`POST /v1/reports`

## Request

- Base URL: `https://help.steep.app` (the document declares no server; this is the origin it was published from)
- URL: `https://help.steep.app/v1/reports`
- Auth: none declared

Create a new report: a saved, shareable document that persists in the workspace as a lasting artifact to revisit or share. Build its body from the `blocks` field. Returns the new report's `id`, title and `link` to open it in the Steep app.

## Request body

- object
  - `title` string, required: Report title. Concise and descriptive.
  - `blocks` union[], required: Ordered list of blocks that make up the report body, in document order. Chart, table and big-number blocks reference metric `id`s from list metrics, search metrics, or get metric by `id`.
    - union
      - object
        - `type` string, required
        - `properties` object, required
          - `body` string, required: Block content as GitHub-flavored Markdown — headings, paragraphs, lists, bold/italic, links, inline code, blockquotes, code blocks, and GFM pipe tables. Use tables for small comparisons; prefer chart blocks for trends over time. Converted to HTML before storage.
      - object: A chart visualizing a metric.
        - `type` string, required
        - `properties` object, required
          - `metricId` string, required: Metric ID to visualize.
          - `sliceId` string: Optional slice/segment ID.
          - `timeGrainMode` union, required: Either an explicit grain, or 'auto' to let the system choose.
            - 'daily' | 'weekly' | 'monthly' | 'quarterly' | 'yearly': Granularity used to aggregate a time series.
            - string
          - `dimensionSettings` object: Breakdown and filter configuration.
            - `breakdown` string: Dimension ID used for breakdown. Required for rank charts.
            - `filters` object, required: Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.
          - `targetName` string: When the user asks for targets, goals, or a target line: set this to the exact target series name from get-metric-targets (e.g. '2025 target', 'Forecast'). This draws the goal line.
          - `metrics` object[]: Add one or more other, different metrics to compare (e.g. revenue vs costs). Do not add the same metric.
            - `metricId` string, required: Metric ID for the comparison series.
            - `sliceId` unknown, required
            - `applyFilters` boolean, required: Whether to apply the chart's dimension filters to this series.
            - `yAxis` 'left' | 'right', required: Which Y-axis this comparison series should use.
            - `vizType` 'line' | 'bar', required: How to render the comparison series.
          - `compares` string[]: Same-metric time comparisons (e.g. lag-1y, year-over-year for vs last year) or moving averages. last-period and x-over-x work when the user asks about a standard rolling period (last week, last month, last year, last 2 years, etc.). Do NOT use last-period or x-over-x when the user specifies an arbitrary explicit date range like 'Feb 2025 to Jul 2025' — the comparison will be silently ignored. For such ranges, use lag-1y or year-over-year instead, or omit functions and note the limitation in text.
          - `cumulative` boolean, required: Show a running total over time. Only valid on a line or bar chart, and only when the metric's `cumulative` hint is `built-in` — for `expanding-window`/`already-cumulative`/`unsupported` metrics, leave this false.
          - `bypassReportFilters` boolean: Ignore the report's own filters and time period for this chart, so it keeps the dates and filters set here. Only set this when the request asks for a chart that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.
          - `title` string: Optional chart title to display above the visualization.
          - `breakdownSettings` object
            - `sortBy` 'value' | 'name': How to sort breakdown items.
            - `sortDirection` 'asc' | 'desc': Sort direction.
            - `hideOther` boolean: Whether to hide the aggregated 'Other' row.
            - `show100PercentBars` boolean: Show bars as percentages (only relevant for some charts).
          - `showValues` 'none' | 'main-metric' | 'all', required: Value labels visibility. Displayed above the data points or bars.
          - `pivotTable` object: Pivot table configuration (rows/cols and rendering options).
            - `rows` union: Axis selection for pivot tables (rows/cols).
              - …
            - `cols` union: Axis selection for pivot tables (rows/cols).
              - …
            - `tableStyle` 'values-and-colors' | 'colors' | 'values', required: How to render each cell (values, colors, or both).
            - `totalsStyle` 'none' | 'rows-and-columns' | 'columns' | 'rows', required: Whether to show row/column totals.
            - `colorScheme` union, required: Heatmap color palette.
              - …
            - `colorSchemeFlipped` boolean, required: Invert the heatmap mapping (high values become low colors).
            - `colorThresholds` object: Optional thresholds to control heatmap scaling.
              - …
          - `cohortsTable` object: Cohorts table configuration.
            - `cohortId` string: Cohort definition identifier.
            - `cohortTimeGrain` union, required: Time grain used to bucket cohorts.
              - …
            - `deltaTimeGrain` union, required: Time grain used for the delta/age axis.
              - …
            - `tableStyle` 'values-and-colors' | 'colors' | 'values', required: How to render each cell (values, colors, or both).
            - `colorScheme` union, required: Heatmap color palette.
              - …
            - `colorSchemeFlipped` boolean, required: Invert the heatmap mapping (high values become low colors).
            - `colorThresholds` object: Optional thresholds to control heatmap scaling.
              - …
          - `chartType` 'line' | 'bar' | 'rank' | 'pivot-table' | 'cohorts-table', required: Visualization type: line/bar for trends over time, rank for top/bottom categories, pivot-table for cross-tab breakdowns, cohorts-table for retention/behavior cohorts. When breaking down an existing chart by a dimension, use the same chart type as the previously shown chart unless the user explicitly requests a different type.
          - `fromDate` string, date, required
          - `toDate` string, date, required
      - object: Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail.
        - `type` string, required
        - `properties` object, required
          - `variant` 'metrics' | 'breakdown', required: Layout variant: 'metrics' shows one tile per selected metric/slice; 'breakdown' shows one tile per value of a dimension for a single metric.
          - `metricSliceIds` object[], required: Metrics to show, one tile each. The breakdown variant uses exactly one entry.
            - `metricId` string, required: Metric ID for this tile.
            - `sliceId` unknown, required
          - `breakdownDimensionId` string: Dimension ID to break the single metric down by. Required for the breakdown variant; unused otherwise.
          - `filters` object: Record of dimension identifier -> selected values. Key each filter by the dimension's `identifier` (its column name, e.g. `workspace_name`), NOT its opaque `id` (e.g. `-ID-FExoC9XG`). Values must be copied exactly as returned by the dimension lookup tool (case-sensitive). Never invent, infer, or modify values.
          - `compare` 'lag-1y' | 'last-period': Comparison shown as a delta on each tile: lag-1y compares to the same period last year; last-period compares to the previous period of equal length. last-period only works for standard periods — it is rejected for arbitrary custom date ranges, so use lag-1y there.
          - `bypassReportFilters` boolean: Ignore the report's own filters and time period for these tiles, so they keep the dates and filters set here. Only set this when the request asks for tiles that stay outside the report's filters — an all-up total shown next to filtered breakdowns, say.
          - `title` string: Optional title displayed above the tiles.
          - `breakdownSettings` object
            - `sortBy` 'value' | 'name': How to sort breakdown tiles.
            - `sortDirection` 'asc' | 'desc': Sort direction.
            - `hideOther` boolean: Whether to hide the aggregated 'Other' tile.
            - `show100PercentBars` boolean: Not rendered by big numbers; carried for type parity.
          - `fromDate` string, date, required
          - `toDate` string, date, required
      - object: A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends.
        - `type` string, required
        - `properties` object, required
          - `title` string: Optional title shown above the table.
          - `bypassReportFilters` boolean: Ignore the report's own filters and time period for this table, so it keeps the dates and filters set here. Only set this when the request asks for a table that stays outside the report's filters — an all-up total shown next to filtered breakdowns, say.
          - `fullWidth` boolean
          - `fixedHeight` boolean
          - `metricSliceIds` object[], required: One or more metrics to show as columns.
            - `metricId` string, required: Metric ID — from ListMetrics / SearchMetrics.
            - `sliceId` string: Optional slice/segment ID.
            - `props` object: Optional per-metric column config (time comparisons).
              - …
          - `fromDate` string, date, required
          - `toDate` string, date, required
          - `layout` object, required: How the table lays its values out: which breakdowns and the metrics sit on rows and on columns, outermost level first, plus grouping, sorting and per-dimension limits. The same shape a report read returns, so a table you were shown can be written back as-is. Defaults to the metrics down the side and one value column: add a temporal level to show a column per period, a categorical one to break the values down by a dimension.
            - `rows` union[], required: Row levels, outermost first.
              - …
            - `columns` union[], required: Column levels, outermost first.
              - …
            - `grouping` object
              - …
            - `measures` object
              - …
            - `sorting` object[]: Ordered: the first rule is the primary sort, later ones break ties. A 'labels' rule orders a level by its own labels (`levelKey` is the dimension identifier or time grain), with `pinned` values first; a 'values' rule orders an axis by the cell values under one header on the other axis, the Total row or column included (a path ending in `{ kind: 'total' }`, which needs `grouping.showTotals`).
              - …
      - object: A horizontal divider that separates sections of the report. Carries no content — use between groups of blocks to break up a long report.
        - `type` string, required
      - object: A layout block that arranges 2–4 content blocks side by side as equal-width columns. Children must be content blocks (text, chart, big-number) — layout blocks cannot nest. Use for comparisons or related charts that read well next to each other.
        - `type` string, required
        - `children` union[], required: The 2–4 content blocks rendered as equal-width columns, left to right.
          - union
            - object
              - …
            - object: A chart visualizing a metric.
              - …
            - object: Headline KPI tiles — one large value per metric (variant 'metrics') or per dimension value (variant 'breakdown', exactly one metricSliceIds entry plus breakdownDimensionId set to a categorical dimension of that metric). Use for key-metrics-at-a-glance sections, typically before charts add detail.
              - …
            - object: A data table of one or more metrics as columns, with rows broken down by a categorical dimension or over time. Use when exact values matter or for side-by-side metric comparison; prefer chart blocks for trends.
              - …

## Response `200`

Response for status 200

- object
  - `id` string, required: Unique resource ID (opaque).
  - `title` string, required
  - `link` string, required: Link to the report in the Steep app.

## Other responses

- `401`: Response for status 401
- `403`: Response for status 403
- `422`: Response for status 422
- `429`: Response for status 429
- `500`: Response for status 500

---

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