Competitor discovery
Brands that appear in AI answers to the domain's tracked prompts but aren't in the tracked competitor set yet — ranked by how many prompts mention them.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/competitor-discovery?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-discovery",
params={"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3", "days": 30},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
data = resp.json()["data"]
for c in data["items"]:
share = 100 * c["prompts_mentioned"] / max(data["total_prompts"], 1)
print(f"{c['name']:<28} {c['prompts_mentioned']:>3}/{data['total_prompts']} prompts ({share:.0f}%)")
const url = new URL("https://api.aiclicks.io/api/v1/competitor-discovery");
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 c of data.items) console.log(c.name, c.prompts_mentioned, "/", data.total_prompts);
{
"data": {
"items": [
{ "id": "b2c3d4e5-6789-4abc-8def-0123456789ab", "name": "Rising Rival", "website": "risingrival.com", "prompts_mentioned": 14, "total_prompts": 52 },
{ "id": "c3d4e5f6-7890-4bcd-9ef0-123456789abc", "name": "Niche Tool", "website": "nichetool.io", "prompts_mentioned": 5, "total_prompts": 52 }
],
"total_prompts": 52
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"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 "who should I be tracking?" endpoint. Where brand-rankings and competitor-time-series only cover competitors you've already added, this surfaces brands the AI models bring up in answers to your prompts that you haven't started tracking — so you can spot emerging rivals before they take share.
Each row is a discovered (detected, not yet dedicated) competitor with prompts_mentioned — how many of your tracked prompts named it — against total_prompts for context. Sorted by prompts_mentioned descending.
domain_id is a required query parameter. Use GET /api/v1/domains to discover which domains the calling key can access.
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.
Response
The discovery payload.
One row per discovered untracked competitor, sorted by prompts_mentioned descending.
Same denominator, repeated at the top level for convenience.
Echo of the requested domain.
Echo of the requested window.
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 no untracked brands were detected in the window, items is an empty list with a 200:
{
"data": { "items": [], "total_prompts": 0 },
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"generated_at": "2026-07-13T10:00:11.218Z"
}