Get GEO Matrix
curl --request GET \
--url https://api.example.com/api/v1/brands/{brandId}/matrix \
--header 'Authorization: <authorization>'import requests
url = "https://api.example.com/api/v1/brands/{brandId}/matrix"
headers = {"Authorization": "<authorization>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<authorization>'}};
fetch('https://api.example.com/api/v1/brands/{brandId}/matrix', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/brands/{brandId}/matrix",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/brands/{brandId}/matrix"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/v1/brands/{brandId}/matrix")
.header("Authorization", "<authorization>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/brands/{brandId}/matrix")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_body{
"success": true,
"brand": {
"id": "<string>",
"name": "<string>"
},
"granularity": "<string>",
"providers": [
{
"id": "<string>",
"name": "<string>"
}
],
"rows": [
{
"id": "<string>",
"name": "<string>",
"promptCount": 123,
"mentionRate": 123,
"coverage": {
"count": 123,
"total": 123,
"percentage": 123
},
"cells": [
{
"provider": "<string>",
"score": 123,
"subScores": {
"mentionRate": 123,
"shareOfVoice": 123,
"citationRate": 123,
"sentiment": 123
},
"ranking": {
"mentionRate": {},
"shareOfVoice": {},
"citationRate": {},
"sentiment": {}
},
"citations": 123,
"position": 123,
"topCompetitor": "<string>",
"topCompetitors": [
{}
],
"topSources": [
{}
]
}
]
}
],
"providerAverages": [
{
"provider": "<string>",
"score": 123,
"mentionRate": 123,
"shareOfVoice": 123,
"citationRate": 123,
"sentiment": 123
}
],
"summary": {
"totalRows": 123,
"averageMentionRate": 123,
"topPerforming": {},
"needsAttention": {}
}
}Cockpit
Get GEO Matrix
Get the GEO visibility matrix for your brand across providers and dimensions
GET
/
api
/
v1
/
brands
/
{brandId}
/
matrix
Get GEO Matrix
curl --request GET \
--url https://api.example.com/api/v1/brands/{brandId}/matrix \
--header 'Authorization: <authorization>'import requests
url = "https://api.example.com/api/v1/brands/{brandId}/matrix"
headers = {"Authorization": "<authorization>"}
response = requests.get(url, headers=headers)
print(response.text)const options = {method: 'GET', headers: {Authorization: '<authorization>'}};
fetch('https://api.example.com/api/v1/brands/{brandId}/matrix', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/api/v1/brands/{brandId}/matrix",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/api/v1/brands/{brandId}/matrix"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("Authorization", "<authorization>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://api.example.com/api/v1/brands/{brandId}/matrix")
.header("Authorization", "<authorization>")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/api/v1/brands/{brandId}/matrix")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
request["Authorization"] = '<authorization>'
response = http.request(request)
puts response.read_body{
"success": true,
"brand": {
"id": "<string>",
"name": "<string>"
},
"granularity": "<string>",
"providers": [
{
"id": "<string>",
"name": "<string>"
}
],
"rows": [
{
"id": "<string>",
"name": "<string>",
"promptCount": 123,
"mentionRate": 123,
"coverage": {
"count": 123,
"total": 123,
"percentage": 123
},
"cells": [
{
"provider": "<string>",
"score": 123,
"subScores": {
"mentionRate": 123,
"shareOfVoice": 123,
"citationRate": 123,
"sentiment": 123
},
"ranking": {
"mentionRate": {},
"shareOfVoice": {},
"citationRate": {},
"sentiment": {}
},
"citations": 123,
"position": 123,
"topCompetitor": "<string>",
"topCompetitors": [
{}
],
"topSources": [
{}
]
}
]
}
],
"providerAverages": [
{
"provider": "<string>",
"score": 123,
"mentionRate": 123,
"shareOfVoice": 123,
"citationRate": 123,
"sentiment": 123
}
],
"summary": {
"totalRows": 123,
"averageMentionRate": 123,
"topPerforming": {},
"needsAttention": {}
}
}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.
This endpoint returns a cross-tabulation of your brand’s visibility. See Performance for aggregated metrics and Competitor for entity structures used in
topCompetitors.Get Matrix
string
required
Bearer token. Example:
Bearer qw-api-xxxGET /api/v1/brands/{brandId}/matrix
Path Parameters
string
required
The unique identifier of the brand
Query Parameters
string
Group rows by:
topics (default), tags, prompts, or funnelnumber
Number of days to include. Default: 30
string
Start date (ISO 8601 format). Overrides
period if provided with endDatestring
End date (ISO 8601 format). Overrides
period if provided with startDatestring
Filter by AI provider. Supports comma-separated multi-select (e.g.,
chatgpt,claude).string
Filter by topic ID (keywordId). Supports comma-separated multi-select (e.g.,
id1,id2).string
Filter by tag ID. Supports comma-separated multi-select (e.g.,
id1,id2).number
Max rows to return. Default: 50, max: 100
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
boolean
Indicates if the request was successful
string
The granularity used for this matrix (
topics, tags, prompts, or funnel)array
array
Matrix rows, one per topic/tag/prompt/funnel stage
Show Row structure
Show Row structure
string
Row identifier (topic ID, tag ID, prompt ID, or funnel stage)
string
Display name of the row
number
Number of distinct prompts in this row
number
Row-level brand mention rate (%) across all providers
object
array
One cell per provider
Show Cell structure
Show Cell structure
string
Provider ID
number
Composite GEO score (0-100)
object
object
number
Number of source citations
number
Best (minimum) position your brand reaches across this cell’s responses (lower is better;
null if not mentioned)string
Name of the leading competitor in this cell (
null if none)array
Top competitors in this cell, each with
name, mentions, avgPosition, and relationshiparray
Top cited sources in this cell
array
Per-provider average metrics across all returned rows.
Show Provider average object
Show Provider average object
object
Example Request
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
{
"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 |
⌘I

