---
title: "Credit ledger entries metrics"
method: POST
path: "/api/credit-ledger-entries/metrics"
tags: ["credit_ledger_entries"]
---

# Credit ledger entries metrics

`POST /api/credit-ledger-entries/metrics`

## Request

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

Credit spend aggregates - THE credits-usage surface: spent (Σ cost) + paid_calls_count over a REQUIRED period (half-open [from,to) on created_at - created_at filter ops ignored), group_by playtable_field_sid | tool_sid | created_date | playtable_sid. Use for: monthly enrichment cost, spend by field/tool/day/table, what run X cost (filter.run_sid). Local receipts - the gtm-api ledger is authoritative billing. Pre-run price → playtable-runs estimate; balance → gs.service.id; line items → search.

Contract:
- MCP tool `get_credit_ledger_entries_metrics`, registry package `mcp.playtables/credit_ledger_entries`, mount `id.billing`.
- Operation `metrics`, response envelope `metrics`.
- Flags: read only.

## Request body

- GetCreditLedgerEntriesMetricsRequest: Request body of `get_credit_ledger_entries_metrics`.
  - `filter` object: Scopes the rows the metrics are computed over: the search filter operators. Omit for all rows.
    - `sid` object: Receipt sid(s), cl_en_ prefix (prefix-validated).
      - `eq` string: Credit ledger entry (receipt) sid (cl_en_…).
      - `in` string[]
    - `playtable_sid` object: Per-table spend scope (pt_tb_…).
      - `eq` string
      - `in` string[]
    - `object_type` object: Residual inside scope: people | company.
      - `eq` 'people' | 'company'
    - `object_sid` object: cr_pp_… / cr_co_… (mixed prefixes - not prefix-pinned); cell drill-down with playtable_field_sid.
      - `eq` string
      - `in` string[]
    - `playtable_field_sid` object: Per-field spend scope (pt_fd_…).
      - `eq` string
      - `in` string[]
    - `run_sid` object: What a run cost (pt_rn_…); is_null:true = non-run spend (empty in v1 - the cell-waterfall writer always carries a run).
      - `eq` string
      - `in` string[]
      - `is_null` boolean
    - `tool_sid` object: Spend through one gtm-api tool (external sid, opaque).
      - `eq` string
      - `in` string[]
    - `created_by_actor_sid` object: "What did this person spend" - projected from created_by.actor_sid.
      - `eq` string
    - `idempotency_key` object: Support/debug: locate one exact charge.
      - `eq` string
    - `created_at` object: ISO 8601 range - day windows; combine bounds in one object. Ignored on metrics - period owns the window.
      - `gte` string
      - `lte` string
      - `gt` string
      - `lt` string
  - `period` object, required: Required. Half-open [from, to) window on created_at (the receipt clock) - created_at operators inside filter are silently ignored.
    - `from` string, required: ISO 8601 UTC window start (inclusive).
    - `to` string, required: ISO 8601 UTC window end (exclusive); must be >= from.
  - `group_by` 'playtable_sid' | 'playtable_field_sid' | 'tool_sid' | 'created_date': Single spend axis: playtable_sid | playtable_field_sid | tool_sid | created_date - adds groups[] with per-value counts + metrics. Cap 500 groups (§4.17).

## Response `200`

`metrics` success envelope.

- GetCreditLedgerEntriesMetricsResponse
  - `success` true, required
  - `operation` 'metrics', required
  - `metrics` object, required
    - `filter` union: Echo of the request CreditLedgerEntrySearchFilter (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: Receipts (paid calls) matching the filter - full filter scope, not the page.
        - `groups` object, required: One axis per CreditLedgerEntryGroupableFieldsEnum value (§4.17). Values are CALL COUNTS - credit sums live in the metrics tool. PHP empty map serialises as [].
          - `playtable_sid` union, required: Flat {pt_tb_ sid: call count} - which table is spending.
            - object
            - unknown[]
              - …
          - `playtable_field_sid` union, required: Flat {pt_fd_ sid: call count} - call concentration by field.
            - object
            - unknown[]
              - …
          - `tool_sid` union, required: Flat {tool_sid: call count} - calls through each gtm-api tool.
            - object
            - unknown[]
              - …
          - `created_date` union, required: Flat {'YYYY-MM-DD': call count} - calls per UTC day (≤ 366 values under 12-month retention).
            - object
            - unknown[]
              - …
      - `metrics` object, required
        - `spent` number, required: Σ cost (credits, decimal(12,4)) over receipts in [from, to) at filter scope.
        - `paid_calls_count` integer, required: Receipts (paid calls) in [from, to) - period-bound, unlike counts.total_count (filter scope).
    - `groups` object[]: Present only when group_by was set - one entry per axis value in scope.
      - `key` string, nullable, required: Value of the group_by axis: a pt_tb_ / pt_fd_ sid, a gtm-api tool_sid, or a 'YYYY-MM-DD' date; null = rows without a value on the axis.
      - `counts` object, required
        - `total_count` integer, required: Receipts (paid calls) matching the filter - full filter scope, not the page.
        - `groups` object, required: One axis per CreditLedgerEntryGroupableFieldsEnum value (§4.17). Values are CALL COUNTS - credit sums live in the metrics tool. PHP empty map serialises as [].
          - `playtable_sid` union, required: Flat {pt_tb_ sid: call count} - which table is spending.
            - object
            - unknown[]
              - …
          - `playtable_field_sid` union, required: Flat {pt_fd_ sid: call count} - call concentration by field.
            - object
            - unknown[]
              - …
          - `tool_sid` union, required: Flat {tool_sid: call count} - calls through each gtm-api tool.
            - object
            - unknown[]
              - …
          - `created_date` union, required: Flat {'YYYY-MM-DD': call count} - calls per UTC day (≤ 366 values under 12-month retention).
            - object
            - unknown[]
              - …
      - `metrics` object, required
        - `spent` number, required: Σ cost (credits, decimal(12,4)) over receipts in [from, to) at filter scope.
        - `paid_calls_count` integer, required: Receipts (paid calls) in [from, to) - period-bound, unlike counts.total_count (filter scope).
  - `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)
