---
title: "Request Analytics Custom Analytics"
method: POST
path: "/api/public/v2/requests/analytics/custom-analytics"
tags: ["tracking"]
---

# Request Analytics Custom Analytics

`POST /api/public/v2/requests/analytics/custom-analytics`

## Request body

- RequestAnalyticsCustomAnalyticsQuery — Request body for POST /api/public/v2/requests/analytics/custom-analytics. Inherits all filter fields from RequestLogQuery and adds `customCharts`.
  - `filter_group` StructuredFilterGroup — A group of filters combined with AND or OR logic. Can be nested recursively.
    - `logic` 'AND' | 'OR' — How to combine the filters in this group.
    - `filters` union[], required — List of filters or nested filter groups.
      - union
        - StructuredFilter — A single filter condition on a request log field.
          - `field` 'pl_id' | 'prompt_id' | 'engine' | 'provider_type' | 'input_text' | 'output_text' | 'prompt_version_number' | 'input_tokens' | 'output_tokens' | 'cost' | 'latency_ms' | 'request_start_time' | 'request_end_time' | 'status' | 'is_json' | 'is_tool_call' | 'is_plain_text' | 'tags' | 'metadata_keys' | 'metadata' | 'tool_names' | 'output' | 'output_keys' | 'input_variables' | 'input_variable_keys' | 'user_intent' | 'agent_intent', required — The request log field to filter on. Intent fields are virtual fields that classify request content by tone and do not require any additional logging configuration. `user_intent` classifies the user's message; valid values: `frustrated`, `satisfied`, `curious`. `agent_intent` classifies the agent's response; valid values: `apologetic`, `refusal`, `uncertain`. Intent fields support operators: `is`, `is_not`, `in`, `not_in`.
          - `operator` 'is' | 'is_not' | 'in' | 'not_in' | 'contains' | 'not_contains' | 'starts_with' | 'ends_with' | 'eq' | 'neq' | 'gt' | 'gte' | 'lt' | 'lte' | 'between' | 'before' | 'after' | 'is_true' | 'is_false' | 'is_empty' | 'is_not_empty' | 'is_null' | 'is_not_null' | 'key_equals' | 'key_not_equals' | 'key_contains', required — The comparison operator.
          - `value` union — The value to compare against. Type depends on the field and operator.
            - string
            - number
            - boolean
          - `nested_key` string, nullable — Required for nested fields (metadata, output, input_variables). Specifies which key within the nested object to filter on.
        - StructuredFilterGroup — recursive
  - `q` string, nullable — Free-text search query.
  - `sort_by` 'request_start_time' | 'input_tokens' | 'output_tokens' | 'cost' | 'latency_ms' | 'status', nullable — Accepted for compatibility; does not affect aggregated output.
  - `sort_order` 'asc' | 'desc', nullable
  - `customCharts` CustomAnalyticsSpec[], required — One or more chart definitions to compute. Chart ids must be unique.
    - `id` string, required — Stable identifier for this chart in the response (alphanumeric, hyphens, underscores; max 64 chars). Must be unique within the request.
    - `title` string, nullable — Optional display title (max 200 chars). Defaults to id.
    - `chartType` 'bar' | 'line' | 'area', required — Chart visualization type. Overall aggregate charts (no timeSeries, no groupByField) must use `bar`.
    - `metric` 'count' | 'sum' | 'avg' | 'min' | 'max' | 'percentile', nullable — Aggregation function. Omit when using `series` (multi-series mode).
    - `metricField` 'input_tokens' | 'output_tokens' | 'cost' | 'latency_ms' | 'prompt_version_number' | 'turn_count' | 'tool_call_count' | 'cached_tokens' | 'thinking_tokens', nullable — Numeric field to aggregate. Required unless metric is `count` or using multi-series mode.
    - `percentile` number, nullable — Required when metric is `percentile`.
    - `series` CustomAnalyticsSeriesSpec[], nullable — Multi-series mode: define two or more series. Omit metric/metricField/percentile when using this.
      - `key` string, required — Unique identifier for this series within the chart (alphanumeric, hyphens, underscores; max 64 chars).
      - `label` string, required — Human-readable series label shown in chart legends (max 120 chars).
      - `metric` 'sum' | 'avg' | 'min' | 'max' | 'percentile', required — Aggregation function for this series.
      - `metricField` 'input_tokens' | 'output_tokens' | 'cost' | 'latency_ms' | 'prompt_version_number' | 'turn_count' | 'tool_call_count' | 'cached_tokens' | 'thinking_tokens', required — Numeric field to aggregate.
      - `percentile` number, nullable — Required when metric is `percentile`; omit otherwise.
    - `derivedInsights` DerivedRatioInsightSpec[], nullable — Ratio insights computed from series totals. Only valid in multi-series mode.
      - `type` 'ratio'
      - `label` string, required — Label shown for this insight (max 200 chars).
      - `numeratorSeriesKey` string, required — Key of the numerator series (must match a series key in the chart).
      - `denominatorSeriesKey` string, required — Key of the denominator series (must match a series key in the chart).
    - `groupByField` 'engine' | 'provider_type' | 'prompt_id' | 'prompt_version_number' | 'status' | 'error_type' | 'tags' | 'metadata_keys' | 'output_keys' | 'input_variable_keys' | 'tool_names', nullable — Break results down by this request log field. Cannot be combined with groupByMetadataKey.
    - `groupByMetadataKey` string, nullable — Break results down by the values of this metadata key. Cannot be combined with groupByField.
    - `timeSeries` boolean — When true, bucket results over time (bucket size chosen automatically from the filter range).
    - `limit` integer — Maximum number of group-by buckets to return.

## Response `200`

Custom chart results in the order requested.

- RequestAnalyticsCustomAnalyticsResponse
  - `success` true, required
  - `customCharts` CustomAnalyticsResult[], required — Results in the same order as the input `customCharts` array.
    - `id` string — Echoes the chart id from the request.
    - `title` string — Chart title (echoed from request, or defaults to id).
    - `chartType` 'bar' | 'line' | 'area'
    - `series` CustomAnalyticsSeriesMeta[] — Series descriptors (one entry per series). For single-metric charts the only entry has key `value`.
      - `key` string — Series key (matches keys in each data row).
      - `label` string — Human-readable label.
      - `unit` 'count' | 'tokens' | 'currency' | 'duration_seconds' | 'number' — Unit hint for rendering axes.
    - `data` object[] — Rows of chart data. Each row has a `label` string and one numeric key per series. Time-series rows also include `bucketKey` (ISO date string).
    - `derivedInsights` DerivedRatioInsightResult[], nullable — Computed ratio insights (multi-series charts only).
      - `type` 'ratio'
      - `label` string
      - `numeratorSeriesKey` string
      - `denominatorSeriesKey` string
      - `value` number — Ratio of numerator total to denominator total.

## Other responses

- `400` — Invalid chart spec or unsupported filter.
- `401` — Unauthorized - missing or invalid API key.
- `403` — Forbidden - API key does not have access to the requested resource.
- `422` — Validation error - request parameters or body are invalid.

---

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