HTTP API
Everything the dashboard reads, you can read. Read-only keys, one spec, and nothing held back.
The dashboard is a client of the same API you get. There is no private endpoint the dashboard uses that you cannot.
Keys
Your account → API keys (the account dialog, under your picture). Keys are read-only and scoped to your instance. The value is shown once.
curl -H 'Authorization: Bearer tkb_live_…' \
'https://stats.example.com/api/v1/sites'For automation on a machine you control, TRCKABLE_API_TOKEN sets a single
bearer token at the server, without creating a key in the dashboard.
The report
One endpoint answers the whole dashboard.
curl -H 'Authorization: Bearer tkb_live_…' \
'https://stats.example.com/api/v1/sites/tkb_a1b2c3d4/report?from=2026-09-01&to=2026-09-23'| Parameter | |
|---|---|
from, to | Dates in the site's timezone, inclusive |
compare | previous, year or custom with cfrom/cto |
bucket | hour, day, week or month |
f | A filter, dim:value. Repeat it to stack them |
daily | 1 adds per-day breakdowns |
deep | 1 adds exit pages, regions and cities |
attr | first credits the visit that found them |
payments | test counts sandbox payments instead of live ones |
Filterable dimensions: channel, referrer, entry_page, exit_page,
campaign, source, medium, country, region, city, device,
browser, os, language.
The same report, as a file
curl -H 'Authorization: Bearer tkb_live_…' -OJ \
'https://stats.example.com/api/v1/sites/tkb_a1b2c3d4/export.csv?from=2026-09-01&to=2026-09-23&f=channel:Search'It takes every parameter the report takes, so the file is the same question
with the same answer. One long table: dimension, value, visitors, sessions, pageviews, bounce_rate, plus revenue, currency, customers once payments are
connected. The total is the first row, the chart follows one bucket at a time,
then every breakdown up to a thousand rows each, then goals.
The other reads
| Endpoint | Returns |
|---|---|
GET /api/v1/sites | Your sites |
GET /api/v1/sites/{site}/live | Server-Sent Events: visits as they happen |
GET /api/v1/sites/{site}/events | The recent live feed |
GET /api/v1/sites/{site}/report/retention | Cohorts |
GET /api/v1/sites/{site}/report/heatmap | Hour by weekday |
GET /api/v1/sites/{site}/report/vitals | Core Web Vitals |
GET /api/v1/sites/{site}/report/crawlers | AI crawlers and bots |
GET /api/v1/sites/{site}/report/goal-props | Goal property breakdowns |
GET /api/v1/sites/{site}/journey/{visitor} | One visitor's path |
GET /api/v1/health | Version, disk, writer lag, backups, webhooks |
Sending events from a server
Events do not have to come from a browser. POST /api/e takes the same shape
the tracker sends:
curl -X POST https://stats.example.com/api/e \
-H 'content-type: application/json' \
-H 'X-Trckable-Proxy-Key: …' \
-H 'X-Real-IP: 203.0.113.9' \
-d '{"s":"tkb_a1b2c3d4","k":"pv","u":"https://example.com/pricing","r":"https://news.ycombinator.com/"}'The proxy key is what allows the forwarded address to be trusted. Without it, trckable uses the address it can see.
Robots
POST /api/crawl records a robot's request. Robots do not run JavaScript, so
this comes from your own server — one line of middleware — and feeds the AI
crawlers module.
Rate limits and errors
Ingest is limited per address and visitor, and the body is capped at 8 KB with a
strict schema. Under pressure trckable answers 503 with a Retry-After and
the tracker queues the event rather than dropping it.
A 5xx or 429 means "come back"; anything else is final.
Outgoing: alerts
Alerts post JSON to any URL you give them — tracking stopped, a busy day, someone paid, disk filling. The destination is checked against private and internal addresses before it is stored, so trckable cannot be pointed at something inside your network.
Upgrading
Take a backup, pull the new image and start a new container from it. Migrations run forwards and refuse to open a database from the future.
MCP server
Let your own assistant answer questions from your analytics. Your key, your model, your data — trckable pays for nothing and sends nothing anywhere.