VisitTrack
Start free
☰ Browse the docs

Developers

API, CSV exports and MCP

Read your analytics from a script, a spreadsheet, or straight from an AI assistant.

Everything in your dashboard is readable through a REST API, downloadable as CSV, and queryable by an AI assistant through MCP. All three use the same key and the same data.

Looking for the write side?

Every endpoint on this page is read-only, by design — it's the same key, but GET-only. If you need to send events instead of reading them (a Stripe webhook, a background worker, anything that happens off the browser), that's a separate endpoint: see /docs/server-events.

Get a key

Settings → API / MCP → New API key. The key is shown once, at creation. We store only a hash of it, so if you lose it there's no way to recover it — create a new one and revoke the old.

REST

code
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://visitrack.app/api/v1/stats?days=30"

Swap stats for any of: site, stats, timeseries, pages, referrers, countries, devices, revenue, goals, live.

  • ?days=30 — how far back to look. Defaults to 30, maximum 365.
  • ?from=&to= — an explicit ISO date range instead, if you'd rather be precise.
  • ?granularity=day|hour|minute — for timeseries only.
  • Rate limit: 120 requests per minute per key.

What each resource takes and what it answers with — plus error shapes and the versioning policy — is on the API reference page at /docs/api-reference.

JavaScript

code
const res = await fetch("https://visitrack.app/api/v1/stats?days=30", {
  headers: { Authorization: `Bearer ${process.env.VISITRACK_API_KEY}` },
});
if (!res.ok) throw new Error(`VisitTrack ${res.status}: ${await res.text()}`);

const { data } = await res.json();
console.log(data.visitors, "visitors,", data.pageviews, "pageviews");

Node 18+ or any browser-less runtime — keep the key server-side, it reads all of your analytics.

Python

code
import os, requests

headers = {"Authorization": f"Bearer {os.environ['VISITRACK_API_KEY']}"}

stats = requests.get("https://visitrack.app/api/v1/stats", params={"days": 30}, headers=headers, timeout=10)
stats.raise_for_status()
print(stats.json()["data"]["visitors"])

pages = requests.get("https://visitrack.app/api/v1/pages", params={"days": 7}, headers=headers, timeout=10)
for page in pages.json()["data"]["pages"]:
    print(page["views"], page["path"])

CSV exports

Add format=csv to any resource made of rows — pages, referrers, countries, devices, goals, timeseries, live — and you get a file a spreadsheet opens directly.

code
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://visitrack.app/api/v1/pages?days=90&format=csv" -o pages.csv

CLI

The same data from your terminal. It's a thin wrapper over the REST API above — every command is one request — so it can never show you something the API wouldn't. It ships in the repo as a single dependency-free file, so it runs from a checkout with nothing to install.

code
export VISITRACK_API_KEY=YOUR_API_KEY

node cli/visitrack.mjs stats
node cli/visitrack.mjs pages --days 7
node cli/visitrack.mjs referrers --csv > referrers.csv
node cli/visitrack.mjs timeseries --granularity hour --days 2

Prefer a plain visitrack command? Install the folder globally from your checkout — then every example above works without the node cli/... prefix.

code
npm install -g ./cli

visitrack stats

Commands match the REST resources: site, stats, timeseries, pages, referrers, countries, devices, revenue, goals, live. Add --json to pipe into jq, or --csv for a spreadsheet. Run visitrack help for the full list.

Not on npm yet

The CLI is not published to the npm registry, so npx visitrack does not work — publishing it is planned, and this page will switch to that form once it does. Until then use one of the two invocations above.

MCP

MCP lets an AI assistant query your analytics directly, so you can ask 'how did traffic do this week, and where did it come from?' in the chat instead of opening a dashboard. Add this to your MCP client's config:

code
{
  "mcpServers": {
    "visitrack": {
      "type": "http",
      "url": "https://visitrack.app/api/mcp",
      "headers": { "Authorization": "Bearer YOUR_API_KEY" }
    }
  }
}

The assistant gets one read-only tool per resource above. It can read your numbers; it can't change anything, and it has no access to any other site.

Where that config file lives depends on the client

Claude Desktop, Claude Code, Cursor, Zed and the rest each keep MCP servers in their own file, and some add a server through a settings screen or a CLI command instead of a file at all. The JSON above is the server definition every one of them needs — check your client's own docs for where to paste it.

A question worth asking it

The point isn't reading one number out loud — the dashboard is faster at that. It's the questions that need three resources cross-referenced, which is exactly the tedious part:

code
Compare the last 7 days with the 7 before them: which traffic sources
grew, which shrank, and did the growth land on the pages that convert?
Use timeseries, referrers, pages and goals, and tell me the two numbers
you're least confident about.

Paste into a chat with the server connected.

The assistant calls timeseries twice for the two windows, then referrers, pages and goals, and answers in one pass. Ask it to show the tool calls if you want to check its arithmetic against the dashboard.

A key is scoped to one site

Each key belongs to the site it was created under. To read several sites, create a key in each and pass whichever one you need.

Something missing? Tell us.

AI agent or LLM? Read this page as markdown.