Brand Rankings
Per-entity performance ranking for a tracked domain — the user's brand plus every dedicated competitor.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/brand-rankings?domain_id=8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3&days=30' \
--header 'Authorization: Bearer ak_live_xxx'
import httpx, os
resp = httpx.get(
"https://api.aiclicks.io/api/v1/brand-rankings",
params={
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for row in resp.json()["data"]["items"]:
pos = row["avg_position"] if row["avg_position"] is not None else "n/a"
print(f"{row['name']:<20} mentions={row['mentions']:>4} "
f"visibility={row['visibility']:>5.2f}% sov={row['sov']:>5.2f}% pos={pos}")
const url = new URL("https://api.aiclicks.io/api/v1/brand-rankings");
url.searchParams.set("domain_id", "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3");
url.searchParams.set("days", "30");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.AICLICKS_API_KEY}` },
});
const { data } = await resp.json();
for (const row of data.items) {
const pos = row.avg_position ?? "n/a";
console.log(`${row.name}: mentions=${row.mentions} visibility=${row.visibility}% sov=${row.sov}% pos=${pos}`);
}
{
"data": {
"items": [
{
"id": "brand",
"name": "Your Brand",
"website": null,
"is_brand": true,
"mentions": 1167,
"visibility": 69.09,
"sov": 69.09,
"avg_position": 4.4,
"prompts_mentioned": 246,
"total_prompts": 335
},
{
"id": "9c4f2e1a-6b08-4b3a-b5a1-c1d2e3f4a5b6",
"name": "keyword.com",
"website": "keyword.com",
"is_brand": false,
"mentions": 520,
"visibility": 30.79,
"sov": 30.79,
"avg_position": 1.2,
"prompts_mentioned": 231,
"total_prompts": 335
},
{
"id": "ab12cd34-ef56-7890-12ab-cd34ef567890",
"name": "x.com",
"website": "x.com",
"is_brand": false,
"mentions": 2,
"visibility": 0.12,
"sov": 0.12,
"avg_position": 2.0,
"prompts_mentioned": 2,
"total_prompts": 335
}
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"generated_at": "2026-06-17T10:00:11.218Z"
}
{
"detail": "domain_id query parameter is required. List the domains this key can access with GET /api/v1/domains, then pass ?domain_id=<uuid>."
}
{
"detail": "Invalid or revoked API key"
}
{
"detail": "API access is not enabled for this team. Contact support@aiclicks.io."
}
{
"detail": "Domain not found"
}
{
"detail": "Too many requests. Please try again later."
}
Returns one row per tracked entity — the user's own brand first, then each dedicated competitor — ranked by mention count. Use it to answer "how is my brand doing against the competitors I told aiclicks to track?" in a single call, without paging through the full prompts surface.
Only dedicated competitors appear (the ones the user explicitly added under Brand Rankings or competitor discovery pages). Auto-discovered competitor mentions are deliberately excluded.
domain_id is a required query parameter. Use GET /api/v1/domains to discover which domains the calling key can access.
Authorizations
Your API key formatted as Bearer ak_live_<your-key>. Create one in the dashboard under Settings → Developers.
Optional UUID for log correlation. If omitted, we generate one and echo it back in the response.
Query parameters
UUID of the domain. Find domains via GET /api/v1/domains. Omitting this returns 400.
Look-back window, 1–365. Defaults to 30.
Response
The ranking payload.
One row per tracked entity. The user's own brand is included as { "id": "brand", "is_brand": true }. Competitors that follow are all dedicated competitors for this domain — auto-discovered mentions are not surfaced. Sorted by mentions descending.
UUID of the entity, or the literal "brand" for the user's own brand row.
Display name. Brand row uses "Your Brand".
Domain string for competitors. null for the brand row.
true for the brand row, false for every competitor row.
Number of AI responses in the window where this entity was mentioned at least once (binary count, not a sum of individual mention counts).
mentions / total_responses_in_window * 100. 0–100, two decimals. Same definition as /api/v1/visibility-time-series, aggregated to a single number over the window.
Share-of-voice: this entity's mentions divided by the sum of every tracked entity's mentions in the window, times 100. Two decimals. Window-aggregate (not a mean of daily ratios), so values match the SOV column on the dashboard's Brand Rankings page.
Average rank where this entity appeared in cited / answered lists, restricted to responses where it actually appeared. null if the entity never appeared in the window — null does not mean position 0.
Number of distinct tracked prompts whose responses mentioned this entity at least once.
Total number of tracked prompts on this domain in the window. The same value is echoed on every row — use it as the denominator for prompts_mentioned.
Echo of the requested domain.
Echo of the requested window.
ISO-8601 timestamp of when the server produced (or cached) this response.
Response headers
| Header | Description |
|---|---|
X-Cache | HIT or MISS. Indicates whether the response came from cache. |
X-Request-Id | Unique request id. Echoes incoming if you set one. |
X-RateLimit-Limit | Max requests per minute for this key. |
X-RateLimit-Remaining | Requests remaining in current minute. |
X-RateLimit-Reset | Unix epoch seconds when the window resets. |
Caching
Cached for 1 hour per (domain_id, days). Newly completed analyses appear after the TTL expires.
How the ranking is computed
For the brand and each dedicated competitor in the window:
-
Count every AI response that ran on a tracked prompt for this domain — the denominator.
-
Count responses where the entity was mentioned at least once (
mentions > 0per row) — the numerator forvisibility. -
Sum that binary count across all tracked entities; each entity's
sovis its count divided by that sum, times 100. -
Average the cited
positionfield across responses where the entity actually appeared — that'savg_position. -
Count distinct prompts whose responses mentioned the entity at least once — that's
prompts_mentioned.total_promptsis the count of distinct prompts that produced any response in the window.
Sort by mentions descending, with the brand row in its natural rank position.
Both visibility and sov use binary counting (responses with ≥1 mention), not sum-of-mention-counts. A response naming the brand five times still counts as one — this matches the SOV column on the Brand Rankings page in the dashboard.
Errors
domain_id query parameter missing. Body points you at /api/v1/domains.
Missing, malformed, or revoked API key.
Team's developer_access flag is off, the domain belongs to a team your API key is not scoped to, or your allowed_domains allowlist excludes it.
domain_id is malformed, does not exist, or your user is not a member of its team.
Rate limit exceeded. Inspect the Retry-After header for how long to wait.
Empty result
If no analyses ran in the window, the response is a successful 200 with a brand row at zero metrics and no competitor rows:
{
"data": {
"items": [
{
"id": "brand",
"name": "Your Brand",
"website": null,
"is_brand": true,
"mentions": 0,
"visibility": 0,
"sov": 0,
"avg_position": null,
"prompts_mentioned": 0,
"total_prompts": 0
}
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"generated_at": "2026-06-17T10:00:11.218Z"
}