Competitor rankings
The leaderboard. Your brand and every active competitor, ranked by visibility, each with market share, sentiment and average first-mention rank. Rank 1 is the most visible.
With compare_to_previous you also get per-row deltas and a movers block naming who gained and
who lost — which is usually the actual question behind “how are we doing”.
GET /v1/brands/{brand_id}/competitors/rankingsAuthorization
| Header | Type | Required |
|---|---|---|
Authorization | Bearer asky_sk_… | required |
Path parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
brand_id | uuid | required | From List brands |
Query parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | integer | optional | Rows per page, 1 to 100. Defaults to 20. |
cursor | string | optional | Opaque cursor from the previous response. Treat it as a token, never construct one. |
start_date | YYYY-MM-DD | optional | Inclusive lower bound, YYYY-MM-DD in UTC. Narrows the population before metrics are computed. |
end_date | YYYY-MM-DD | optional | Inclusive upper bound, YYYY-MM-DD in UTC. Narrows the population before metrics are computed. |
compare_to_previous | boolean | optional | Also return the prior equal-length period and per-row deltas. |
topic_id | uuid, repeatable | optional | Restrict to these topics. From List topics. Includes the topic and its subtopics. A root topic returns everything beneath it; a subtopic returns only itself. Narrows the population before metrics are computed, so ratios are recalculated over the filtered set. |
engine | string, repeatable | optional | Restrict to these AI search engines, by slug. From List engines. Narrows the population before metrics are computed. |
country | string, repeatable | optional | Restrict to these execution country codes. Narrows the population before metrics are computed. |
tag_id | uuid, repeatable | optional | Restrict to prompts carrying these tags. From List tags. Narrows the population before metrics are computed. |
tag_match_mode | string | optional | How to combine tag_id values. Defaults to ‘any’. One of: any, all. |
Request
cURL
curl --request GET \
--url 'https://api.askylabs.com/v1/brands/242546de-4cee-4a7d-952e-f6aa60c63ef8/competitors/rankings?compare_to_previous=true' \
--header 'Authorization: Bearer <api-key>'Response
200
{
"data": [
{
"rank": 1,
"name": "Asky",
"is_our_brand": true,
"visibility_pct": 34.2,
"market_share_pct": 24.1,
"sentiment_score": 71.4,
"avg_rank": 2.8,
"previous": {
"rank": 2,
"visibility_pct": 29.7,
"market_share_pct": 22
},
"rank_change": 1,
"visibility_delta": 4.5,
"market_share_delta": 2.1
}
],
"pagination": {
"limit": 20,
"has_more": true,
"next_cursor": "eyJ2IjoxLCJvIjoyMCwibCI6MjB9"
},
"meta": {
"period": {
"start_date": "2026-08-06",
"end_date": "2026-08-13"
},
"brand_id": "242546de-4cee-4a7d-952e-f6aa60c63ef8",
"total_competitors": 6,
"previous_period": {
"start_date": "2026-07-30",
"end_date": "2026-08-06"
},
"movers": {
"gainers": [
{
"name": "Asky",
"is_our_brand": true,
"visibility_delta": 4.5,
"market_share_delta": 2.1
}
],
"losers": []
}
},
"request_id": "req_c72f18e0b34a49d5812c"
}Response fields
| Field | Type | Description |
|---|---|---|
data.brand_id | uuid | required |
data.period | object | required. { start_date, end_date } actually used. Read it before comparing endpoints — their defaults differ |
data.rankings | object[] | required, rank ascending |
data.rankings[].rank | integer | required. 1 is most visible |
data.rankings[].name | string | required |
data.rankings[].is_our_brand | boolean | required. Your row is in this list |
data.rankings[].visibility_pct | number | null | |
data.rankings[].market_share_pct | number | null | Share of voice by mention count |
data.rankings[].sentiment_score | number | null | 0–100 |
data.rankings[].avg_rank | number | null | Average first-mention position |
data.rankings[].rank_change | integer | null | Only with compare. Positive means climbed |
data.total_competitors | integer | required. Excludes your own row |
data.movers | object | Only with compare. { gainers, losers }, computed over the full set rather than the returned page |
request_id | string | required. Also returned as the x-request-id header. Quote it when contacting support |
Errors
| Status | Code | When |
|---|---|---|
| 400 | invalid_request | A parameter is unknown or malformed. The message names it |
| 401 | invalid_token | The key is missing, malformed, or does not exist |
| 401 | token_expired | The key passed its expiry date |
| 401 | token_revoked | The key was revoked |
| 404 | not_found | The brand does not exist, or this key is not allowed to reach it. The two are deliberately indistinguishable |
| 429 | rate_limited | Over 300 requests per minute. See the Retry-After header |
Notes
movers is computed over every entity, not just the returned page. Paging with limit never
changes who is reported as a mover.
Your own brand is a row in rankings, flagged with is_our_brand. A leaderboard that omitted
the subject would force every client to merge two responses to draw one table.
Last updated on