Install & operate

API reference

Ingest

No authentication; the site id is the authorisation.

The tracker posts to /api/d; /api/collect is the same endpoint under its original name, kept for existing integrations.

POST /api/d
Content-Type: application/json

{
  "site": "SITE_ID",
  "type": "pageview",          // or "event"
  "url": "/pricing?utm_source=x",
  "referrer": "https://chatgpt.com/",
  "name": "cta_click",         // required when type=event
  "props": { "plan": "pro" },
  "identity": "user-id",        // optional
  "tag": "v2"
}
ResponseMeaning
204Recorded.
202Accepted but not stored — Do Not Track in strict mode.
400Invalid body — the reason is in the JSON.
404Unknown site id.
429Monthly quota exceeded.
The server does not trust the client. Timestamp, IP, country and the bot decision are all determined server-side; sending them in the body has no effect.

Reading your data with an API key

Create a key in the dashboard under Workspace → API keys (workspace admins only). A key reads every site in its workspace and can change nothing — it is accepted only by the read endpoints, so there is no write it could reach. It is shown once; we store a hash of it.

Send it in the Authorization header. A key in the URL is refused with 401 rather than accepted, because URLs end up in logs.

# Which sites can this key read?
curl https://app.vitrus.dev/api/sites   -H "Authorization: Bearer vk_…"

# Last 30 days — every number with the query that produced it
curl "https://app.vitrus.dev/api/stats?site=SITE_ID&days=30"   -H "Authorization: Bearer vk_…"
ResponseMeaning
401Missing, unknown or revoked key — the same answer for all three.
404The site is not in this key's workspace (or does not exist).
429More than 600 requests a minute with this key.

Live data and session replays are not available to keys: live is for the dashboard, and a recording is the one thing we would rather a leaked key could never fetch.

Query endpoints

Each takes an API key or a signed-in session, and passes through site access control — another workspace's site id returns 404, not 403, so existence is not leaked. days is the window (1–365), or use from and to in epoch milliseconds.

EndpointReturns
GET /api/sitesThe sites an API key can read (key only).
GET /api/stats?site=&days=Evidence bundle: query, parameters and result per metric.
GET /api/digest?site=&days=Digest plus evidence. &format=text for plain text.
GET /api/funnel?site=&steps=Funnel result. steps is a JSON array.
GET /api/retention?site=Cohort matrix, or why it cannot be computed.
GET /api/sessions?site=Sessions, newest first; /api/sessions/:id for one timeline.
GET /api/users?site=Identified users and their traits.
GET /api/journeys?site=The most common page paths.
GET /api/performance?site=Core Web Vitals at p50–p99.
GET /api/gsc?site=&days=Google Search Console clicks, impressions, CTR and position, with Google's request and answer — see Search Console.
GET /api/revenue?site=&currency=&by=Revenue per currency, by dimension and over time — see Revenue.
GET /api/geo?site=Countries, regions, cities and coordinates.
GET /api/export?site=Raw events as CSV (up to 100,000 rows).
GET /api/orgs/:id/usageQuota status (session only).
POST /mcpMCP (JSON-RPC 2.0) — see MCP server.