Skip to main content
POST
/
api
/
public
/
v2
/
requests
/
analytics
/
custom-analytics
curl --request POST \
  --url https://api.promptlayer.com/api/public/v2/requests/analytics/custom-analytics \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: <api-key>' \
  --data '
{
  "filter_group": {
    "logic": "AND",
    "filters": [
      {
        "field": "request_start_time",
        "operator": "between",
        "value": [
          "2025-06-01T00:00:00Z",
          "2025-06-08T00:00:00Z"
        ]
      }
    ]
  },
  "customCharts": [
    {
      "id": "cost_by_model",
      "title": "Cost by Model",
      "chartType": "bar",
      "metric": "sum",
      "metricField": "cost",
      "groupByField": "engine",
      "limit": 10
    }
  ]
}
'
{
  "success": true,
  "customCharts": [
    {
      "id": "cost_by_model",
      "title": "Cost by Model",
      "chartType": "bar",
      "series": [
        {
          "key": "value",
          "label": "Cost",
          "unit": "currency"
        }
      ],
      "data": [
        {
          "label": "gpt-4o",
          "value": 8.42
        },
        {
          "label": "claude-sonnet-4-6",
          "value": 3.91
        }
      ]
    }
  ]
}
Run custom aggregations over your request logs. Define what to measure and how to slice it; the API returns structured data you can use however you want — feed it into a chart, run analysis on it, pipe it into a dashboard, or process it programmatically. Each query in the customCharts array specifies a metric and optionally a breakdown dimension or time bucketing:
ShapeFields required
Single aggregatemetric (and metricField unless metric is count)
Grouped breakdownAdd groupByField or groupByMetadataKey
Over timeAdd timeSeries: true
Multiple metrics at onceReplace metric/metricField with a series array

Metrics

metric controls the aggregation function:
ValueDescription
countNumber of matching requests (no metricField needed)
sumTotal of a numeric field
avgAverage of a numeric field
minMinimum value
maxMaximum value
percentileArbitrary percentile — requires percentile (0–100)

Supported metric fields (metricField)

input_tokens, output_tokens, cost, latency_ms, prompt_version_number, turn_count, tool_call_count, cached_tokens, thinking_tokens
Latency values are returned in seconds (converted from milliseconds internally).

Group-by fields (groupByField)

engine, provider_type, prompt_id, prompt_version_number, status, error_type, tags, metadata_keys, output_keys, input_variable_keys, tool_names Use groupByMetadataKey instead to break down by values of a specific metadata key (e.g. "environment" or "user_id").

Filters

All filter fields from Search Request Logs are supported (filter_group, q, sort_by, sort_order). Filters are applied before aggregation.

Response shape

Each entry in the response customCharts array contains:
  • id — echoes the id you sent
  • series — array of series descriptors: { key, label, unit } — describes what each numeric key in the data rows represents
  • data — array of rows, each with a label and one numeric key per series. Time-bucketed rows also include bucketKey (ISO date string).
  • derivedInsights — (multi-metric only) pre-computed ratio summaries
chartType and title are also echoed back but are optional hints — use them if you’re rendering a chart, ignore them if you’re just processing the numbers.

Behavior Notes

  • sort_by / sort_order are accepted for compatibility but do not affect aggregated output.
  • Overall aggregates (no timeSeries, no groupByField) return a single row with label: "Overall".
  • Multi-metric grouped time-series is not supported — use multiple single-metric queries instead.
  • series keys must be unique within a query; id values must be unique within the request.

Authorizations

X-API-KEY
string
header
required

Body

application/json

Request body for POST /api/public/v2/requests/analytics/custom-analytics. Inherits all filter fields from RequestLogQuery and adds customCharts.

customCharts
CustomAnalyticsSpec · object[]
required

One or more chart definitions to compute. Chart ids must be unique.

Minimum array length: 1
filter_group
StructuredFilterGroup · object

Nested filter group with AND/OR logic.

q
string | null

Free-text search query.

sort_by
enum<string> | null

Accepted for compatibility; does not affect aggregated output.

Available options:
request_start_time,
input_tokens,
output_tokens,
cost,
latency_ms,
status
sort_order
enum<string> | null
Available options:
asc,
desc

Response

Custom chart results in the order requested.

success
enum<boolean>
required
Available options:
true
customCharts
CustomAnalyticsResult · object[]
required

Results in the same order as the input customCharts array.