Competitor time-series
Daily visibility, share-of-voice, and position for each tracked competitor (plus the brand) — the trend version of brand-rankings.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/competitor-time-series?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/competitor-time-series",
params={"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3", "days": 30},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for e in resp.json()["data"]["items"]:
tag = "you" if e["is_brand"] else "competitor"
print(f"{e['name']:<24} avg visibility {e['avg_visibility']:>5}% ({tag})")
const url = new URL("https://api.aiclicks.io/api/v1/competitor-time-series");
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 e of data.items) console.log(e.name, e.is_brand, e.series);
{
"data": {
"items": [
{
"id": "user-brand-8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"name": "Your Brand",
"website": "yourbrand.com",
"is_brand": true,
"avg_mentions": 12.4,
"avg_position": 2.05,
"avg_visibility": 76.1,
"avg_sov": 22.3,
"avg_sentiment": 0.62,
"total_queries": 52,
"series": [
{ "date": "2026-06-01", "mentions": 10, "visibility": 74.0, "sov": 21.5, "avg_position": 2.1, "sentiment": 0.60 },
{ "date": "2026-06-02", "mentions": 12, "visibility": 78.2, "sov": 23.0, "avg_position": 1.9, "sentiment": 0.63 }
]
},
{
"id": "b2c3d4e5-6789-4abc-8def-0123456789ab",
"name": "Competitor A",
"website": "competitor-a.com",
"is_brand": false,
"avg_mentions": 9.8,
"avg_position": 3.2,
"avg_visibility": 61.5,
"avg_sov": 18.9,
"avg_sentiment": 0.51,
"total_queries": 52,
"series": [
{ "date": "2026-06-01", "mentions": 8, "visibility": 60.0, "sov": 18.0, "avg_position": 3.3, "sentiment": 0.50 },
{ "date": "2026-06-02", "mentions": 11, "visibility": 63.1, "sov": 19.8, "avg_position": 3.1, "sentiment": 0.52 }
]
}
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"model": "all",
"generated_at": "2026-07-13T10: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": "Too many requests. Please try again later." }
The over-time companion to brand-rankings. Where brand-rankings gives a single snapshot of the brand vs. its competitors, this returns a daily series for each — so you can see who is gaining or losing ground in AI answers, and whether a competitor's rise is steady or a one-day spike.
One entry per tracked (dedicated) competitor plus the brand itself (is_brand: true, sorted first). Each entry carries window averages and a series of daily datapoints: visibility, sov (share of voice), mentions, avg_position, and sentiment.
domain_id is a required query parameter. Use GET /api/v1/domains to discover which domains the calling key can access. Competitors are scoped to the domain — you only ever see the competitors tracked for that domain.
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.
Trailing look-back window, 1–365. Defaults to 30.
Restrict to a single AI channel by generic name (ChatGPT, Perplexity, Gemini, Claude…), or all (default).
Response
The list payload.
One entry per tracked competitor plus the brand. The brand (is_brand: true) is first; competitors follow, sorted by average visibility descending.
Competitor UUID (matches the id from GET /api/v1/brand-rankings), or a synthetic user-brand-<domain_id> id for the brand row.
Competitor (or brand) display name.
Competitor website host, or null if unknown.
true for the domain's own brand row, false for competitors.
Mean daily mentions over the window.
Mean position within AI answers over the window (lower is better).
Mean daily visibility % (share of responses that mention this entity).
Mean daily share of voice % (this entity's mentions vs. all entities that day).
Mean sentiment score over the window.
Number of tracked prompts contributing to this entity's metrics.
Daily datapoints, sorted by date ascending.
Echo of the requested domain.
Echo of the requested window.
Echo of the requested model filter (all when unset).
ISO-8601 timestamp of when the server produced (or cached) this response.
Response headers
| Header | Description |
|---|---|
X-Cache | HIT or MISS. 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 the current minute. |
X-RateLimit-Reset | Unix epoch seconds when the window resets. |
Empty result
If the domain has no tracked competitors and no analyses in the window, items is an empty list with a 200. A domain with competitors configured but no data yet returns each entry with an empty series and zeroed averages.