---
title: "Workflows metrics"
method: POST
path: "/api/workflows/metrics"
tags: ["workflows"]
---

# Workflows metrics

`POST /api/workflows/metrics`

## Request

- Base URL: `https://beta.getsales.io/playtables/v1`
- URL: `https://beta.getsales.io/playtables/v1/api/workflows/metrics`
- Auth: HTTP bearer and API key in header `Team-SID`

Campaign funnel over the filtered workflows: enrolled_in_period / replied_in_period / completed_in_period count record clocks (enrollment / reply / completion) inside half-open [from,to) - NOT workflows.created_at; active_records_now is point-in-time. aggregated.counts = free workflow-row counts by status. group_by:"status" adds groups[] with counts + metrics per value. Per-step funnel → workflow-records metrics with group_by:current_step_id.

Contract:
- MCP tool `get_workflows_metrics`, registry package `mcp.playtables/workflows`, mount `playtables.workflows`.
- Operation `metrics`, response envelope `metrics`.
- Flags: read only.

## Request body

- GetWorkflowsMetricsRequest: Request body of `get_workflows_metrics`.
  - `filter` object: Scopes the rows the metrics are computed over: the search filter operators. Omit for all rows.
    - `playtable_sid` object: The home playtable.
      - `eq` string
      - `in` string[]
    - `sid` object: Prefix-validated wf_wf_ sid(s).
      - `eq` string: Workflow sid (wf_wf_…).
      - `in` string[]
    - `status` object: Default UI scope excludes archived client-side.
      - `eq` 'draft' | 'active' | 'paused' | 'archived'
      - `ne` 'draft' | 'active' | 'paused' | 'archived'
      - `in` string[]
      - `nin` string[]
    - `published_version_sid` object: is_null:true = never published.
      - `eq` string
      - `is_null` boolean
    - `agent_sid` object: The AI SDR the workflow picked (ub_ag_…); is_null:true = the workflows on their table's pick.
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `q` string: Free text over name + description (MySQL LIKE, prefix/infix).
    - `created_at` object: ISO 8601 range; combine bounds in one object.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
    - `updated_at` object: "Recently edited" scans; ISO 8601 range.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
    - `deleted_at` object: Default scope is { is_null: true } (live rows).
      - `gte` string
      - `lte` string
      - `is_null` boolean
  - `period` object, required: Required. Bounds the JOINED record clocks (enrollment / reply / completion), not workflows.created_at; filter scopes workflow rows.
    - `from` string, required: ISO 8601 UTC window start (inclusive).
    - `to` string, required: ISO 8601 UTC window end (exclusive); must be >= from.
  - `group_by` 'status': Single axis - adds groups[] with per-value counts + metrics. Cap 500 groups.

## Response `200`

`metrics` success envelope.

- GetWorkflowsMetricsResponse
  - `success` true, required
  - `operation` 'metrics', required
  - `metrics` object, required
    - `filter` union: Echo of the request WorkflowSearchFilter (PHP empty map serialises as []).
      - object
      - unknown[]
        - unknown
    - `period` object, required
      - `from` string, required
      - `to` string, required
    - `aggregated` object, required
      - `counts` object, required
        - `total_count` integer, required: Workflow rows matching the filter scope.
        - `groups` object, required
          - `status` union, required: Campaign distribution by status (feeds list badges); absent key = zero (PHP empty map serialises as []).
            - object
              - …
            - unknown[]
              - …
      - `metrics` object, required
        - `enrolled_in_period` integer, required: Records created within [period.from, period.to).
        - `replied_in_period` integer, required: Records whose reply clock falls in the period.
        - `completed_in_period` integer, required: Records that reached a terminal completed state in the period.
        - `active_records_now` integer, required: Non-terminal records; point-in-time snapshot, period-independent.
    - `groups` object[]: Present only when group_by was set - one entry per axis value. Cap 500 groups → 422.
      - `key` string, required: Value of the group_by axis (a WorkflowStatusEnum value).
      - `counts` object, required
        - `total_count` integer, required: Workflow rows matching the filter scope.
        - `groups` object, required
          - `status` union, required: Campaign distribution by status (feeds list badges); absent key = zero (PHP empty map serialises as []).
            - object
              - …
            - unknown[]
              - …
      - `metrics` object, required
        - `enrolled_in_period` integer, required: Records created within [period.from, period.to).
        - `replied_in_period` integer, required: Records whose reply clock falls in the period.
        - `completed_in_period` integer, required: Records that reached a terminal completed state in the period.
        - `active_records_now` integer, required: Non-terminal records; point-in-time snapshot, period-independent.
  - `applied_filters` object
  - `meta` object, required
    - `trace_id` string, required: UUID v7; same 128-bit value as the X-Trace-Id header.
    - `span_id` string, required: 16 hex chars, root span of this request.
    - `timestamp` string, required: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
    - `duration_ms` integer, required: Server-side wall clock.
    - `team_sid` string, nullable: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends.
    - `actor_type` string, nullable: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends.

## Other responses

- `4XX`: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented.
- `5XX`: MCP error envelope with `error.code` internal_error or service_unavailable.

---

[API](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables.md) - [All operations](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/llms.txt) - [OpenAPI document](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/revisions/aa394506515d?raw)
