> ## Documentation Index
> Fetch the complete documentation index at: https://docs.querying.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Monitor Reports: Mention Rate, Share of Voice and Analytics

> Read a monitor's report from one endpoint, with an explicit window, filters, denominators and comparison rules.

`GET /v1/monitors/{id}/analytics` ([reference](/api-reference/monitors/get-analytics.md)) returns every
number in a monitor's report from one set of answers: one window, one set of filters, and the same window
before it for comparison. Build every panel of your own report from this endpoint, and read `quality`
before the numbers. Reading a report costs nothing.

```bash theme={"theme":"css-variables"}
curl "https://api.querying.ai/v1/monitors/$MONITOR_ID/analytics?since=2026-10-16T00:00:00Z&until=2026-10-18T00:00:00Z&engine=CHATGPT" \
  -H "Authorization: Bearer $QUERYING_API_KEY"
```

## Query parameters

| Parameter | Description |
| - | - |
| `days` | `7`, `30` (default) or `90`: the window ends now. Cannot be combined with `since` and `until`. |
| `since`, `until` | A fixed window. Send both, as ISO 8601 instants with a timezone, such as `2026-10-16T00:00:00Z`. The span must be positive and at most 90 days, and `until` cannot be in the future. A bare date such as `2026-10-16` is rejected. |
| `engine` | Only answers from this engine: a monitor engine id or one of its aliases, such as `GOOGLE_AIO`. |
| `prompt` | Only answers to this prompt, by exact text, 1–2,000 characters. Answers are stored by prompt text, so a prompt you have removed from the monitor stays queryable. |

The window is half-open and in UTC: `since` is included, `until` is not. The previous window has exactly
the same length, ends at `since` and uses the same filters, so every comparison is like for like. Send
each parameter once.

## Example

For example, a brand monitor that asks ChatGPT two prompts once a day with `samples: 5` (ten answers a
day), filtered to ChatGPT over two days, returns:

> **Full response**
>
> ```json theme={"theme":"css-variables"}
> {
>   "success": true,
>   "data": {
>     "monitor": {
>       "id": "d39b8de0-b159-4229-bf58-7064e5369db1",
>       "name": "Earbud brand tracking",
>       "mode": "BRAND",
>       "category": null,
>       "promptTopics": {},
>       "engines": ["CHATGPT", "GEMINI"],
>       "prompts": ["best wireless earbuds for commuting", "are cheap earbuds worth it"],
>       "aliases": ["Acme Audio", "Acme"],
>       "domains": ["acme-audio.example"],
>       "country": "US",
>       "intervalHours": 24,
>       "enabled": true,
>       "alertBelowPct": 40,
>       "competitors": [
>         { "name": "Northwind Audio", "aliases": ["Northwind Audio"], "source": "user" },
>         { "name": "Contoso Sound", "aliases": ["Contoso Sound", "Contoso"], "source": "user" }
>       ],
>       "competitorsReadAt": "2026-10-17T03:10:22.004Z",
>       "location": null,
>       "grid": null,
>       "engineSettings": { "CHATGPT": { "samples": 5 } },
>       "webhookUrl": null,
>       "analysis": false,
>       "nextRunAt": "2026-10-19T09:00:02.118Z",
>       "lastRunAt": "2026-10-18T09:00:01.730Z",
>       "shareAccess": "PRIVATE",
>       "shareSlug": null,
>       "createdAt": "2026-10-09T08:59:57.410Z",
>       "updatedAt": "2026-10-12T14:21:09.882Z"
>     },
>     "window": {
>       "since": "2026-10-16T00:00:00.000Z",
>       "until": "2026-10-18T00:00:00.000Z",
>       "previousSince": "2026-10-14T00:00:00.000Z",
>       "previousUntil": "2026-10-16T00:00:00.000Z",
>       "timezone": "UTC",
>       "bounds": "[since, until)"
>     },
>     "filters": { "engine": "CHATGPT", "prompt": null },
>     "stats": { "runs": 20, "mentioned": 9, "cited": 3, "competitorOnly": 7, "mentionRate": 45, "citationRate": 15, "competitorOnlyRate": 35 },
>     "previous": { "runs": 20, "mentioned": 12, "cited": 4, "competitorOnly": 5, "mentionRate": 60, "citationRate": 20, "competitorOnlyRate": 25 },
>     "changes": { "mentionRatePp": -15, "citationRatePp": -5 },
>     "engineRates": [
>       { "engine": "CHATGPT", "runs": 20, "mentioned": 9, "cited": 3, "competitorOnly": 7, "mentionRate": 45, "citationRate": 15, "competitorOnlyRate": 35 }
>     ],
>     "series": [
>       {
>         "day": "2026-10-16",
>         "engine": "CHATGPT",
>         "partial": false,
>         "runs": 10,
>         "mentioned": 5,
>         "cited": 2,
>         "competitorOnly": 3,
>         "mentionRate": 50,
>         "citationRate": 20,
>         "competitorOnlyRate": 30
>       },
>       {
>         "day": "2026-10-17",
>         "engine": "CHATGPT",
>         "partial": false,
>         "runs": 10,
>         "mentioned": 4,
>         "cited": 1,
>         "competitorOnly": 4,
>         "mentionRate": 40,
>         "citationRate": 10,
>         "competitorOnlyRate": 40
>       }
>     ],
>     "brands": [
>       {
>         "name": "Northwind Audio",
>         "mentions": 10,
>         "sampleSize": 20,
>         "mentionRate": 50,
>         "shareOfVoice": 43.47826086956522,
>         "previousMentionRate": 40,
>         "previousShareOfVoice": 33.33333333333333,
>         "configured": true
>       },
>       {
>         "name": "__you__",
>         "mentions": 9,
>         "sampleSize": 20,
>         "mentionRate": 45,
>         "shareOfVoice": 39.130434782608695,
>         "previousMentionRate": 60,
>         "previousShareOfVoice": 50,
>         "configured": true
>       },
>       {
>         "name": "Contoso Sound",
>         "mentions": 4,
>         "sampleSize": 20,
>         "mentionRate": 20,
>         "shareOfVoice": 17.391304347826086,
>         "previousMentionRate": 20,
>         "previousShareOfVoice": 16.666666666666664,
>         "configured": true
>       }
>     ],
>     "voiceSeries": [
>       { "day": "2026-10-16", "name": "__you__", "mentions": 5, "runs": 10, "mentionRate": 50, "shareOfVoice": 41.66666666666667 },
>       { "day": "2026-10-16", "name": "Northwind Audio", "mentions": 5, "runs": 10, "mentionRate": 50, "shareOfVoice": 41.66666666666667 },
>       { "day": "2026-10-16", "name": "Contoso Sound", "mentions": 2, "runs": 10, "mentionRate": 20, "shareOfVoice": 16.666666666666664 },
>       { "day": "2026-10-17", "name": "__you__", "mentions": 4, "runs": 10, "mentionRate": 40, "shareOfVoice": 36.36363636363637 },
>       { "day": "2026-10-17", "name": "Northwind Audio", "mentions": 5, "runs": 10, "mentionRate": 50, "shareOfVoice": 45.45454545454545 },
>       { "day": "2026-10-17", "name": "Contoso Sound", "mentions": 2, "runs": 10, "mentionRate": 20, "shareOfVoice": 18.181818181818183 }
>     ],
>     "prompts": [
>       {
>         "prompt": "are cheap earbuds worth it",
>         "runs": 10,
>         "mentioned": 3,
>         "cited": 0,
>         "competitorOnly": 4,
>         "mentionRate": 30,
>         "citationRate": 0,
>         "competitorOnlyRate": 40,
>         "previous": { "runs": 10, "mentioned": 5, "cited": 1, "competitorOnly": 3, "mentionRate": 50, "citationRate": 10, "competitorOnlyRate": 30 },
>         "engines": [
>           {
>             "prompt": "are cheap earbuds worth it",
>             "engine": "CHATGPT",
>             "runs": 10,
>             "mentioned": 3,
>             "cited": 0,
>             "competitorOnly": 4,
>             "mentionRate": 30,
>             "citationRate": 0,
>             "competitorOnlyRate": 40,
>             "previous": { "runs": 10, "mentioned": 5, "cited": 1, "competitorOnly": 3, "mentionRate": 50, "citationRate": 10, "competitorOnlyRate": 30 },
>             "mentionRateChangePp": -20,
>             "topCompetitor": "Northwind Audio",
>             "topCompetitorRate": 60,
>             "evidenceTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63",
>             "mentionTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63",
>             "latestTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63"
>           }
>         ]
>       },
>       {
>         "prompt": "best wireless earbuds for commuting",
>         "runs": 10,
>         "mentioned": 6,
>         "cited": 3,
>         "competitorOnly": 3,
>         "mentionRate": 60,
>         "citationRate": 30,
>         "competitorOnlyRate": 30,
>         "previous": { "runs": 10, "mentioned": 7, "cited": 3, "competitorOnly": 2, "mentionRate": 70, "citationRate": 30, "competitorOnlyRate": 20 },
>         "engines": [
>           {
>             "prompt": "best wireless earbuds for commuting",
>             "engine": "CHATGPT",
>             "runs": 10,
>             "mentioned": 6,
>             "cited": 3,
>             "competitorOnly": 3,
>             "mentionRate": 60,
>             "citationRate": 30,
>             "competitorOnlyRate": 30,
>             "previous": { "runs": 10, "mentioned": 7, "cited": 3, "competitorOnly": 2, "mentionRate": 70, "citationRate": 30, "competitorOnlyRate": 20 },
>             "mentionRateChangePp": -10,
>             "topCompetitor": "Northwind Audio",
>             "topCompetitorRate": 40,
>             "evidenceTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61",
>             "mentionTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61",
>             "latestTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61"
>           }
>         ]
>       }
>     ],
>     "opportunities": [
>       {
>         "prompt": "are cheap earbuds worth it",
>         "engine": "CHATGPT",
>         "runs": 10,
>         "mentioned": 3,
>         "cited": 0,
>         "competitorOnly": 4,
>         "mentionRate": 30,
>         "citationRate": 0,
>         "competitorOnlyRate": 40,
>         "previous": { "runs": 10, "mentioned": 5, "cited": 1, "competitorOnly": 3, "mentionRate": 50, "citationRate": 10, "competitorOnlyRate": 30 },
>         "mentionRateChangePp": -20,
>         "topCompetitor": "Northwind Audio",
>         "topCompetitorRate": 60,
>         "evidenceTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63",
>         "mentionTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63",
>         "latestTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a63"
>       },
>       {
>         "prompt": "best wireless earbuds for commuting",
>         "engine": "CHATGPT",
>         "runs": 10,
>         "mentioned": 6,
>         "cited": 3,
>         "competitorOnly": 3,
>         "mentionRate": 60,
>         "citationRate": 30,
>         "competitorOnlyRate": 30,
>         "previous": { "runs": 10, "mentioned": 7, "cited": 3, "competitorOnly": 2, "mentionRate": 70, "citationRate": 30, "competitorOnlyRate": 20 },
>         "mentionRateChangePp": -10,
>         "topCompetitor": "Northwind Audio",
>         "topCompetitorRate": 40,
>         "evidenceTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61",
>         "mentionTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61",
>         "latestTaskId": "6f1c2a9e-3b4d-4e5f-8a7b-1c2d3e4f5a61"
>       }
>     ],
>     "quality": {
>       "comparable": true,
>       "comparisonReason": null,
>       "scoringVersions": ["3f9a6c1e8b2d4f7a9c0e1b3d5f7a9c1e3b5d7f9a1c3e5b7d9f1a3c5e7b9d1f3a"],
>       "noAnswerObservations": 0,
>       "unknownObservations": 0,
>       "noAnswerIncluded": true,
>       "historicalFailures": null,
>       "sampleSize": 20,
>       "previousSampleSize": 20,
>       "configuredCells": 2,
>       "observedCells": 2,
>       "missingCells": 0,
>       "lowSample": true,
>       "partialDays": [],
>       "denominator": "scored_answers",
>       "shareOfVoiceDenominator": "tracked_brand_mentions",
>       "trackedBrandMentions": 23,
>       "answerTextLimit": 8000,
>       "scoring": "collection_time_definitions",
>       "failedTasksIncluded": false
>     },
>     "pauses": [],
>     "health": { "completed": 12, "failed": 0, "pending": 0, "topError": null },
>     "healthScope": "recent_visible_tasks"
>   }
> }
> ```

Reading it: the brand was named in 9 of 20 ChatGPT answers (45%), down 15 points from the two days
before. Northwind Audio was named in more answers, and "are cheap earbuds worth it" is the weakest
prompt, with 4 answers that named a competitor and not the brand. `quality.lowSample` is `true`, so treat
the change as a signal to check, not a trend.

## Response sections

| Field | Contents |
| - | - |
| `monitor` | The stored monitor definition. |
| `window` | `since`, `until`, `previousSince`, `previousUntil`, `timezone` (`UTC`) and `bounds` (`[since, until)`). `previousUntil` always equals `since`. |
| `filters` | The filters applied, resolved: the canonical engine id, the exact prompt, or `null`. |
| `stats`, `previous` | Counts and rates for the window and for the window before it. See [Rate objects](#rate-objects). |
| `changes` | `mentionRatePp` and `citationRatePp`: the change in percentage points, or `null` when the comparison is withheld. |
| `engineRates` | The rate object per engine. |
| `series` | The rate object per UTC day and engine, with `partial: true` on a day the window covers only in part. |
| `brands` | Your brand (`__you__`) and every competitor named in the window, most mentions first. See [Brands and share of voice](#brands-and-share-of-voice). |
| `voiceSeries` | Per UTC day and brand: `mentions`, `runs` (the day's answers), `mentionRate` and `shareOfVoice`. |
| `prompts` | Per prompt, weakest mention rate first: the rate object, `previous`, and `engines`, one cell per engine. |
| `opportunities` | Cells where a competitor was named and your brand was not (`competitorOnly` above 0), most such answers first. The list to work from. |
| `quality` | What the sample is made of and what the numbers cannot say. See [Quality](#quality). |
| `pauses` | Pauses that overlap the window, oldest first: `pausedAt` and `resumedAt` (`null` while paused). |
| `health`, `healthScope` | Recent task status, a separate scope from the report. See [Health](#health). |

### Rate objects

`stats`, `previous`, each `engineRates` and `series` entry, each prompt and each cell carry the same
fields:

| Field | Meaning |
| - | - |
| `runs` | Scored answers. The denominator of every rate below. |
| `mentioned` | Answers that named your brand. |
| `cited` | Answers that cited one of your domains. |
| `competitorOnly` | Answers that named at least one competitor and not your brand. |
| `mentionRate`, `citationRate`, `competitorOnlyRate` | `100 × count / runs`, or `null` when `runs` is 0. |

### Cells

A cell is one prompt on one engine. Besides the rate object and `previous`, it carries:

| Field | Meaning |
| - | - |
| `mentionRateChangePp` | The cell's change in points, or `null` when the comparison is withheld. |
| `topCompetitor` | The competitor named in the most of the cell's answers, or `null`. |
| `topCompetitorRate` | That competitor's mention rate in the cell, or `null` when some of the cell's answers predate stored scoring context. |
| `evidenceTaskId` | The latest answer that named a competitor and not your brand. |
| `mentionTaskId` | The latest answer that named your brand. |
| `latestTaskId` | The latest answer. |

Each id is `null` when no answer qualifies. Open one with
[`GET /v1/monitors/{id}/answers/{taskId}`](/monitors/evidence#read-one-answer).

### Brands and share of voice

Each entry in `brands` has `name`, `mentions`, `sampleSize`, `mentionRate`, `shareOfVoice`,
`previousMentionRate`, `previousShareOfVoice` and `configured` (`false` for a brand named in the window
that is no longer on the monitor).

## What the numbers mean

`GET /v1/monitors/capabilities` returns these definitions as `metrics`, so a client can show them next to
the numbers.

* **`mentionRate`** is `100 × mentioned / scored answers`, for the window, each engine, each day and each
  cell. It is weighted by answers, not averaged across engines, so a busy engine is not outvoted by a
  quiet one.
* **`citationRate`** has the same shape for answers that cited one of your domains. With no domains it is
  always 0, because citation tracking is off.
* **A brand's rate divides by its own `sampleSize`.** For your brand that is every scored answer. For a
  competitor it is only the answers scored while it was on the monitor, so a competitor added today is
  measured from today. A competitor's `mentionRate` is `null` when some answers in the window were scored
  before scoring context was stored, because what they were matched against is unknown.
* **`shareOfVoice`** is `100 × that brand's mentions / all tracked brand mentions` in the window, so the
  shares of one window add up to 100 (`quality.trackedBrandMentions` is the denominator). It compares
  brands inside the answers you collected for these prompts. It is not market share and not a ranking of
  visibility.
* **`competitorOnly`** and `opportunities` count answers that named a competitor while your brand was
  absent: the gap you can act on.
* **`null` is not 0.** A rate is `null` when there were no answers to divide by. 0 means there were
  answers and none matched.
* **An answer with no text counts as not mentioned.** A completed task that returned no answer stays in
  the denominator; `quality.noAnswerObservations` counts them. A **failed** task is excluded from every
  rate and appears only in `health`. A broken engine shrinks the sample rather than showing up as absence.
* **`position`** on a scored answer is the character offset of the first match of your brand: a proxy for
  prominence, not a rank. It is `null` when the brand is absent.

### When changes are withheld

`changes`, each cell's `mentionRateChangePp`, and each brand's `previousMentionRate` and
`previousShareOfVoice` are `null`, and `quality.comparable` is `false`, when the two windows cannot be
compared. `quality.comparisonReason` says why:

| `comparisonReason` | Meaning |
| - | - |
| `insufficient_periods` | One of the two windows has no answers. |
| `legacy_scoring_unknown` | Some answers were scored before the definition they were scored against was stored. |
| `scoring_definitions_changed` | The aliases, domains, competitors or country changed between the answers in the two windows. |

Every answer keeps the definition it was scored with, and `quality.scoringVersions` lists the distinct
definitions across both windows (`legacy` for answers without one). Changing your aliases or competitors
never rewrites past answers. The one exception is the weekly competitor read: when the competitors it
finds change, the monitor's stored answers are scored again against the new list.

### Quality

| Field | Meaning |
| - | - |
| `comparable`, `comparisonReason` | Whether the change figures are shown, and why not. |
| `scoringVersions` | The distinct scoring definitions in both windows. |
| `scoring` | Always `collection_time_definitions`: answers are scored with the definition in force when they arrived. |
| `sampleSize`, `previousSampleSize` | Scored answers in each window. |
| `lowSample` | `true` below 30 scored answers in the window. |
| `configuredCells`, `observedCells`, `missingCells` | Prompt × engine cells the filters cover, cells with at least one answer, and the difference. |
| `partialDays` | UTC days the window cuts, or that are not over yet. A partial day's lower count is arithmetic, not a decline. |
| `noAnswerObservations` | Completed answers with no text, counted as not mentioned. |
| `unknownObservations` | Answers scored before scoring context was stored. |
| `noAnswerIncluded`, `failedTasksIncluded`, `historicalFailures` | Always `true`, `false` and `null`: answers without text are in the denominator, failed tasks are not, and failures are never reconstructed from history. |
| `denominator`, `shareOfVoiceDenominator` | `scored_answers` and `tracked_brand_mentions`. |
| `trackedBrandMentions` | The share of voice denominator. |
| `answerTextLimit` | `8000`: stored answer text is cut at 8,000 characters. |

### Health

`health` has `completed`, `failed`, `pending` and `topError` (the most common error code among failed
tasks) for the monitor's tasks that are in flight or finished in the last 24 hours. `healthScope` is
always `recent_visible_tasks`. It is a diagnostic for runs, independent of the window, and never part of
a rate's denominator.

## Poll while a run is in flight

Every call returns the full report for the window and filters. While a run is in flight,
`health.pending` counts its tasks that are still running. Read the report again once it reaches 0.

## Category reports

A [category monitor](/monitors.md#category-monitors) returns a different body from the same endpoint, with
the same `window`, `filters`, `quality`, `pauses` and `health`:

* `stats` and `previous` hold `runs`, `named` (answers that named at least one tracked brand) and
  `namedRate`. `changes.namedRatePp` is the change in points.
* `category` holds the ranking:

| Field | Contents |
| - | - |
| `category.name` | The monitor's `category`. |
| `category.brands` | Every tracked brand and every brand the answers named, most mentions first: `name`, `rank`, `mentions`, `sampleSize`, `mentionRate`, `shareOfVoice`, `previousMentionRate`, `previousShareOfVoice`, `changePp` and `configured`. |
| `category.topics` | One row per sub-field (`topic: null` is the whole category): `prompts`, `runs`, `named`, `namedRate` and `leaders`, the three brands named most. |
| `category.engines` | One row per engine with answers in the window: `runs`, `named`, `namedRate` and `leaders`. |
| `category.series` | Per UTC day, the five leading tracked brands: `mentions`, `sampleSize`, `runs`, `mentionRate` and `partial`. |
| `category.prompts` | One row per prompt: `topic`, `retired` (`true` for a prompt no longer on the monitor), `runs`, `named`, `namedRate`, `leaders`, and `engines`, each with `runs`, `named` and an `evidenceTaskId` for the latest answer that named a brand. |

For example, one `category.brands` entry:

```json theme={"theme":"css-variables"}
{
  "name": "Northwind Sun",
  "mentions": 18,
  "sampleSize": 40,
  "mentionRate": 45,
  "shareOfVoice": 30,
  "previousMentionRate": 40,
  "previousShareOfVoice": 25,
  "changePp": 5,
  "configured": true,
  "rank": 1
}
```

* **`rank`** orders brands by the number of answers that name them. A brand no answer named has
  `rank: null`.
* **`mentionRate`** divides by the brand's own `sampleSize`: the answers scored while it was on the list.
* **`shareOfVoice`** is `100 × that brand's mentions / all brand mentions` in the window, so the shares add
  up to 100.

## Errors and limits

* The window is at most 90 days.
* Invalid parameters return `400 VALIDATION_ERROR` with a message naming the problem: `days` with `since`
  or `until`, only one of `since` and `until`, a timestamp without a timezone, a span over 90 days, an
  `until` in the future, an engine that cannot be monitored, a prompt over 2,000 characters, or a
  repeated parameter.
* A report too large to aggregate returns `400 VALIDATION_ERROR` with "This report is too large". Narrow
  the window, engine or prompt.

See [Monitors](/monitors.md#errors) for the codes every monitor endpoint shares.

## Next steps

> **[Sources and answers](/monitors/evidence.md)**
>
> The cited pages and the answers behind each number.

> **[Events and alerts](/monitors/events-and-alerts.md)**
>
> Get notified when answers change.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.