Visibility by engine
Brand and competitor visibility broken out per engine, in one call. ChatGPT and Perplexity can disagree sharply about who leads a category, and an aggregate number hides that entirely.
Each engine carries your position, the leader, and the strongest competitors on that engine — so “who is beating me, and where” is one request rather than a fan-out per engine.
GET /v1/brands/{brand_id}/visibility/enginesAuthorization
| 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. |
top_competitors | integer | optional | Competitors shown per engine. |
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. |
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. |
Request
cURL
curl --request GET \
--url 'https://api.askylabs.com/v1/brands/242546de-4cee-4a7d-952e-f6aa60c63ef8/visibility/engines?compare_to_previous=true' \
--header 'Authorization: Bearer <api-key>'Response
200
{
"data": [
{
"engine": "ChatGPT",
"executions": 720,
"leader": "Peec AI",
"brand": {
"name": "Asky",
"rank": 2,
"visibility_pct": 31.4,
"market_share_pct": 22.8,
"sentiment_score": 70.2,
"avg_rank": 2.9,
"previous": {
"visibility_pct": 26,
"market_share_pct": 20.1,
"rank": 3
},
"visibility_delta": 5.4,
"market_share_delta": 2.7,
"rank_change": 1
},
"top_competitors": [
{
"name": "Peec AI",
"rank": 1,
"visibility_pct": 38.9,
"market_share_pct": 28.4
}
]
}
],
"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",
"previous_period": {
"start_date": "2026-07-30",
"end_date": "2026-08-06"
}
},
"request_id": "req_ab3e71cd0294f6b18d4e"
}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.engines | object[] | required |
data.engines[].engine | string | required |
data.engines[].executions | integer | required |
data.engines[].leader | string | null | Rank-1 entity on this engine. May be you |
data.engines[].brand | object | null | Your row: rank, visibility_pct, market_share_pct, sentiment_score, avg_rank. null if absent from this engine entirely |
data.engines[].top_competitors | object[] | required. Same shape, ranked |
data.previous_period | object | Only with compare_to_previous |
data.unavailable_engines | string[] | Engines that could not be read on this attempt. Not the same as zero |
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
rank_change is positive when you climbed, because a lower rank number is better.
unavailable_engines means “could not read”, not “no data”. Treat those engines as unknown
rather than charting them as zero.
There is no engine filter here — the engine is the axis.
Last updated on