Skip to main content

AI

Crawler series

Crawler activity in buckets, split by what each fetch came to do.

GET/sites/{siteId}/ai/series
Crawler series
curl --request GET \
  --url 'https://truestat.io/api/v1/sites/{siteId}/ai/series' \
  --header 'Authorization: Bearer <token>'
{
  "data": [
    {
      "total": 338,
      "bucket": "2026-09-09 00:00:00",
      "indexing": 50,
      "training": 209,
      "answering": 2,
      "ai_referrals": 4
    }
  ],
  "meta": {
    "range": {
      "to": "2026-09-16T13:40:00.000Z",
      "tz": "UTC",
      "from": "2026-09-09T13:40:00.000Z",
      "clamped": false
    },
    "site_id": "6fed8980-a119-4a9c-a4d4-53e448ef9f9e"
  }
}

Crawler activity over time, with each bucket split by purpose — what the AI chart is drawn from.

Why the split lives here and not in /timeseries

/timeseries carries crawler_views, a single total per bucket. That is the line the visitor chart draws.

The split comes from its own query, and it is here because the distinction is the whole reason the AI section exists: a fetch that answers somebody's question right now and a fetch that harvests pages for a training run arrive the same way and mean opposite things. One is a reader you never see; the other is nobody at all. Collapsed into one line, that difference disappears.

So: one number for the chart, four for the argument.

total is more than the three parts

answering + indexing + training will usually come to less than total, and nothing is missing. Crawls whose purpose we do not recognise are counted in total and have no column of their own — a recognised crawler doing something unclassified, rather than an error.

Measured on a real site in one hour: 9 answering, 26 training, total 37.

Bucket size

unit takes minute, hour, day, week or month, and defaults to a size that suits the window — hours for a day, days for a month, weeks for a year. A year in minutes is half a million buckets, which is not a chart.

Buckets are cut in UTC

tz resolves the window here as it does everywhere: period=today&tz=Europe/Istanbul means your today, not the server's.

What it does not do is move the boundaries inside that window. A unit=day bucket starts at UTC midnight whatever tz you pass.

For this measurement it matters little — a crawler keeps no office hours, so an edge a few hours out changes the shape of the curve rather than what it says. It is written down because /timeseries does cut its buckets in tz, so the two charts disagree at the edges, and a caller comparing them deserves the reason rather than a mystery.

Crawler traffic is always counted here, whatever bots says. See crawlers.

Authorizations

Authorizationstringheaderrequired

An API key from Settings → API keys. Scopes available: analytics:read, sites:read, sites:write, settings:read, settings:write, goals:read, goals:write, funnels:read, funnels:write, notes:read, notes:write, alerts:read, alerts:write, team:read, team:write, revenue:read, revenue:write.

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path parameters

siteIdstring (uuid)pathrequired
The site's id, from `GET /sites`. A site that is not yours and a site that does not exist both answer 403, so this cannot be used to discover other people's ids.

Query parameters

unitenum<string>query
Bucket size. Defaults to one chosen for the window; a year in minutes is half a million buckets, which is not a chart.
options:minutehourdayweekmonth
periodenum<string>query
A named window, resolved in `tz`. Cannot be combined with `from`/`to` — a request carrying both is refused rather than guessed at.
options:todayyesterdaylast24hlast7dlast30dlast12mmonthyearall
fromstring (date-time)query
Start of the window, ISO 8601 with an offset. Must be given together with `to`.
tostring (date-time)query
End of the window. Must be given together with `from`.
tzstringquerydefault: UTC
IANA timezone for day boundaries. `period=today&tz=Europe/Istanbul` means the reader's today, not the server's. Defaults to UTC.
botsenum<string>querydefault: excluded
Whether crawler traffic is counted. Excluded by default — the `/ai/*` endpoints report it separately and always include it.
options:excludedincluded
filter_pathstringquery
Narrow the result to one `path`.
filter_path_patternstringquery
Narrow the result to one `path_pattern`.
filter_hostnamestringquery
Narrow the result to one `hostname`.
filter_entry_pathstringquery
Narrow the result to one `entry_path`.
filter_exit_linkstringquery
Narrow the result to one `exit_link`.
filter_file_downloadstringquery
Narrow the result to one `file_download`.
filter_goalstringquery
Narrow the result to one `goal`.
filter_browserstringquery
Narrow the result to one `browser`.
filter_osstringquery
Narrow the result to one `os`.
filter_devicestringquery
Narrow the result to one `device`.
filter_countrystringquery
Narrow the result to one `country`.
filter_regionstringquery
Narrow the result to one `region`.
filter_citystringquery
Narrow the result to one `city`.
filter_referrerstringquery
Narrow the result to one `referrer`.
filter_channelstringquery
Narrow the result to one `channel`.
filter_utm_sourcestringquery
Narrow the result to one `utm_source`.
filter_utm_mediumstringquery
Narrow the result to one `utm_medium`.
filter_utm_campaignstringquery
Narrow the result to one `utm_campaign`.
filter_gad_campaign_idstringquery
Narrow the result to one `gad_campaign_id`.
filter_utm_termstringquery
Narrow the result to one `utm_term`.
filter_bot_kindstringquery
Narrow the result to one `bot_kind`.

Response

application/json

The answer.

dataunknown
See the example.
metaobject