---
title: "List the calculated metrics"
method: POST
path: "/calculated-metrics/list"
tags: ["Calculated Metrics"]
---

# List the calculated metrics

`POST /calculated-metrics/list`

## Request

- Base URL: `https://api.reportingninja.com/v1`
- URL: `https://api.reportingninja.com/v1/calculated-metrics/list`
- Auth: HTTP bearer

Returns the calculated metrics of the account, each with the integration and the data view it belongs to and with the block of its kind: a formula, a metric aggregated over a period, or a metric read through a saved filter. A calculated metric can be read with /v1/fields and asked for in /v1/query; the definition of a widget does not take one.

## Request body

- CalculatedMetricsListRequest: All of them, or only the ones of one integration.
  - `integration_id` string: Only the entries of this integration. From /v1/integrations. Omit it for all of them.

## Response `200`

The call succeeded. This endpoint reports its errors with a real HTTP status, so a 200 always carries status=ok.

- CalculatedMetricsListResponse
  - `status` 'ok', required
  - `data` CalculatedMetricsListData, required: The calculated metrics of the account, ordered by name.
    - `calculated_metrics` CalculatedMetric[], required
      - `calculated_metric_key` string, nullable, required: The metric. Published by a read and never written: a body that carries it is accepted, ignored and named in a READ_ONLY_FIELD_IGNORED warning, so the object a read answers can be sent back as it is. It is null in ONE place: the preview of a dry run of a creation, where the row does not exist yet and so has no key.
      - `name` string, nullable, required
      - `display_name` string, nullable: The name shown on a widget that uses it, when it differs from the name.
      - `internal_notes` string, nullable: A note for the account's own staff.
      - `integration_id` string, nullable, required: The integration the metric belongs to, or null when the data source has no public id.
      - `integration` string: The name the product gives a data source with no public integration_id. Present only in that case. Published by a read and never written: a body that carries it is accepted, ignored and named in a READ_ONLY_FIELD_IGNORED warning, so the object a read answers can be sent back as it is.
      - `level` string, nullable, required: The data view the metric belongs to. Most metrics belong to none and are read as null; when the one they do belong to has no public name, level is null and not_expressible_reason says level_not_available.
      - `type` 'expression' | 'function' | 'filtered', nullable, required: Which of the three kinds it is.
      - `is_system_defined` boolean, required: Whether the metric is one the platform ships. Published by a read and never written: a body that carries it is accepted, ignored and named in a READ_ONLY_FIELD_IGNORED warning, so the object a read answers can be sent back as it is.
      - `expression` CalculatedMetricExpression, required: A metric written as a formula.
        - `format` 'none' | 'time' | 'currency' | 'percentage' | 'time_millis' | 'text', nullable, required: How the result is formatted. time_millis and text are two older values outside the four the editor offers, published as they are stored.
        - `formula` string[], required: The formula as a flat list of infix tokens: the metric ids as the definition stores them, normally the ones /v1/fields publishes, plus the operators + - * /, parentheses and literal numbers. A metric the product retired can still appear in an older formula.
        - `green_when_increases` boolean, required: Whether a rise of the metric is shown as a good thing.
      - `function` CalculatedMetricFunction, required: A metric aggregated over a period.
        - `metric` string, nullable, required: The metric being aggregated, named as /v1/fields names it.
        - `function` 'average' | 'min' | 'max', nullable, required
        - `time_period` 'day' | 'week' | 'month', nullable, required
      - `filtered` CalculatedMetricFiltered, required: A metric read through a saved filter.
        - `metric` string, nullable, required: The metric being read, named as /v1/fields names it.
        - `filter_key` string, nullable, required: The saved filter it is read through. From /v1/filters/list. It is published as it is stored and may name a filter that was deleted, which /v1/filters/get answers with 404.
      - `not_expressible_reason` 'source_not_available' | 'level_not_available' | 'unreadable', nullable, required: Why the definition is not published as it stands. With source_not_available and with unreadable the three blocks are null; with level_not_available only level is, because the id of a metric does not depend on the data view it is read in. Null when there is nothing to report. Published by a read and never written: a body that carries it is accepted, ignored and named in a READ_ONLY_FIELD_IGNORED warning, so the object a read answers can be sent back as it is.
      - `not_expressible_message` string, nullable: The same thing in a sentence. Published by a read and never written: a body that carries it is accepted, ignored and named in a READ_ONLY_FIELD_IGNORED warning, so the object a read answers can be sent back as it is.
    - `count` integer, required
  - `meta` Meta, required
    - `request_id` string, required: Id of this request, useful when reporting an incident.
    - `timestamp` string, date-time, required: When the answer was built, in UTC.

## Other responses

- `400`: The request was refused before anything was written. INVALID_REQUEST covers the framework refusals of every endpoint (the Content-Type is not application/json, the body could not be read, the body is not valid JSON). The report endpoints add their own: VALIDATION_FAILED with details.problems, UNKNOWN_PARAM with the path of the field the endpoint does not read, and the single-field refusals MISSING_REQUIRED_FIELD, INVALID_VALUE and APPEND_NOT_ALLOWED. The description of each operation lists the ones it emits. Everything else a body can get wrong arrives as an entry of details.problems rather than as the code of the envelope.
- `401`: Invalid or missing Bearer token.
- `413`: The request body is over 1 MB. The cap is applied before authentication, so this answer is refused without the key being read, and it carries the usual error envelope.
- `429`: A budget was spent. RATE_LIMITED is the per-key read budget (300/minute, 5000/day) or the per-account write budget (60/minute, 1000/day). EMAIL_QUOTA_REACHED is the separate budget of 50 calls per account per day that send email, and its Retry-After points at the next UTC midnight. The Retry-After header gives the seconds until the more restrictive window resets. The X-RateLimit-* headers report the read budget, except on the 429 of a write, where they report the write budget.
- `500`: Internal server error.

---

[API](https://skmtc.dev/reportingninja/apis/reporting-ninja-api.md) · [All operations](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/llms.txt) · [OpenAPI document](https://skmtc.dev/reportingninja/apis/reporting-ninja-api/revisions/13876c71be34?raw)
