---
title: "List Custom Metrics"
method: GET
path: "/api/v1/custom-metrics"
tags: ["custom-metrics"]
---

# List Custom Metrics

`GET /api/v1/custom-metrics`

List custom metrics with optional filters.

**The three applicability filters exist so a picker can stop offering
metrics that cannot produce a result.** Both re-evaluate fetchers called
this with `{}` and filtered on `status === "active"` alone, so the phone
page's menu listed booking-only and formula metrics. Choosing one succeeded
*silently and wrote nothing*: the job enqueued, `enqueued_count` counted the
logs truthfully, and the per-log gate `metric_applies_to_log` dropped every
one of them.

Filtered server-side rather than in the picker, because there are four
consumers and client-side filtering is how they drift — `GET /log-columns`
already made this argument and has been filtering by `applies_to_*` since it
shipped.

## Query parameters

- `search` string, nullable
- `response_type` 'pass_fail' | 'yes_no' | 'numeric_score' | 'categorical' | 'text' | 'json'
- `tag` string, nullable
- `linked_agent_id` string, nullable
- `status` 'active' | 'archived'
- `applies_to_channel` 'voice' | 'text' | 'email' | 'booking', nullable — Only metrics that can score this subject. A voice-only metric on a text log renders dashes at best and, offered in a re-evaluate menu, enqueues a job that writes nothing.
- `compute_type` 'model' | 'formula'
- `has_active_revision` boolean, nullable — Only metrics with (or without) an active revision. A metric with none has no prompt to run, so re-scoring it is a no-op.
- `page` integer
- `page_size` integer

## Response `200`

Successful Response

- CustomMetricListResponse — Paginated list of custom metrics.
  - `items` CustomMetricRead[], required
    - `id` string, uuid, required
    - `name` string, required
    - `description` string, nullable, required
    - `category` string, nullable, required
    - `source_template_key` string, nullable, required
    - `compute_type` 'model' | 'formula', required
    - `response_type` 'pass_fail' | 'yes_no' | 'numeric_score' | 'categorical' | 'text' | 'json', required
    - `status` 'active' | 'archived', required
    - `tags` string[], required
    - `active_revision_id` string, uuid, nullable, required
    - `linked_agent_ids` string[], required
    - `applies_to_voice` boolean, required
    - `applies_to_text` boolean, required
    - `applies_to_email` boolean, required
    - `applies_to_booking` boolean, required
    - `created_at` string, date-time, required
    - `updated_at` string, date-time, required
    - `is_booking_intent_definition` boolean, required — True when this metric is the tenant's Booking Intent classifier. Derived from the tag so the frontend never hardcodes the magic string. Set/cleared only via the dedicated designation endpoint.
  - `total_count` integer, required

## Other responses

- `401` — Authentication required
- `422` — Validation Error

---

[API](https://skmtc.dev/getanana/apis/cleon-api.md) · [All operations](https://skmtc.dev/getanana/apis/cleon-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/getanana/cleon-api/revisions/c0f54348e251/schema)
