ChatGPT Ads Timeline
Daily ChatGPT-ads activity for a tracked domain over the window — the ads trend.
curl --request GET \
--url 'https://api.aiclicks.io/api/v1/ads/timeline?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/ads/timeline",
params={
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
},
headers={"Authorization": f"Bearer {os.environ['AICLICKS_API_KEY']}"},
)
resp.raise_for_status()
for point in resp.json()["data"]["timeline"]:
print(f"{point['date']} total={point['anyAdvertiser']:>4} you={point['yourBrand']:>4}")
const url = new URL("https://api.aiclicks.io/api/v1/ads/timeline");
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 point of data.timeline) {
console.log(`${point.date}: total=${point.anyAdvertiser}, you=${point.yourBrand}`);
}
{
"data": {
"timeline": [
{ "date": "2026-05-18", "anyAdvertiser": 0, "yourBrand": 0 },
{ "date": "2026-05-19", "anyAdvertiser": 12, "yourBrand": 3 },
{ "date": "2026-05-20", "anyAdvertiser": 18, "yourBrand": 5 },
{ "date": "2026-05-21", "anyAdvertiser": 9, "yourBrand": 2 }
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"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."
}
Returns one point per calendar day across the lookback window, counting the ad cards seen inside ChatGPT answers for your domain's tracked prompts. Every point carries the total across all advertisers (anyAdvertiser) and the slice attributed to your own brand (yourBrand). Use it to answer "how has ChatGPT ad volume on my prompts moved day by day?" in one call.
The series is dense — every day in the window is present, filled with 0 where no ads ran — so it plots without gap-filling. Days are UTC calendar dates, oldest first.
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.
Look-back window, 1–365. Defaults to 30. The number of points returned equals the number of calendar days spanned (roughly days + 1, inclusive of today).
Response
The timeline payload.
One point per UTC calendar day in the window, oldest first. Days with no ads are present with 0 counts — the series is never sparse.
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. 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 30 minutes server-side per (domain_id, days). Newly completed analyses appear 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
If no ads ran in the window, the response is still a successful 200: the series is fully present with every point zeroed.
{
"data": {
"timeline": [
{ "date": "2026-05-18", "anyAdvertiser": 0, "yourBrand": 0 },
{ "date": "2026-05-19", "anyAdvertiser": 0, "yourBrand": 0 }
]
},
"domain_id": "8f1d3c0a-2f9b-4c11-9b80-7a82e1f0c3f3",
"days": 30,
"generated_at": "2026-06-17T10:00:11.218Z"
}