Skip to content

Product reporting reference #

Product reporting applies the Product Query filters and record-read permission to one published model. It provides bounded operational summaries and extracts; it is not an unrestricted analytics or warehouse interface.

Define metrics #

The metrics array accepts at most eight entries. Each entry has a result name, a function in fn, and, where required, a published field key:

json
{
  "where": [
    { "field": "status", "op": "eq", "value": "declined" }
  ],
  "metrics": [
    { "name": "transactions", "fn": "count" },
    { "name": "value", "fn": "sum", "field": "amount" }
  ]
}

Supported functions are count, sum, avg, min, and max. count without a field counts records; count with a field counts indexed values. The other functions require a stored numeric field: integer, decimal, or money.

Without grouping, the response contains model and a metrics array. Each metric reports its requested name, fn, field, and value.

Group results #

Set group_by to a list containing one stored scalar field key. Reference fields and non-stored fields cannot be grouped. Although the validation boundary accepts at most two group keys, the V1 aggregate executor supports one grouping field.

Grouped aggregates support count only. The response contains groups, group_by, and truncated. Each group has a key object and its own metrics array.

At most 100 groups are returned. If more values exist, truncated is true. Use a narrower Product Query filter or export authorised records for processing in a customer-owned reporting system.

Bucket datetime values #

Use time_bucket with a stored datetime field and one of hour, day, week, or month:

json
{
  "metrics": [
    { "name": "transactions", "fn": "count" }
  ],
  "time_bucket": {
    "field": "occurred_at",
    "unit": "day"
  }
}

Time buckets support count only and return at most 100 buckets, using truncated to report a bounded result. time_bucket and group_by cannot be combined.

Stream a CSV export #

CSV export accepts Product Query where, order_by, select, and include_archived values. It reads records in cursor pages and streams the response as text/csv rather than materialising the complete result.

The first line is a # product_query_export comment containing JSON metadata: model key and stable ID, export time, filters, ordering, projection, archived selection, and published schema version. The final comment reports exported_rows.

Columns always begin with id, created_at, and updated_at, followed by the selected visible field keys. Nested values are serialised as compact JSON.

The default and hard maximum export bound is 50,000 rows. A positive max_rows can request a lower bound; values above the hard maximum are capped. Streaming controls application memory use, but it does not turn the endpoint into an unlimited bulk export.

Choose an appropriate reporting path #

Use aggregates for dashboards and bounded operational summaries. Use CSV for a reviewable extract from one model. For joins, arbitrary full-text search, long-term history, or high-cardinality analysis, move authorised data through an integration into a customer-owned reporting system.