Citation Share
The citation share of the brand and of each tracked competitor, inside every topic or tag of a domain.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/citation-share?domain_id=8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3&group_by=topic&days=30' \
--header 'Authorization: Bearer ak_live_xxx'
import httpx, os
resp = httpx.get(
"https://api.aiclicks.io/api/v1/citation-share",
params={
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"group_by": "tag",
"days": 30,
},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for unit in resp.json()["data"]["items"]:
brand = next((b for b in unit["brands"] if b["is_brand"]), None)
print(unit["name"], brand and brand["share_of_all_citations"])
const url = new URL("https://api.aiclicks.io/api/v1/citation-share");
url.searchParams.set("domain_id", "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3");
url.searchParams.set("group_by", "topic");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.AICLICKS_API_KEY}` },
});
const { data } = await resp.json();
for (const unit of data.items) console.log(unit.name, unit.brands.length);
{
"data": {
"group_by": "topic",
"items": [
{
"id": "c0ffee00-0000-4000-8000-000000000001",
"name": "Inventory software",
"brands": [
{
"id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"name": "Northwind",
"website": null,
"is_brand": true,
"citations": 120,
"share_of_all_citations": 8.12
},
{
"id": "f6a7b8c9-3333-4eee-8fff-000000000001",
"name": "Acme Rival",
"website": "acmerival.com",
"is_brand": false,
"citations": 151,
"share_of_all_citations": 10.22
}
]
},
{
"id": "c0ffee00-0000-4000-8000-000000000002",
"name": "Warehouse robots",
"brands": []
}
]
},
"generated_at": "2026-11-09T09:40:12.901Z",
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"model": "all"
}
{
"detail": "Dates must be YYYY-MM-DD."
}
{
"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."
}
This endpoint breaks citations down by topic or by tag. For each topic (or tag) of the domain, it returns the own brand and each tracked competitor, with its citations and its share of the citations in that unit.
Use this endpoint to answer the question "In which topics do competitors get more citations than we do?". For one total across all prompts, use GET /api/v1/competitor-citations.
Inside each unit, the own brand is first. The competitors follow, from the most citations to the fewest. The endpoint returns every topic or tag of the domain, also the units with no citations.
Authorizations
Your API key in the format Bearer ak_live_<your-key>. Create a key in the dashboard under Settings → Developers.
An optional UUID for log correlation. If you do not send one, the server makes one and returns it in the response.
Query parameters
The UUID of the domain. Find domains with GET /api/v1/domains.
The unit for the breakdown: topic or tag. The default is topic.
The look-back window in days, from 1 to 365. The default is 30. The server uses the exact value. It does not round it to a fixed bucket.
The first day of a fixed window, in the format YYYY-MM-DD. Send it with end_date. When you send both dates, they replace days.
The last day of a fixed window, in the format YYYY-MM-DD. The day is included. A window can be at most 365 days.
One AI channel by its generic name, for example ChatGPT, Perplexity, Gemini, AI Overviews, AI Mode, Claude, Microsoft Copilot or Grok. The default is all.
Set true to skip the cache and calculate the result again. The new result replaces the cached result. The default is false.
Response
The citation share for each unit.
The unit of the breakdown: topic or tag.
One item for each topic (or tag) of the domain.
The ISO-8601 time when the server made (or cached) this response.
The domain from the request.
The days value from the request.
The model value from the request.
Response headers
| Header | Description |
|---|---|
X-Cache | HIT, MISS or REFRESH. REFRESH means that you sent fresh=true. |
X-Request-Id | The request id. If you sent one, the server returns it. |
X-RateLimit-Limit | The maximum number of requests per minute for this key. |
X-RateLimit-Remaining | The number of requests that remain in this minute. |
X-RateLimit-Reset | The Unix time in seconds when the window starts again. |
Caching
The server caches the response for 1 hour for each set of parameters. To get new data before the cache expires, send fresh=true. A domain with many topics can take longer to calculate on a cache miss.
Errors
A date is not in the format YYYY-MM-DD, start_date is after end_date, or the window is longer than 365 days. If domain_id is missing, group_by is not topic or tag, or days is out of range, the endpoint returns 422.
The API key is missing, malformed or revoked.
The developer_access flag of the team is off. Or the domain is not in the scope of your key, or your allowed_domains list does not include it.
The domain_id is malformed or does not exist, or your user is not a member of its team.
You sent too many requests. Read the Retry-After header to know how long to wait.
Empty result
If the domain has no topics (or no tags, with group_by=tag), the endpoint returns 200 with an empty list:
{
"data": { "group_by": "topic", "items": [] },
"generated_at": "2026-11-09T09:40:12.901Z",
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"model": "all"
}