Skip to main content

Overview

The Query API provides aggregated access to Scrunch’s core AI visibility metrics. It is the same data that powers the Scrunch dashboard, exposed in a flexible, queryable format for analytics and reporting workflows. This API is optimized for scale and performance, making it ideal for BI tools, reporting pipelines, scheduled exports, and automation where response-level detail is not required. Each request returns pre-aggregated metrics based on the dimensions you select.

What the Query API includes

The Query API returns aggregated metrics such as:
  • Brand presence percentage
  • Brand position score
  • Brand sentiment score
  • Competitor presence percentage
  • Sub-brand presence, position, and sentiment
  • Citation rate, share of voice, and citation volume
  • Response counts
These metrics can be grouped by dimensions including:
  • Date (day, week, month, quarter, year)
  • Prompt or prompt metadata
  • Persona
  • Tag
  • Platform
  • Competitor
  • Sub-brand
  • Source URL
  • Branded vs non-branded
All results are derived summaries, not raw AI responses. Metrics cover history from active and paused prompts; archived prompts are excluded. Persona state does not affect which prompts’ history is counted, so aggregates stay consistent with your configured prompt list.

When to use the Query API

Use the Query API when you need:
  • Weekly or monthly reporting
  • Trend analysis over time
  • Brand and competitor visibility metrics
  • Aggregation by date, persona, tag, platform, or prompt
  • Data for dashboards (Looker, Power BI, Tableau)
  • Large batch metric pulls for automation or reporting
The Query API is designed to answer questions like: “How is our AI visibility changing over time?”
“How do we compare to competitors by topic or platform?”

When not to use the Query API

The Query API is not appropriate if you need:
  • Raw AI response text
  • Citation URLs or snippets
  • Per-response competitor sentiment or position
  • Full message-level audits or research
For those use cases, use the Responses API, which exposes the underlying response records in full detail.

Example query

You can narrow results with filters (pre-aggregation, on dimensions) and having (post-aggregation, on metrics):
Break responses out by the individual fan-out queries an AI engine ran, instead of by the prompt you submitted:
Break the brand / competitor / other ownership split out across responses — the shape BI tools (Looker, Power BI, Tableau) typically chart:

Two ways to query

The Query API exposes two endpoints that share the same dimensions and metrics:
  • GET /v1/{brand_id}/query — URL-parameter form. Use it for simple pulls and BI integrations that prefer query strings.
  • POST /v2/query/{brand_id} — JSON-body form. Use it when you need post-aggregation thresholds (HAVING), negated filters, or period-over-period comparison in a single request. See the Structured Query Endpoint reference.
Both endpoints require an API key with access to the target brand; the POST /v2 endpoint additionally requires the Query scope on the key.

Fields reference

Specify fields in the fields= array to control what is returned. Dimensions determine how metrics are grouped — querying a dimension alone returns its unique values. Metrics are numeric measures — querying a metric alone returns its overall aggregate across all data.

Dimensions

Metrics

Citation metrics are computed on the staging source path. To break citations down by source, pair them with the domain, source_url, owner, cited_competitor_name, citation_segment, or source_topic dimensions — these activate the source-grain breakdown. You can also break citation metrics down by prompt (on its own or combined with a source-grain dimension) to see per-prompt citation rates. Mixing citation fields with high-cardinality dimensions can be slower than mention-only queries; keep date windows and field lists tight.
Pooled “All (brands & competitors)” metrics. The market_* metrics roll mention, position, sentiment, and rank up across your brand and every active competitor in a single volume-weighted average. Use them to track the overall AI conversation about your category — not the sum of per-entity rates. They run as their own query path, so they cannot be mixed with brand, competitor, or sub-brand metrics in the same request; pull them on their own and combine the series downstream.
Citation metrics cannot be combined with fields that force the raw query path — competitor_id, competitor_name, the competitor mention metrics, ai_platform_search_enabled, or source_domain — such requests return HTTP 400. To scope competitor citation metrics to specific competitors, use the cited_competitor_name filter; to break citations down by publisher, use domain instead of source_domain. The prompt dimension is supported: combining it with a citation metric (optionally alongside a source-grain dimension such as domain or source_url) returns the per-prompt citation rate.
Active-entity scope. Sub-brand metrics, the sub_brand_id breakdown, competitor citation metrics, and the cited_competitor_name filter and breakdown only count rows tied to currently active sub-brands and competitors. Archived sub-brands (including those whose parent competitor is no longer active) and deactivated competitors are excluded from numerators, share-of-voice denominators, and breakdown values. Re-activate the entity in your Scrunch brand configuration to bring its history back into results.

Share of Voice supported breakdowns and filters

Mention Share of Voice (brand_share_of_voice, competitor_share_of_voice) divides an entity’s present-response count by the full brand-plus-active-competitors set. Adding a breakdown re-buckets both sides of that ratio, so each row divides by its own slice’s present-set — never a global total. Only the dimensions listed below produce a valid partition; anything else returns HTTP 400. Supported breakdowns. date, date_week, date_month, date_quarter, date_year, ai_platform, stage, persona_name, country, prompt, competitor_id, competitor_name. The prompt breakdown partitions the denominator per prompt, so each row is that prompt’s share of voice against the full competitive set on the same prompt. Supported filters. All of the supported breakdowns are also filterable, plus prompt_id, tag, prompt_topic, and ai_platform_search_enabled. tag and prompt_topic are filter-only for Share of Voice — as breakdowns they would fan a multi-tag response across array elements in the numerator while it counts once in the whole-set denominator, inflating the share. Not supported. The conditional dimensions position_bucket, sentiment_band, and rank are rejected as both breakdowns and filters — they describe one entity’s row within a response, so they cannot narrow the whole-set denominator. Source-grain fields (domain, source_url, owner, cited_competitor_name, citation_segment, source_topic, source_type, source_domain) are citation-path only and cannot combine with mention Share of Voice. Sub-brand Share of Voice. sub_brand_share_of_voice runs on the sub-brand query path. It accepts tag and prompt_topic as filters (parity with sub_brand_citation_share_of_voice) but still rejects them as breakdowns. The prompt (text) dimension is not available on this path at all — for a per-prompt sub-brand slice, break down by prompt_id instead.

Example: citation metrics

Example: Influence Score for outreach prioritization

Rank cited domains by Influence Score alongside the share of pages that already mention your brand — a shortlist of high-influence sources you don’t yet appear on:

Example: citations broken down by domain topic

Break down citation volume by the topic tags configured for each cited source’s domain. Untagged sources appear in an explicit Untagged bucket:

Example: pooled market metrics

Example: sub-brand citation rate by platform

Break down how often each AI platform cites a specific sub-brand’s owned domains:

Cross-grain pooled presence

cross_grain_presence_percentage pools presence across the brand grain (your brand plus selected competitors) and the sub-brand grain (selected sub-brands) into one presence rate. A response counts as present if any selected entity on either grain appeared, so a response that mentions both a brand-grain entity and a sub-brand-grain entity is counted once — not twice. Use it when you want to chart brand + sub-brand visibility as a single combined series (for example, “Own brand + all sub-brands” or “Own brand + one sub-brand + one competitor”) without the double-counting you’d get from summing the per-grain rates.

Selecting which entities join the pool

By default the pool includes your own brand plus every active competitor and every active sub-brand. Narrow either grain with a positive filter on that grain’s identity field:
  • filters=competitor_name:<name> — narrows the competitor branch of the brand grain. Your own brand always stays in the pool.
  • filters=sub_brand_id:<id> — narrows the sub-brand grain to the named sub-brand(s).
  • filters=ownership:competitor — signals “include the competitor branch” when you want all active competitors in the pool but have no specific names to list. Without either this filter or a competitor_name list, the pool drops the competitor branch entirely and uses your own brand alone on the brand grain.
Multiple positive values on the same identity field are combined as IN (...) — the pool is the union of the named entities, matching what an Explorer multi-select produces. Negated identity filters (competitor_name:!<name>, sub_brand_id:!<id>) are rejected with HTTP 400.

Supported breakdowns

Cross-grain pooling is presence-only, so it accepts only the non-conditional lens dimensions: date, date_week, date_month, date_quarter, date_year, ai_platform, stage, persona_name, persona_id, country, branded, prompt_id. Entity-identity breakdowns (competitor_id, competitor_name, sub_brand_id) and source-grain dimensions (domain, source_url, owner, source_domain) are not supported — the pooled series has no per-entity split. Position, sentiment, rank, and share-of-voice have no cross-grain analogue and are not available either.

Example

Weekly combined presence for your brand, a chosen competitor, and one sub-brand on ChatGPT:
Weekly combined presence for your brand plus every active sub-brand (no competitor leg):
Only active competitors and sub-brands contribute to the pool. Archived competitors and sub-brands (including those whose parent competitor is no longer active) are excluded from the numerator, so re-activate them in your brand configuration to bring their history back in.

Filtering results

The Query API supports two filter parameters that narrow what is returned. Both can be combined in the same request and both can be repeated to apply multiple filters (combined with AND).

Dimension filters (filters)

Use filters to narrow rows before aggregation runs. Each filter takes the form field:value. Combine multiple values with | for an IN match, and prefix the value with ! to negate.
Filterable dimensions: prompt_id, persona_id, persona_name, ai_platform, ai_platform_search_enabled, tag, competitor_id, competitor_name, sub_brand_id, branded, stage, prompt_topic, country, position_bucket, sentiment_band, rank, date, date_week, date_month, date_quarter, date_year, owner. rank values must be positive integers (1, 2, …); non-numeric values return HTTP 400. owner accepts a closed vocabulary — brand, competitor, other. Any other value returns HTTP 400; see Filtering by citation source owner. source_url, domain, source_domain, source_topic, prompt, and query_fanouts are not filterable.

Filter for prompts with no tag or topic

Pass the reserved token __none__ as a filter value on tag or prompt_topic to match prompts that carry no tag or no topic. Use it to isolate the untagged tail of your prompt set.
Combine __none__ with real values using | — the filter matches the untagged prompts or the named tags:
Prefix with ! to invert the whole filter — for example, prompts that carry at least one tag:
Only tag and prompt_topic accept __none__. Sending it on any other dimension returns HTTP 400. A tag literally named __none__ becomes unreachable by equality — the token always resolves to the absence match. Rename such a tag if you need to filter for it directly.

Filtering by citation source owner

owner scopes results to citations owned by the brand, a configured competitor, or a third party. Values are a closed vocabulary: brand, competitor, other. Any other value returns HTTP 400. The filter behaves at two grains depending on what else is in fields:
  • Response grain (default). Without a source-grain breakdown, the filter keeps whole responses that cite at least one source of that owner. Every metric in the request is scoped to those responses.
  • Source grain (with domain, source_url, citation_segment, or source_topic in fields). The filter narrows the source-grain rows to the matching sources only, so a citation-domain breakdown returns just the domains owned by the selected class.
Applying an owner filter creates citation context, so it must be paired with a citation metric (for example citation_count, brand_citation_rate, citation_unique_responses). Pairing owner with only response-level metrics such as responses returns HTTP 400 — use the owner breakdown for that shape instead.

Metric filters (having)

Use having to filter on aggregated metric values after GROUP BY runs. Each entry takes the form metric:operator:value.
The metric you reference in having must also appear in fields.

Breaking mentions down by a conditional dimension

position_bucket, sentiment_band, and rank are conditional dimensions — they describe how an entity appeared in a response, so they only exist on responses where that entity is actually mentioned (and, for rank, ranked):
  • position_bucket: top, middle, bottom
  • sentiment_band: positive, mixed, negative, none
  • rank: positive integers (1, 2, …), where 1 is the first mention
When you group by any of these, responses where the entity is not mentioned (or, for rank, not ranked) are excluded from the breakdown — there is no “not mentioned” or “rank 0” row. Alongside a presence metric, each row reports that bucket’s share of mentions: the buckets within a group sum to 1.0 (100% of mentioned responses), not to the overall mention rate. To relate the shares back to overall visibility, run a second query without the conditional dimension or multiply each share by the overall presence metric. The conditional dimension follows the entity scope of the metric it is paired with:
  • Pair with brand_* mention metrics to break out your brand’s position, sentiment, or rank distribution.
  • Pair with competitor_* mention metrics (plus a competitor_id / competitor_name filter) to break out a competitor’s distribution.
  • Pair with market_* mention metrics to break out the pooled distribution across every tracked entity.

Position breakdown

Here 58% of the responses that mention your brand place it in the top of the answer.

Rank distribution

Of all responses that mention your brand, 62% list it first. Pair rank with a competitor_* mention metric (and a competitor_id filter) to chart the same distribution for a competitor, or with a market_* mention metric to chart the pooled distribution across every tracked entity.

Crossing with non-conditional dimensions

The same decomposition holds per group when you cross a conditional dimension with a non-conditional one — shares sum to 1.0 within each ai_platform below:

Filtering on a conditional dimension

You can also use either dimension purely as a filter — for example, to restrict every other metric in a query to responses where the brand appears in the top of the answer, or only to positive mentions:
This behavior only applies when position_bucket or sentiment_band is in fields. For queries that do not group by either, brand_presence_percentage keeps its usual meaning — the share of all responses that mention the brand.
A single query cannot mix a brand metric and a competitor metric and a conditional dimension — one breakdown column can only describe one entity’s row. Such requests return HTTP 400; split them into separate queries. having on a presence metric is also rejected with HTTP 400 when a conditional dimension is in fields; filter on a count metric such as brand_unique_responses instead.

Date range and validation

Use the start_date and end_date query parameters to scope a request to a specific window. Both are optional and accept the YYYY-MM-DD format.

Example: valid request

Example: invalid date returns 400

If you build query strings dynamically, prefer omitting start_date / end_date when you don’t have a value rather than passing an empty string — the result is the same, but the intent is clearer.

Cardinality and result size

Because the Query API performs grouping dynamically, combining highly granular dimensions can significantly increase the number of rows returned. Examples of high-cardinality dimensions include:
  • ai_platform
  • tag
  • prompt_topic
  • competitor_id
  • competitor_name
  • source_url
  • source_domain
  • domain
  • source_type
  • query_fanouts
Each additional high-cardinality field multiplies the number of possible result rows.
Avoid combining multiple high-cardinality dimensions unless required, as this can produce very large result sets and slower queries.

Limits and performance considerations

  • The Query API supports large batch pulls (up to tens of thousands of rows per request)
  • Results are pre-aggregated and optimized for analytics and BI ingestion
  • Query performance degrades as result cardinality increases
For best performance, keep field selections focused and intentional.

Best practices

  • Prefer date_week or date_month over daily granularity when possible
  • Run separate queries for different reporting needs and join downstream
  • Keep field lists small to control result size
  • Use brand-scoped API keys when embedding in client-facing dashboards
  • Treat Query API outputs as metrics tables, not raw data logs

Relationship to the Responses API

The Query API and Responses API are complementary:
  • Query API: fast, aggregated metrics for reporting and dashboards
  • Responses API: full-fidelity response text and citation data for deep analysis
Most customers use the Query API for ongoing reporting and the Responses API selectively for audits, research, or investigation.

Run your first query

Go to the Query API Quickstart →