List Topics
Every topic defined for a domain — the lookup you use to turn topic names into topic_ids before adding a prompt.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/topics?domain_id=8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3' \
--header 'Authorization: Bearer ak_live_xxx'
import httpx, os
resp = httpx.get(
"https://api.aiclicks.io/api/v1/topics",
params={"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3"},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
# Resolve a name to its id for the add-prompt call.
topics_by_name = {t["name"].lower(): t["id"] for t in resp.json()["data"]}
pricing_id = topics_by_name["pricing"]
print(pricing_id)
const url = new URL("https://api.aiclicks.io/api/v1/topics");
url.searchParams.set("domain_id", "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3");
const resp = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.AICLICKS_API_KEY}` },
});
const { data } = await resp.json();
const byName = Object.fromEntries(data.map((t) => [t.name.toLowerCase(), t.id]));
console.log(byName["pricing"]);
{
"data": [
{
"id": "d4e5f6a7-2222-4ccc-8ddd-000000000001",
"name": "Pricing",
"description": "Prompts about plans, cost, and value comparisons."
},
{
"id": "d4e5f6a7-2222-4ccc-8ddd-000000000002",
"name": "Integrations",
"description": "Prompts about connecting to other tools and APIs."
},
{
"id": "d4e5f6a7-2222-4ccc-8ddd-000000000003",
"name": "Security",
"description": null
}
],
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"generated_at": "2026-08-18T10: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."
}
Returns the domain's topic catalog: one row per topic with its name and optional description. Use it to resolve human-readable topic names into the topic_ids that `` expects — the write endpoint takes ids, not names, so this is the read you call first.
This is a deliberately trimmed view: each row is just id, name, and description. Internal fields (domain_id, created_at) are not returned. Archived topics are excluded.
domain_id is a required query parameter. Use `` 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 ``. Omitting this returns 400.
Response
One row per non-archived topic on the domain.
Echo of the requested domain.
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. A newly created topic appears after the TTL expires.
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
A domain with no topics returns a successful 200 with an empty list:
{
"data": [],
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"generated_at": "2026-08-18T10:00:11.218Z"
}