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
- Date (day, week, month, quarter, year)
- Prompt or prompt metadata
- Persona
- Tag
- Platform
- Competitor
- Sub-brand
- Source URL
- Branded vs non-branded
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
“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
Example query
filters (pre-aggregation, on dimensions) and having (post-aggregation, on metrics):
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.
POST /v2 endpoint additionally requires the Query scope on the key.
Fields reference
Specify fields in thefields= 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
| Field | Type | Description | Constraints | Prompt relationship |
|---|---|---|---|---|
prompt_id | Number | Unique identifier for the prompt | — | — |
prompt | String | Full text of the prompt submitted to the AI platform | — | — |
date_month | String | Month responses were collected, truncated to the first day of the month. Use for monthly trend reporting. | Last 90 days only | Many to many |
date_week | String | Calendar week responses were collected, truncated to the start of the week. Use for weekly trend reporting. | Last 90 days only. Recommend keeping date filters week-aligned. | Many to many |
date | String | Specific date responses were collected. Use for daily granularity. | Last 90 days only | Many to many |
source_url | String | Full URL of a citation source found in AI responses. Use to analyze which web properties appear most in AI answers. | — | Many to many |
domain | String | Registered domain of a citation source (e.g. example.com). Use to roll source_url data up to the domain level. | — | Many to many |
owner | String (Enum) | Ownership classification of a citation’s domain. Values: brand (the tracked brand), competitor (a configured competitor), other (everything else). Use to chart the brand vs. competitor vs. third-party split. | Not filterable | Many to many |
source_type | String (Enum) | Ownership classification of a citation source. Values: brand, competitor, other (third-party in the Scrunch UI). Equivalent to owner and retained for backward compatibility — new integrations should prefer owner. | — | Many to many |
source_domain | String | Host of a citation source, lowercased and www-stripped (for example, nytimes.com). Use to group citations by publisher rather than by individual URL. | Computed on the raw query path — cannot be combined with citation metrics (use domain for that) and is not filterable. | Many to many |
persona_id | Number | Unique identifier for the persona associated with the prompt | — | One to many |
persona_name | String | Name of the persona associated with the prompt. Personas represent audience segments or geographic configurations. | — | One to many |
competitor_id | Number | Unique identifier for a competitor tracked in your Scrunch brand configuration | — | Many to many |
competitor_name | String | Name of the competitor. Use alongside competitor metrics to analyze individual competitor visibility. | — | Many to many |
sub_brand_id | Number | Unique identifier for a sub-brand tracked in your Scrunch brand configuration. Use alongside sub-brand metrics to analyze a specific product line, region, or division. | — | Many to many |
ai_platform | String (Enum) | AI platform that generated the response. Values: chatgpt, perplexity, google_ai_overviews, meta, claude | — | Many to many |
tag | String | User-defined tag attached to prompts in the Scrunch UI. Use to group and filter by custom categories. | — | Many to many |
branded | Boolean | Whether the prompt includes the brand name or an alternate brand name. Use to compare branded vs. unbranded query performance. | — | One to many |
stage | String (Enum) | Stage of the customer journey the prompt is mapped to. Values: Advice, Awareness, Evaluation, Comparison, Other | — | One to many |
prompt_topic | String | Key topic extracted from or assigned to the prompt. Use to group performance by topic area. | — | Many to many |
country | String | 2-letter ISO country code for which the response was retrieved, based on the persona or brand default configuration. | — | One to many |
position_bucket | String (Enum) | Where your brand appears inside a response when it is mentioned. Values: top, middle, bottom. Use to break mentions out by prominence — for example, to see what share of mentions land in the top of the answer. | Conditional dimension: rows where the brand is not mentioned are excluded from the breakdown. See Breaking mentions down by a conditional dimension. | Many to many |
sentiment_band | String (Enum) | How your brand is talked about inside a response when it is mentioned. Values: positive, mixed, negative, none. Use to break mentions out by tone — for example, to see what share of mentions are positive on each platform. | Conditional dimension: rows where the brand is not mentioned are excluded from the breakdown. See Breaking mentions down by a conditional dimension. | Many to many |
query_fanouts | String | Individual search query an AI engine generated internally during query fan-out. Each row in the response represents one fan-out query; observations without a fan-out yield zero rows for this dimension. Use to break metrics down by the underlying searches an AI platform actually ran. | Not filterable. Forces the raw query path, which can be slower than other dimensions. | Many to many |
Metrics
| Field | Type | Description | Aggregation | Constraints |
|---|---|---|---|---|
responses | Number | Total number of AI responses collected for the selected dimensions. The base volume metric. | Count | — |
unique_prompts | Number | Distinct count of prompt variants that produced responses in the selected window. A prompt expands into one variant per platform × persona × geography × language × scenario combination, and variants are what Scrunch actually monitors — so this is what the Scrunch dashboard’s “Prompts” tile reports. Use to size the underlying variant set behind any aggregate. | Distinct count | — |
brand_presence_percentage | Number | Percentage of responses in which your brand was mentioned. The primary measure of AI visibility. | Average | — |
brand_unique_prompts | Number | Distinct count of prompt variants where your brand was mentioned in at least one response. Variant-grain, matching unique_prompts. | Distinct count | — |
brand_unique_responses | Number | Distinct count of responses that mentioned your brand. | Distinct count | — |
brand_share_of_voice | Number | Your brand’s share of mentions across the full competitive set. Computed as your brand’s mention responses divided by the total mention responses for your brand plus all active competitors. Across a given slice, brand_share_of_voice plus the sum of competitor_share_of_voice for every competitor equals 1. Use to compare visibility on a normalized scale that ignores prompts where nobody was mentioned. | Ratio | Range: 0–1. The denominator always reflects the full brand-plus-competitors set, even if you filter to specific competitors. |
brand_position_score | Number | Weighted score (0–100) reflecting how prominently your brand appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — higher scores indicate more top-of-response appearances. Note: the Scrunch dashboard displays the raw share of Top-position responses; this score is a continuous aggregate and will differ from that figure. | Average | Range: 0–100 |
brand_sentiment_score | Number | Weighted score (0–100) reflecting overall sentiment toward your brand across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — higher scores indicate a more positive distribution. Note: the Scrunch dashboard displays the raw share of Positive-sentiment responses; this score is a continuous aggregate and will differ from that figure. | Average | Range: 0–100 |
brand_avg_rank | Number | Average first-occurrence rank of your brand among same-type entities mentioned in a response, where 1 is the first mention. Lower is better. Only responses in which your brand was ranked contribute to the average — responses where your brand was not mentioned are skipped, so this metric measures positioning among ranked appearances only. Pair with brand_presence_percentage to see how often your brand shows up at all. | Average | Starts at 1. Computed over ranked appearances only. |
competitor_presence_percentage | Number | Percentage of responses in which the competitor was mentioned. | Average | Must be used with competitor_id or competitor_name (or both) |
competitor_position_score | Number | Weighted score (0–100) reflecting how prominently the competitor appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — see note on brand_position_score regarding differences from dashboard figures. | Average | Range: 0–100. Must be used with competitor_id or competitor_name (or both) |
competitor_sentiment_score | Number | Weighted score (0–100) reflecting overall sentiment toward the competitor across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — see note on brand_sentiment_score regarding differences from dashboard figures. | Average | Range: 0–100. Must be used with competitor_id or competitor_name (or both) |
competitor_avg_rank | Number | Average first-occurrence rank of the competitor among same-type entities mentioned in a response, where 1 is the first mention. Lower is better. Only responses in which the competitor was ranked contribute to the average; responses where the competitor was not mentioned are skipped. Pair with competitor_presence_percentage to see how often the competitor shows up at all. | Average | Starts at 1. Computed over ranked appearances only. Must be used with competitor_id or competitor_name (or both) |
competitor_unique_prompts | Number | Distinct count of prompt variants where the competitor was mentioned in at least one response. Variant-grain, matching unique_prompts. | Distinct count | Must be used with competitor_id or competitor_name (or both) |
competitor_unique_responses | Number | Distinct count of responses that mentioned the competitor. | Distinct count | Must be used with competitor_id or competitor_name (or both) |
competitor_share_of_voice | Number | The competitor’s share of mentions across the full competitive set. Computed as the competitor’s mention responses divided by the total mention responses for your brand plus all active competitors. Pair with competitor_id or competitor_name for a per-competitor breakdown; without that dimension the value aggregates every competitor. The denominator stays fixed to the full set, so filtering competitor rows does not rescale the share. | Ratio | Range: 0–1. Must be used with competitor_id or competitor_name (or both) for per-competitor values. |
sub_brand_presence_percentage | Number | Percentage of responses in which the sub-brand was mentioned. Use to measure AI visibility for a specific product line, region, or division. | Average | Pair with sub_brand_id to break out by sub-brand, or filter sub_brand_id to isolate one |
sub_brand_position_score | Number | Weighted score (0–100) reflecting how prominently the sub-brand appears across all responses. Derived from the distribution of Top, Middle, and Bottom positions — see note on brand_position_score regarding differences from dashboard figures. | Average | Range: 0–100 |
sub_brand_sentiment_score | Number | Weighted score (0–100) reflecting overall sentiment toward the sub-brand across all responses. Derived from the distribution of Positive, Mixed, Negative, and None sentiments — see note on brand_sentiment_score regarding differences from dashboard figures. | Average | Range: 0–100 |
sub_brand_unique_prompts | Number | Distinct count of prompt variants where the sub-brand was mentioned in at least one response. Variant-grain, matching unique_prompts. | Distinct count | — |
sub_brand_unique_responses | Number | Distinct count of responses that mentioned the sub-brand. | Distinct count | — |
sub_brand_share_of_voice | Number | The aggregate share of mentions across the sub-brands you track under your brand. Computed as present (sub_brand, response) pairs over the total present pairs across all tracked sub-brands, so the values across a sub-brand set sum to 1. Use to gauge how attention is distributed across your own product lines, regions, or other sub-brand groupings. The denominator reflects the full tracked sub-brand set and does not shrink when you filter to a subset. | Ratio | Range: 0–1. Not compatible with the tag or prompt_topic breakdown dimensions (mirrors brand_share_of_voice / competitor_share_of_voice). |
citation_rate | Number | Share of all responses in the slice that include at least one citation, regardless of who owns it. The denominator is every response in the slice. | Average | Range: 0–1 |
brand_citation_rate | Number | Share of all responses in the slice that cite at least one brand-owned domain. The denominator is every response in the slice, matching brand_presence_percentage semantics for citations. | Average | Range: 0–1 |
competitor_citation_rate | Number | Share of all responses in the slice that cite at least one competitor-owned domain. | Average | Range: 0–1. Cannot be combined with competitor_id / competitor_name (HTTP 400) — scope to specific competitors with the cited_competitor_name filter. |
brand_citation_share_of_voice | Number | Of responses that cite anything, the share that cite at least one brand-owned domain. The denominator is responses with at least one citation — use this to ask “when the AI cites sources, how often is it citing us?” | Ratio | Range: 0–1 |
competitor_citation_share_of_voice | Number | Of responses that cite anything, the share that cite at least one competitor-owned domain. | Ratio | Range: 0–1. Cannot be combined with competitor_id / competitor_name (HTTP 400) — scope with the cited_competitor_name filter. |
citation_count | Number | Total citation occurrences across responses in the slice. A response that cites three URLs contributes three. Entity-agnostic — counts every citation regardless of owner. | Sum | — |
brand_citation_count | Number | Total citation occurrences that resolve to a brand-owned domain. | Sum | — |
competitor_citation_count | Number | Total citation occurrences that resolve to a competitor-owned domain. | Sum | Cannot be combined with competitor_id / competitor_name (HTTP 400) — scope with the cited_competitor_name filter. |
citation_unique_responses | Number | Distinct count of responses that contain at least one citation. | Distinct count | — |
brand_citation_unique_responses | Number | Distinct count of responses that cite at least one brand-owned domain. | Distinct count | — |
competitor_citation_unique_responses | Number | Distinct count of responses that cite at least one competitor-owned domain. | Distinct count | Cannot be combined with competitor_id / competitor_name (HTTP 400) — scope with the cited_competitor_name filter. |
citation_unique_domains | Number | Distinct count of citation hosts (www-stripped) across responses in the slice. | Distinct count | — |
brand_citation_unique_domains | Number | Distinct count of brand-owned citation hosts (www-stripped). | Distinct count | — |
competitor_citation_unique_domains | Number | Distinct count of competitor-owned citation hosts (www-stripped). | Distinct count | Cannot be combined with competitor_id / competitor_name (HTTP 400) — scope with the cited_competitor_name filter. |
sub_brand_citation_rate | Number | Share of responses (0–1) that cite a source owned by the sub-brand. Use to measure how often AI grounds answers in your sub-brand’s own web properties. | Average | Pair with sub_brand_id for per-sub-brand values (recommended — without it the value aggregates across all tracked sub-brands). Requires sub-brands to be configured for the brand. |
sub_brand_citation_share_of_voice | Number | Of responses that cite any source, the share (0–1) that cite a sub-brand-owned source. Use to compare a sub-brand’s citation footprint against all cited domains. | Ratio | Pair with sub_brand_id for per-sub-brand values. |
sub_brand_citation_count | Number | Total citation occurrences across responses where the cited domain is owned by the sub-brand. | Count | Pair with sub_brand_id for per-sub-brand values. |
sub_brand_citation_unique_responses | Number | Distinct count of responses that include at least one citation to a sub-brand-owned source. | Distinct count | Pair with sub_brand_id for per-sub-brand values. |
sub_brand_citation_unique_domains | Number | Distinct count of sub-brand-owned domains (www-stripped) cited across responses. | Distinct count | Pair with sub_brand_id for per-sub-brand values. |
Citation metrics are computed on the staging source path. To break citations down by source, pair them with the
domain, source_url, owner, or cited_competitor_name dimensions — these activate the source-grain breakdown. Mixing citation fields with high-cardinality dimensions can be slower than mention-only queries; keep date windows and field lists tight.Example: citation metrics
Example: sub-brand citation rate by platform
Break down how often each AI platform cites a specific sub-brand’s owned domains: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.
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, date, date_week, date_month, date_quarter, date_year.
source_url, domain, owner, source_domain, prompt, and query_fanouts are not filterable.
Metric filters (having)
Use having to filter on aggregated metric values after GROUP BY runs. Each entry takes the form metric:operator:value.
| Operator | Meaning |
|---|---|
gt | Greater than |
gte | Greater than or equal |
lt | Less than |
lte | Less than or equal |
eq | Equal |
neq | Not equal |
having must also appear in fields.
Breaking mentions down by a conditional dimension
position_bucket and sentiment_band are conditional dimensions — they describe how your brand appeared in a response, so they only exist on responses where the brand is actually mentioned:
position_bucket:top,middle,bottomsentiment_band:positive,mixed,negative,none
brand_presence_percentage, 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 brand_presence_percentage.
Position breakdown
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 eachai_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.Date range and validation
Use thestart_date and end_date query parameters to scope a request to a specific window. Both are optional and accept the YYYY-MM-DD format.
| Behavior | What happens |
|---|---|
| Both omitted | Returns the last 30 days, ending today (UTC). |
Only start_date set | end_date defaults to today (UTC). |
Only end_date set | start_date defaults to 30 days before end_date. |
Empty string (?start_date=) | Treated as missing. The default applies. |
Trailing or leading whitespace (?start_date=2026-03-20%20) | Trimmed before parsing. The cleaned value is used. |
Malformed value (?start_date=2024-02-30 or ?start_date=tomorrow) | Returns HTTP 400 with the offending value in detail. |
Example: valid request
Example: invalid date returns 400
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
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
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
Run your first query
Go to the Query API Quickstart →