Citation Domains
Every website that AI answers cite for the prompts of a domain, sorted by citations, with its owner: own, competitor or third party.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/citation-domains?domain_id=8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3&days=30&page=1&size=100' \
--header 'Authorization: Bearer ak_live_xxx'
import httpx, os
resp = httpx.get(
"https://api.aiclicks.io/api/v1/citation-domains",
params={
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"start_date": "2026-10-01",
"end_date": "2026-10-31",
},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
data = resp.json()["data"]
third_party = [row for row in data["items"] if row["owner"] == "third_party"]
print(data["total"], "domains;", len(third_party), "third-party on this page")
const url = new URL("https://api.aiclicks.io/api/v1/citation-domains");
url.searchParams.set("domain_id", "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3");
url.searchParams.set("size", "50");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.AICLICKS_API_KEY}` },
});
const { data } = await resp.json();
console.table(data.items);
{
"data": {
"items": [
{
"domain": "reddit.com",
"citations": 640,
"prompt_count": 38,
"share_percent": 10.63,
"owner": "third_party"
},
{
"domain": "northwind.example",
"citations": 412,
"prompt_count": 27,
"share_percent": 6.84,
"owner": "own"
},
{
"domain": "acmerival.com",
"citations": 287,
"prompt_count": 21,
"share_percent": 4.77,
"owner": "competitor"
}
],
"total": 214,
"page": 1,
"size": 100,
"total_pages": 3
},
"generated_at": "2026-11-09T09:50:31.004Z",
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30
}
{
"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."
}
This endpoint lists the websites (hosts) that AI answers cite for the prompts of a domain. Each row has the number of citations, the number of prompts, the share of all citations and the owner of the website.
The owner field has one of three values:
own: the website of the brand.competitor: the website of a tracked competitor.third_party: any other website.
The list starts with the most-cited website. The response is paginated. To see the URLs on one website, use GET /api/v1/citations with cited_domain.
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. If you do not send it, the endpoint returns 400.
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.
Topic UUIDs from GET /api/v1/topics. Repeat the parameter for each value, for example topic_ids=a&topic_ids=b. The endpoint then counts only the prompts in these topics.
Tag UUIDs from GET /api/v1/tags. Repeat the parameter for each value. If you send topic_ids and tag_ids, the endpoint counts the prompts that match either filter.
The page number. The first page is 1. The default is 1.
The number of rows on each page, from 1 to 500. The default is 100.
Set true to skip the cache and calculate the result again. The new result replaces the cached result. The default is false.
Response
One page of cited websites.
The cited websites on this page, from the most citations to the fewest.
The number of cited hosts on all pages.
The page number from the request.
The page size from the request.
The number of pages. It is 1 when the list is empty.
The ISO-8601 time when the server made (or cached) this response.
The domain from the request.
The days 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. The full list is also cached, so other pages of the same query are fast. To get new data before the cache expires, send fresh=true.
Errors
The domain_id query parameter is missing. Or start_date is after end_date, or the window is longer than 365 days. If a date is not in the format YYYY-MM-DD, or page, size 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 window has no citations, or the filters match no prompts, the endpoint returns 200 with an empty list:
{
"data": { "items": [], "total": 0, "page": 1, "size": 100, "total_pages": 1 },
"generated_at": "2026-11-09T09:50:31.004Z",
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30
}