Skip to main content

Base URL and authentication

GET /v1/sources/breakdown takes Authorization: Bearer <YOUR_API_KEY> (details) and the stats:read permission. Its site_id is the site’s snippet key, the ttid_ value your install snippet carries as data-site, which you can read from GET /v1/sites. GET /v1/sources, at the bottom of this page, is different on both counts: a dashboard session only, and a UUID.

GET /v1/sources/breakdown

One row per day per source, with attributed revenue joined on. This is the data behind the Sources page in the dashboard.

Choosing the window

Send either from and to together, or days. If you send neither, the window is the last 7 days. Two limits apply to from and to:
  • The range may not span more than 730 days.
  • from may not be more than 730 days ago.
The second one is not arbitrary. Bounce rate is derived from session-level records, which are kept for at least 730 days and at most 760, while the session counts beside them are kept for the life of your account. Because the guarantee for any individual session is the 730-day end of that range, an older window could report a confident 0.0% bounce rate instead of telling you the data is gone. It is refused instead.

Response fields

Each breakdown row:

About the two revenue fields

revenue_usd_cents is how revenue is stored: integer US cents, so it never drifts through rounding. revenue_display is the same amount in your site’s reporting currency. Each day converts at that day’s exchange rate, so a figure you read last month does not change when rates move. If we hold no rate for one of the dates in your window, that row’s revenue_display is null and the date is listed in missing_rate_dates. It is never the US dollar figure relabelled with your currency. If your reporting currency is USD, no conversion happens: converted is false and revenue_display equals revenue_usd_cents / 100.

ai_source is a source label, not an AI flag

ai_source also carries non-AI values (direct, organic_search, social, email, paid, referral), so summing every row gives you total traffic rather than AI traffic. total_sessions is that same total, computed independently.

Errors

GET /v1/sources

Dashboard session only. Unlike /breakdown above, this endpoint does not accept a tk_live_ API key. A key gets 401, whatever its permissions. It is documented because it exists, not because you can call it with a key today.
The distinct source keys seen for a site: the ai_source values actually observed in the window, plus the fixed list of non-AI channels. The dashboard uses it to populate its source filter. Two things differ from every other read on this page. site_id is the site’s Postgres id (a UUID), not the ttid_ snippet key, and the window is days rather than from and to.
ai depends on the window. non_ai is a fixed list and does not. This is one of the endpoints that predates the { status, data } envelope, so the object above is the whole body. If the underlying query fails, ai comes back empty with a 200 and no caching headers, rather than an error. Treat an empty ai as “no answer right now”, not as “no AI traffic”.

Next