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

# Get GEO Matrix

> Get the GEO visibility matrix for your brand across providers and dimensions

Get the GEO visibility matrix: rows (topics, tags, prompts, or funnel stages) crossed with columns (AI providers), showing composite scores, sub-scores, rankings, citations, and top competitors per cell.

<Note>
  This endpoint returns a cross-tabulation of your brand's visibility. See [Performance](/developers/endpoints/performance) for aggregated metrics and [Competitor](/developers/entities#competitor) for entity structures used in `topCompetitors`.
</Note>

## Get Matrix

<ParamField header="Authorization" type="string" required>
  Bearer token. Example: `Bearer qw-api-xxx`
</ParamField>

```http theme={null}
GET /api/v1/brands/{brandId}/matrix
```

### Path Parameters

<ParamField path="brandId" type="string" required>
  The unique identifier of the brand
</ParamField>

### Query Parameters

<ParamField query="granularity" type="string">
  Group rows by: `topics` (default), `tags`, `prompts`, or `funnel`
</ParamField>

<ParamField query="period" type="number">
  Number of days to include. Default: 30
</ParamField>

<ParamField query="startDate" type="string">
  Start date (ISO 8601 format). Overrides `period` if provided with `endDate`
</ParamField>

<ParamField query="endDate" type="string">
  End date (ISO 8601 format). Overrides `period` if provided with `startDate`
</ParamField>

<ParamField query="provider" type="string">
  Filter by AI provider. Supports comma-separated multi-select (e.g., `chatgpt,claude`).
</ParamField>

<ParamField query="topic" type="string">
  Filter by topic ID (keywordId). Supports comma-separated multi-select (e.g., `id1,id2`).
</ParamField>

<ParamField query="tag" type="string">
  Filter by tag ID. Supports comma-separated multi-select (e.g., `id1,id2`).
</ParamField>

<ParamField query="limit" type="number">
  Max rows to return. Default: 50, max: 100
</ParamField>

### Granularity Options

| Value     | Groups rows by                 |
| --------- | ------------------------------ |
| `topics`  | Keywords/topics (default)      |
| `tags`    | Tags applied to prompts        |
| `prompts` | Individual monitored questions |
| `funnel`  | Funnel stages (TOFU/MOFU/BOFU) |

### Response

<ResponseField name="success" type="boolean">
  Indicates if the request was successful
</ResponseField>

<ResponseField name="brand" type="object">
  <Expandable title="Brand info">
    <ResponseField name="id" type="string">Brand ID</ResponseField>
    <ResponseField name="name" type="string">Brand name</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="granularity" type="string">
  The granularity used for this matrix (`topics`, `tags`, `prompts`, or `funnel`)
</ResponseField>

<ResponseField name="providers" type="array">
  List of AI providers used as columns. Each entry is an object with an `id` and a `name`.

  <Expandable title="Provider object">
    <ResponseField name="id" type="string">Provider ID (e.g., `chatgpt`, `perplexity`, `claude`)</ResponseField>
    <ResponseField name="name" type="string">Display name of the provider</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="rows" type="array">
  Matrix rows, one per topic/tag/prompt/funnel stage

  <Expandable title="Row structure">
    <ResponseField name="id" type="string">Row identifier (topic ID, tag ID, prompt ID, or funnel stage)</ResponseField>
    <ResponseField name="name" type="string">Display name of the row</ResponseField>
    <ResponseField name="promptCount" type="number">Number of distinct prompts in this row</ResponseField>
    <ResponseField name="mentionRate" type="number">Row-level brand mention rate (%) across all providers</ResponseField>

    <ResponseField name="coverage" type="object">
      Row-level coverage: how many responses in this row mention your brand. Reported per row, not per cell.

      <Expandable title="Coverage object">
        <ResponseField name="count" type="number">Responses in this row that mention your brand</ResponseField>
        <ResponseField name="total" type="number">Total responses in this row</ResponseField>
        <ResponseField name="percentage" type="number">Coverage percentage (0-100)</ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField name="cells" type="array">
      One cell per provider

      <Expandable title="Cell structure">
        <ResponseField name="provider" type="string">Provider ID</ResponseField>
        <ResponseField name="score" type="number">Composite GEO score (0-100)</ResponseField>

        <ResponseField name="subScores" type="object">
          <Expandable title="Sub-scores breakdown">
            <ResponseField name="mentionRate" type="number">Brand mention rate (%)</ResponseField>
            <ResponseField name="shareOfVoice" type="number">Share of voice (%)</ResponseField>
            <ResponseField name="citationRate" type="number">Source citation rate (%)</ResponseField>
            <ResponseField name="sentiment" type="number">Average sentiment (0-100)</ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="ranking" type="object">
          <Expandable title="Ranking per metric">
            <ResponseField name="mentionRate" type="object">Rank and total (e.g., `{"rank": 2, "total": 8}`)</ResponseField>
            <ResponseField name="shareOfVoice" type="object">Rank and total</ResponseField>
            <ResponseField name="citationRate" type="object">Rank and total</ResponseField>
            <ResponseField name="sentiment" type="object">Rank and total</ResponseField>
          </Expandable>
        </ResponseField>

        <ResponseField name="citations" type="number">Number of source citations</ResponseField>
        <ResponseField name="position" type="number">Best (minimum) position your brand reaches across this cell's responses (lower is better; `null` if not mentioned)</ResponseField>
        <ResponseField name="topCompetitor" type="string">Name of the leading competitor in this cell (`null` if none)</ResponseField>
        <ResponseField name="topCompetitors" type="array">Top competitors in this cell, each with `name`, `mentions`, `avgPosition`, and `relationship`</ResponseField>
        <ResponseField name="topSources" type="array">Top cited sources in this cell</ResponseField>
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="providerAverages" type="array">
  Per-provider average metrics across all returned rows.

  <Expandable title="Provider average object">
    <ResponseField name="provider" type="string">Provider ID</ResponseField>
    <ResponseField name="score" type="number">Average composite GEO score for this provider (0-100)</ResponseField>
    <ResponseField name="mentionRate" type="number">Average mention rate for this provider (%)</ResponseField>
    <ResponseField name="shareOfVoice" type="number">Average share of voice for this provider (%)</ResponseField>
    <ResponseField name="citationRate" type="number">Average citation rate for this provider (%)</ResponseField>
    <ResponseField name="sentiment" type="number">Average sentiment for this provider (0-100)</ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="summary" type="object">
  <Expandable title="Summary statistics">
    <ResponseField name="totalRows" type="number">Total number of rows</ResponseField>
    <ResponseField name="averageMentionRate" type="number">Average mention rate across all returned rows (%)</ResponseField>
    <ResponseField name="topPerforming" type="object">Highest mention-rate row, or `null`. Shape: `{ rowId, rowName, mentionRate }`.</ResponseField>
    <ResponseField name="needsAttention" type="object">Lowest non-zero mention-rate row below 50%, or `null`. Shape: `{ rowId, rowName, mentionRate }`.</ResponseField>
  </Expandable>
</ResponseField>

### Example Request

```bash theme={null}
curl -X GET "https://www.qwairy.co/api/v1/brands/cm1234567890abcdef/matrix?granularity=topics&period=30&limit=10" \
  -H "Authorization: Bearer qw-api-your-token-here"
```

### Example Response

```json theme={null}
{
  "success": true,
  "brand": {
    "id": "cm1234567890abcdef",
    "name": "My Brand"
  },
  "granularity": "topics",
  "providers": [
    { "id": "chatgpt", "name": "ChatGPT" },
    { "id": "perplexity", "name": "Perplexity" },
    { "id": "claude", "name": "Claude" }
  ],
  "rows": [
    {
      "id": "topic1",
      "name": "Product Reviews",
      "promptCount": 12,
      "mentionRate": 52.4,
      "coverage": { "count": 38, "total": 60, "percentage": 63.0 },
      "cells": [
        {
          "provider": "chatgpt",
          "score": 72,
          "subScores": {
            "mentionRate": 65.0,
            "shareOfVoice": 18.5,
            "citationRate": 30.2,
            "sentiment": 81.0
          },
          "ranking": {
            "mentionRate": { "rank": 2, "total": 8 },
            "shareOfVoice": { "rank": 3, "total": 8 },
            "citationRate": { "rank": 1, "total": 8 },
            "sentiment": { "rank": 1, "total": 8 }
          },
          "citations": 12,
          "position": 2,
          "topCompetitor": "Competitor A",
          "topCompetitors": [
            { "name": "Competitor A", "mentions": 9, "avgPosition": 2, "relationship": "DIRECT" },
            { "name": "Competitor B", "mentions": 6, "avgPosition": 3, "relationship": "DIRECT" }
          ],
          "topSources": [
            { "domain": "industry-news.com", "citations": 8 }
          ]
        },
        {
          "provider": "perplexity",
          "score": 58,
          "subScores": {
            "mentionRate": 50.0,
            "shareOfVoice": 12.3,
            "citationRate": 42.1,
            "sentiment": 76.0
          },
          "ranking": {
            "mentionRate": { "rank": 3, "total": 7 },
            "shareOfVoice": { "rank": 4, "total": 7 },
            "citationRate": { "rank": 2, "total": 7 },
            "sentiment": { "rank": 2, "total": 7 }
          },
          "citations": 18,
          "position": 3,
          "topCompetitor": "Competitor B",
          "topCompetitors": [
            { "name": "Competitor B", "mentions": 11, "avgPosition": 2, "relationship": "DIRECT" },
            { "name": "Competitor A", "mentions": 7, "avgPosition": 4, "relationship": "DIRECT" }
          ],
          "topSources": [
            { "domain": "tech-review.com", "citations": 14 }
          ]
        },
        {
          "provider": "claude",
          "score": 45,
          "subScores": {
            "mentionRate": 35.0,
            "shareOfVoice": 9.8,
            "citationRate": 15.0,
            "sentiment": 72.0
          },
          "ranking": {
            "mentionRate": { "rank": 5, "total": 6 },
            "shareOfVoice": { "rank": 4, "total": 6 },
            "citationRate": { "rank": 3, "total": 6 },
            "sentiment": { "rank": 3, "total": 6 }
          },
          "citations": 4,
          "position": 4,
          "topCompetitor": "Competitor A",
          "topCompetitors": [
            { "name": "Competitor A", "mentions": 5, "avgPosition": 3, "relationship": "DIRECT" }
          ],
          "topSources": [
            { "domain": "mybrand.com", "citations": 3 }
          ]
        }
      ]
    }
  ],
  "providerAverages": [
    { "provider": "chatgpt", "score": 72, "mentionRate": 65.0, "shareOfVoice": 18.5, "citationRate": 30.2, "sentiment": 81.0 },
    { "provider": "perplexity", "score": 58, "mentionRate": 50.0, "shareOfVoice": 12.3, "citationRate": 42.1, "sentiment": 76.0 },
    { "provider": "claude", "score": 45, "mentionRate": 35.0, "shareOfVoice": 9.8, "citationRate": 15.0, "sentiment": 72.0 }
  ],
  "summary": {
    "totalRows": 12,
    "averageMentionRate": 50,
    "topPerforming": {
      "rowId": "topic1",
      "rowName": "Product Reviews",
      "mentionRate": 52.4
    },
    "needsAttention": {
      "rowId": "topic7",
      "rowName": "Pricing",
      "mentionRate": 31.0
    }
  }
}
```

### Error Responses

| Status | Code                | Description                                         |
| ------ | ------------------- | --------------------------------------------------- |
| 400    | `INVALID_PARAMETER` | Invalid query parameter (e.g., unknown granularity) |
| 401    | `INVALID_TOKEN`     | Authentication failed                               |
| 404    | `BRAND_NOT_FOUND`   | Brand doesn't exist or not accessible               |
