List Fan-out Queries
Returns the search queries LLMs fanned out to per tracked prompt, attributed by model.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/fanout-queries?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/fanout-queries",
params={
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for prompt in resp.json()["data"]["items"]:
print(prompt["text"])
for f in prompt["fanout_queries"]:
print(f" [{f['model']}] {f['query']}")
const url = new URL("https://api.aiclicks.io/api/v1/fanout-queries");
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 prompt of data.items) {
console.log(prompt.text);
for (const f of prompt.fanout_queries) {
console.log(` [${f.model}] ${f.query}`);
}
}
{
"data": {
"items": [
{
"id": "21c1f9aa-9b6d-4e3a-8a31-2b0c0e1f2a3b",
"text": "best CRM for small business",
"fanout_queries": [
{
"id": "8a3c2e91-1f44-4b6e-9a01-2c0d8f3e1aab",
"query": "top CRM software 2026",
"model": "ChatGPT"
},
{
"id": "9b4d3f02-2055-4c7f-aa12-3d1e9f4f2bbc",
"query": "Salesforce vs HubSpot review",
"model": "Claude"
},
{
"id": "ac5e4013-3166-4d80-bb23-4e2faf503ccd",
"query": "best CRM cheap",
"model": "Perplexity"
}
]
},
{
"id": "32d2e8bb-aa7e-5f4b-9b42-3c1d1f2a3b4c",
"text": "Salesforce vs HubSpot",
"fanout_queries": [
{
"id": "bd6f5124-4277-4e91-cc34-5f3fbf614dde",
"query": "HubSpot pricing 2026",
"model": "ChatGPT"
}
]
}
],
"total": 12
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"model": "all",
"generated_at": "2026-06-17T10: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": "Domain not found"
}
{
"detail": "Too many requests. Please try again later."
}
When you ask an LLM a question, it doesn't just answer it. Internally it issues one or more fan-out search queries to ground its response in fresh information. These are the real searches the LLM ran on your behalf — and the closest thing you have to "what queries should I rank for" inside AI search.
This endpoint groups fan-out queries under the tracked prompt that triggered them. Each fan-out entry is one actual emission, attributed to a specific response and model channel. To rank queries by global frequency across prompts, flatten the result client-side.
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.
Look-back window, 1–365. Defaults to 30. Snapped to the nearest known bucket: 1, 7, 14, 30, 90, 180, 270, or 365 days.
Filter to a single model channel. Accepts either the generic name (ChatGPT, Claude, Gemini, Perplexity, AI Overviews, AI Mode, Grok, Microsoft Copilot) or the underlying model key. Defaults to all — every channel.
Response
The list payload.
Array of prompts that produced at least one fan-out query in the window.
UUID of the tracked prompt.
The prompt text exactly as you track it.
One entry per emission. Same query string may appear multiple times — each represents a distinct LLM run.
UUID of the response that emitted this fan-out query. Lets you correlate emissions if you later expose response data.
The actual fan-out search query the LLM ran.
Generic channel name. Possible values: ChatGPT, Claude, Gemini, Perplexity, AI Overviews, AI Mode, Grok, Microsoft Copilot.
Number of prompts that produced at least one fan-out query. Equals items.length.
Echo of the requested domain.
Echo of the requested window.
Echo of the requested model filter.
ISO-8601 timestamp of when the server produced (or cached) this response.
Response headers
| Header | Description |
|---|---|
X-Cache | HIT or MISS. Indicates 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 current minute. |
X-RateLimit-Reset | Unix epoch seconds when the window resets. |
Caching
Cached for 1 hour per (domain_id, days, model). Fresh analyses that complete inside the cache window appear after the TTL expires.
Frequency and ranking
There is no count field. Each entry in fanout_queries is one actual LLM emission — frequency is fanout_queries.filter(f => f.query === target).length. To rank fan-out queries globally across prompts:
const counts = {};
for (const p of data.items) {
for (const f of p.fanout_queries) {
const key = f.query.toLowerCase().trim();
counts[key] = (counts[key] || 0) + 1;
}
}
const ranked = Object.entries(counts).sort((a, b) => b[1] - a[1]);
Artefact filtering
Some LLMs emit metadata strings that are not real searches (e.g. answer_guess, related_queries, internal field names). AIclicks strips these server-side before you see them. The filter is defensive and may evolve — if you see a string that shouldn't be in the list, contact support.
Errors
domain_id query parameter missing. Body points you at /api/v1/domains.
Missing, malformed, or revoked API key.
Team's developer_access flag is off, the domain belongs to a team your API key is not scoped to, or your allowed_domains allowlist excludes it.
domain_id is malformed, does not exist, or your user is not a member of its team.
Rate limit exceeded. Inspect the Retry-After header for how long to wait.
Empty result
If no analyses ran in the window — or every fan-out string was filtered as an artefact — the response is a successful 200 with an empty list:
{
"data": { "items": [], "total": 0 },
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"model": "all",
"generated_at": "2026-06-17T10:00:11.218Z"
}