Available cubes, each as the CubeMeta discovery projection — the cube name, its title and description, and the measures/dimensions a client may name in a query. A bare array: there is no cubes wrapper object, and no cube sql is published.
Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages)
declaredCode
string
optional
The producer-declared code, verbatim, when it is not a member of the closed code vocabulary — the open, author-authored channel (app-specific spellings; ADR-0112)
message
string
✅
Readable error message
userMessage
string
optional
Producer-marked user-facing refusal text, verbatim. Present exactly when the producer opted in at throw time; consumers render it to end users and keep their generic substitution for anything unmarked. Status-agnostic; never replaces message.
refusal
true
optional
Producer-declared: the 5xx this envelope carries is a deliberate refusal whose message is authored for the caller, so a boundary that reads the declaration keeps it verbatim (until the withhold arms read it, a declared refusal is still withheld). Absent (the default) on a declared fault, whose message is withheld from the body and logged for the operator; redundant on a 4xx. Presence is the declaration — true is the only value.
category
string
optional
Error category (e.g. validation, authorization)
httpStatus
integer
optional
HTTP status of the response carrying this error
details
any
optional
Additional error context (e.g. field validation errors)
Filtering criteria (canonical Query DSL FilterCondition). An authored FilterArray is lowered by parseFilterAST on the client before the wire; this field admits only the lowered FilterCondition (see FilterArray in data/filter.zod.ts).
Time-bucketed dimensions. Each entry names a dimension, an optional bucket granularity, and an optional dateRange — a preset name from the closed date-range vocabulary (e.g. 'last_7_days') or an explicit [start, end] window; an unrecognised string answers 400 ANALYTICS_DATE_RANGE_UNRECOGNIZED instead of silently widening.
order
Record<string, Enum<'asc' | 'desc'>>
optional
limit
integer
optional
Maximum number of rows to return, applied after order — a non-negative integer (0 returns no rows)
offset
integer
optional
Number of rows to skip before the first row returned, applied after order — a non-negative integer; an offset with no limit returns every row after it
timezone
string
optional
query
never
optional
[REMOVED] query was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0. The { cube, query: {...} } envelope was the dialect of the retired degraded analytics shim — the real engine never understood it. Move the query.* fields to the body top level: { cube, measures, dimensions?, where?, timeDimensions?, order?, limit?, offset?, timezone? }.
format
never
optional
[REMOVED] format was removed from AnalyticsQueryRequest in @objectstack/spec 17.0.0. It was never implemented — every response is the JSON envelope. Delete the key; for CSV/XLSX use the export surface instead.
Time window for this dimension: a date-range PRESET name from the closed vocabulary in data/date-range-presets.ts (today, yesterday, this_week, last_week, this_month, last_month, this_quarter, last_quarter, this_year, last_year, last_7_days, last_30_days, last_90_days — e.g. 'last_7_days'), or an explicit [start, end] array of ISO dates / {date-macro} tokens (e.g. ["2023-01-01", "2023-01-31"]). Any other string is refused at the schema with 400 ANALYTICS_DATE_RANGE_UNRECOGNIZED.
Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages)
declaredCode
string
optional
The producer-declared code, verbatim, when it is not a member of the closed code vocabulary — the open, author-authored channel (app-specific spellings; ADR-0112)
message
string
✅
Readable error message
userMessage
string
optional
Producer-marked user-facing refusal text, verbatim. Present exactly when the producer opted in at throw time; consumers render it to end users and keep their generic substitution for anything unmarked. Status-agnostic; never replaces message.
refusal
true
optional
Producer-declared: the 5xx this envelope carries is a deliberate refusal whose message is authored for the caller, so a boundary that reads the declaration keeps it verbatim (until the withhold arms read it, a declared refusal is still withheld). Absent (the default) on a declared fault, whose message is withheld from the body and logged for the operator; redundant on a 4xx. Presence is the declaration — true is the only value.
category
string
optional
Error category (e.g. validation, authorization)
httpStatus
integer
optional
HTTP status of the response carrying this error
details
any
optional
Additional error context (e.g. field validation errors)
Marginal aggregates - one entry per requested totals grouping, in request order, each computed with the measure's true aggregate over the underlying data (never re-derived from bucketed values). The grand-total grouping yields a single dimensionless row.
object
string
optional
The base object of the dataset the answer was computed from: the dataset's object, by machine name. Every dataset answer (POST /analytics/dataset/query) must carry it, whatever dimensions are selected and whether or not rows came back, so a consumer can refresh on that object's record changes and drill into its records. Absent on a cube query answer, which has no dataset behind it.
dimensionFields
Record<string, string>
optional
Drill-through sidecar: each equality-drillable dimension the answer is grouped by, dimension name to that dataset dimension's own field (a base-object field or a relationship.field path). Set only on a dataset answer (POST /analytics/dataset/query) that has rows and groups by at least one dimension with a field that is not type: 'date'; a date dimension is never listed (see drillRanges). Absent on a cube query answer.
drillRawRows
Record<string, any>[]
optional
Drill-through sidecar, aligned to rows by index: each dimensionFields dimension name to the stored value that row was grouped by (a select option's value, a lookup's record id), captured before label resolution rewrites the row to its display label. An exact-match drill filter is built from these, not from the labels in rows. Set exactly when dimensionFields is.
drillRawTotals
Record<string, any>[][]
optional
Drill-through sidecar for totals: entry [i][j] aligns to totals[i].rows[j] and holds the stored value of the dimensionFields dimensions that grouping groups by, so the grand-total grouping yields an empty map per row. Set only when dimensionFields is and the answer carries at least one totals grouping.
Drill-through sidecar for time buckets, aligned to rows by index: date dimension name to the half-open range [gte, lt) that row's bucket covers. Bounds are YYYY-MM-DD calendar days, or ISO-8601 instants at midnight in the reference timezone when the source field is datetime; a row whose bucket value is null gets no entry for that dimension. Set only on a dataset answer that has rows and groups by at least one type: 'date' dimension with a field and a granularity; independent of dimensionFields. Absent on a cube query answer.
Error code (e.g. VALIDATION_ERROR; StandardErrorCode ∪ the ledger the serving side registers — ERROR_CODE_LEDGER for framework packages)
declaredCode
string
optional
The producer-declared code, verbatim, when it is not a member of the closed code vocabulary — the open, author-authored channel (app-specific spellings; ADR-0112)
message
string
✅
Readable error message
userMessage
string
optional
Producer-marked user-facing refusal text, verbatim. Present exactly when the producer opted in at throw time; consumers render it to end users and keep their generic substitution for anything unmarked. Status-agnostic; never replaces message.
refusal
true
optional
Producer-declared: the 5xx this envelope carries is a deliberate refusal whose message is authored for the caller, so a boundary that reads the declaration keeps it verbatim (until the withhold arms read it, a declared refusal is still withheld). Absent (the default) on a declared fault, whose message is withheld from the body and logged for the operator; redundant on a 4xx. Presence is the declaration — true is the only value.
category
string
optional
Error category (e.g. validation, authorization)
httpStatus
integer
optional
HTTP status of the response carrying this error
details
any
optional
Additional error context (e.g. field validation errors)
Time-bucketed dimensions. Each entry names a dimension, an optional bucket granularity, and an optional dateRange — a preset name from the closed date-range vocabulary (e.g. 'last_7_days') or an explicit [start, end] window; an unrecognised string answers 400 ANALYTICS_DATE_RANGE_UNRECOGNIZED instead of silently widening.
Presentation-scope date bucketing applied to every selected date dimension; an explicit timeDimensions entry wins over it, and the dataset dimension's own default is used when neither is set
order
Record<string, Enum<'asc' | 'desc'>>
optional
limit
integer
optional
Maximum number of rows to return, applied after order — a non-negative integer (0 returns no rows)
offset
integer
optional
Number of rows to skip before the first row returned, applied after order — a non-negative integer; an offset with no limit returns every row after it
Time window for this dimension: a date-range PRESET name from the closed vocabulary in data/date-range-presets.ts (today, yesterday, this_week, last_week, this_month, last_month, this_quarter, last_quarter, this_year, last_year, last_7_days, last_30_days, last_90_days — e.g. 'last_7_days'), or an explicit [start, end] array of ISO dates / {date-macro} tokens (e.g. ["2023-01-01", "2023-01-31"]). Any other string is refused at the schema with 400 ANALYTICS_DATE_RANGE_UNRECOGNIZED.