Query Analytics data with selected fields, time bounds and filters.
Ternary's Analytics API puts you in control of your data and lets you make queries against the billing dataset you have ingested to Ternary. This endpoint is the primary endpoint for doing so.
Select FOCUS_BILLING, the data source exposed by Fetch Metadata, and the fields to query. start_time and end_time are optional bounds: the start is inclusive and the end is exclusive. Set precision to group results by time; without it, the query adds no timestamp grouping. With precision, each row includes timestamp, the UTC bucket start, and defaults to ascending timestamp order unless order_by explicitly orders that key. ROLLUP subtotal rows can omit it. Dimensions group the selected measures, and filters narrow the matching data.
To view a list of available measures and dimensions for filtering, use the Fetch Metadata endpoint first, then use the string values in the response as the values inside this request.
Here's an example query payload for Billed Cost per day from April 30 through May 30, 2025, inclusive in UTC, grouped by Service Category.
{
"data_source": "FOCUS_BILLING",
"dimensions": [
"FOCUS_SPEC_FIELD/ServiceCategory"
],
"measures": [
"FOCUS_SPEC_FIELD/BilledCost"
],
"precision": "DAY",
"start_time": "2025-04-30T00:00:00.000Z",
"end_time": "2025-05-31T00:00:00.000Z"
}Filters use their fields directly. A single filter has schema_field_name, operator and any operator-specific values; do not wrap it in singleFilter:
{
"schema_field_name": "FOCUS_SPEC_FIELD/ServiceCategory",
"operator": "equals",
"values": ["Compute"]
}Dimension filters support equality, comparisons and set checks; contains/notContains apply only to STRING dimensions. Measure filters support gt/gte/lt/lte/set/notSet. Time-dimension filters support gt/gte/lt/lte with one timestamp value. Value-count validation is inconsistent, so malformed counts may return a server error.
For a group, supply boolean_logical_operator (and, or, nand or nor) and a nonempty filters array. Groups can contain other groups; do not wrap them in compositeFilter:
{
"boolean_logical_operator": "or",
"filters": [
{
"schema_field_name": "FOCUS_SPEC_FIELD/ServiceCategory",
"operator": "equals",
"values": ["Compute", "Storage"]
},
{
"boolean_logical_operator": "and",
"filters": [
{
"schema_field_name": "FOCUS_SPEC_FIELD/ServiceCategory",
"operator": "equals",
"values": ["Networking"]
}
]
}
]
}These rules apply to the Analytics Query endpoint. Core API custom-measure variable filters have a narrower contract: groups accept and or or, and values must be strings within the Core schema limits.
Use these objects inside pre_agg_filters or post_agg_filters in the query. The JSON examples show the recursive shape even when an interactive form cannot expand every nesting level.
