For your agent: Download .md lightweightanalytics.com/docs/api.md

Agent & CLI API

Lightweight Analytics is agent-first: everything you can do in the dashboard (register sites, pull stats, manage goals) is available through a small JSON API designed to be driven by AI agents (Claude, Codex, or your favorite) and our upcoming CLI.

Working with an agent? Point it at the raw markdown version of this page: https://lightweightanalytics.com/docs/api.md, or at https://lightweightanalytics.com/llms.txt. Both are plain text, no HTML to scrape.

Base URL & authentication

https://lightweightanalytics.com/api/v1

Create an API key at Settings → API keys and send it on every request:

curl -H "Authorization: Bearer la_YOUR_KEY" \
  https://lightweightanalytics.com/api/v1/me

X-Api-Key: la_YOUR_KEY works too if setting an Authorization header is awkward. Keys act on your whole account, can be named (one per agent/machine is a good habit), and can be revoked instantly from the same page. We store only a hash of the key, so copy it when it's shown.

In the examples below, export it once:

export LA_API_KEY="la_YOUR_KEY"

Rate limits & errors

Limits are generous: 600 requests/minute per key (bursts up to 120 are fine). Over the limit you get 429 with a Retry-After header. Wait a second and retry.

Every error has the same flat shape:

{ "error": "not_found", "message": "No site with that id belongs to this account. GET /api/v1/sites lists yours." }
Status error codes you'll see
400 domain_required, invalid_domain, invalid_range, invalid_bucket, invalid_breakdown, confirmation_required, invalid_goal_name, invalid_goal_type, invalid_match_type, pattern_required, invalid_value
401 missing_api_key, invalid_api_key
403 subscription_required, site_limit_reached
404 not_found
409 domain_taken, goal_exists
429 rate_limited

Date ranges

Stats endpoints accept either a preset range or explicit dates. All dates are UTC.

  • ?range= one of today, yesterday, 7d, 30d (default), 90d, 365d, thisMonth, lastMonth, thisYear, all
  • ?from=2026-08-01&to=2026-08-11: explicit dates (to is inclusive, whole day)
  • ?segment=dev: switch from production traffic to non-production traffic (localhost, staging hosts, etc.)

Account

GET /me

Sanity-check your key and see account status.

curl -H "Authorization: Bearer $LA_API_KEY" \
  https://lightweightanalytics.com/api/v1/me
{
  "email": "[email protected]",
  "name": "Ada Lovelace",
  "keyName": "Claude on my laptop",
  "keyPrefix": "la_9f2c4e01",
  "plan": "annual",
  "subscriptionStatus": "active",
  "sites": 3,
  "siteLimit": 100,
  "apiCallsToday": 42,
  "rateLimit": "600 requests/minute per key (burst 120)"
}

Sites

GET /sites

List every site on the account. Add ?includeStats=true for all-time pageviews/visitors (slightly slower).

curl -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites?includeStats=true"
{
  "sites": [
    {
      "siteId": "11111111-2222-3333-4444-555555555555",
      "domain": "example.com",
      "name": "My blog",
      "useVisitorCookie": true,
      "useLivePings": false,
      "isFavorite": true,
      "publicDashboardEnabled": false,
      "goals": 2,
      "allTimePageviews": 48210,
      "allTimeVisitors": 19877
    }
  ],
  "count": 1,
  "siteLimit": 100
}

POST /sites (register a site)

Only domain is required. The response includes the tracking snippet to paste into the site's <head>.

curl -X POST -H "Authorization: Bearer $LA_API_KEY" -H "Content-Type: application/json" \
  -d '{"domain": "example.com", "name": "My blog"}' \
  https://lightweightanalytics.com/api/v1/sites
{
  "siteId": "11111111-2222-3333-4444-555555555555",
  "domain": "example.com",
  "name": "My blog",
  "useVisitorCookie": true,
  "useLivePings": false,
  "isFavorite": false,
  "publicDashboardEnabled": false,
  "trackingSnippet": "<script defer src=\"https://cdn.lightweightanalytics.com/script.min.js\" data-siteid=\"11111111-2222-3333-4444-555555555555\" data-c_mode=\"true\" data-l_ping=\"false\"></script>",
  "dashboardUrl": "https://lightweightanalytics.com/dashboard?siteId=11111111-2222-3333-4444-555555555555"
}

Optional body fields: useVisitorCookie (default true, first-party visitor id for accurate uniques) and useLivePings (default false, 30-second keep-alive for the live counter).

GET /sites/

Site details, settings, all-time stats, goal count and the current tracking snippet.

curl -H "Authorization: Bearer $LA_API_KEY" \
  https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555

PATCH /sites/

Send only the fields you want to change: name, useVisitorCookie, useLivePings.

curl -X PATCH -H "Authorization: Bearer $LA_API_KEY" -H "Content-Type: application/json" \
  -d '{"useLivePings": true}' \
  https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555

Changing tracking options changes the snippet. The response includes the updated one to re-paste.

DELETE /sites/

Permanently deletes the site and all its analytics data. As a guard you must echo the site's domain in confirm:

curl -X DELETE -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555?confirm=example.com"
{ "deleted": true, "siteId": "11111111-2222-3333-4444-555555555555", "domain": "example.com" }

Stats

GET /sites/

The headline numbers for a period, the same as the dashboard's top row.

curl -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/stats/summary?range=7d"
{
  "siteId": "11111111-2222-3333-4444-555555555555",
  "domain": "example.com",
  "from": "2026-08-05T00:00:00Z",
  "to": "2026-08-11T23:59:59.9999999Z",
  "pageviews": 4821,
  "visitors": 1977,
  "sessions": 2410,
  "bounceRate": 0.44,
  "avgSessionSeconds": 74.2,
  "pagesPerSession": 2.0,
  "newVisitors": 1544,
  "returningVisitors": 433,
  "liveVisitors": 3
}

GET /sites/

Pageviews and visitors over time, zero-filled so every bucket is present. bucket is auto (the default: hourly for ranges up to 2 days, daily otherwise), hour or day.

curl -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/stats/timeseries?range=7d"
{
  "granularity": "day",
  "points": [
    { "date": "2026-08-05", "pageviews": 512, "visitors": 231 },
    { "date": "2026-08-06", "pageviews": 748, "visitors": 342 }
  ]
}

GET /sites/

Top-N tables, one endpoint for every dimension. by is one of: pages, referrers, countries, browsers, devices, os, languages, resolutions, hosts, campaigns. limit defaults to 10 (max 100).

curl -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/stats/breakdown?by=referrers&range=30d&limit=5"
{
  "by": "referrers",
  "items": [
    { "key": "news.ycombinator.com", "count": 1204 },
    { "key": "google.com", "count": 892 },
    { "key": "direct", "count": 611 }
  ]
}

by=campaigns returns your UTM campaign traffic (always the last 30 days) with a different item shape:

{
  "by": "campaigns",
  "items": [
    { "source": "newsletter", "medium": "email", "campaign": "launch-week", "count": 302 }
  ]
}

GET /sites/

Visitors active in the last 5 minutes. Not cached, so poll it as often as you like within the rate limit.

curl -H "Authorization: Bearer $LA_API_KEY" \
  https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/stats/live
{ "siteId": "11111111-2222-3333-4444-555555555555", "liveVisitors": 3 }

Goals & campaigns

Goals track conversions (sign-ups, purchases, clicks). Three types:

  • manual: you fire the event yourself (JS window.la('event', 'Signup') or the collect endpoint below)
  • click: fired declaratively via a data-la-goal attribute on an element
  • url: fired automatically when a visited URL matches pattern (matchType: contains, starts or regex)

Values are integer cents to avoid floating point.

GET /sites/

curl -H "Authorization: Bearer $LA_API_KEY" \
  https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/goals
{
  "goals": [
    { "goalId": "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee", "name": "Signup", "type": "manual", "matchType": null, "pattern": null, "defaultValueCents": null },
    { "goalId": "ffffffff-1111-2222-3333-444444444444", "name": "Checkout", "type": "url", "matchType": "contains", "pattern": "/thank-you", "defaultValueCents": 2900 }
  ]
}

POST /sites/

curl -X POST -H "Authorization: Bearer $LA_API_KEY" -H "Content-Type: application/json" \
  -d '{"name": "Checkout", "type": "url", "matchType": "contains", "pattern": "/thank-you", "defaultValueCents": 2900}' \
  https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/goals

PATCH /goals/

Send only what changes, e.g. adjust the default conversion value for a campaign push:

curl -X PATCH -H "Authorization: Bearer $LA_API_KEY" -H "Content-Type: application/json" \
  -d '{"defaultValueCents": 4900}' \
  https://lightweightanalytics.com/api/v1/goals/ffffffff-1111-2222-3333-444444444444

DELETE /goals/

Deletes the goal definition and (by default) its recorded conversions. Keep the historical events with ?purgeEvents=false.

curl -X DELETE -H "Authorization: Bearer $LA_API_KEY" \
  https://lightweightanalytics.com/api/v1/goals/ffffffff-1111-2222-3333-444444444444

GET /sites/

Conversions and revenue per goal for a period.

curl -H "Authorization: Bearer $LA_API_KEY" \
  "https://lightweightanalytics.com/api/v1/sites/11111111-2222-3333-4444-555555555555/goals/stats?range=30d"
{
  "goals": [
    { "goalId": "ffffffff-1111-2222-3333-444444444444", "name": "Checkout", "type": "url", "conversions": 41, "revenue": 1189.00, "avgValue": 29.00 }
  ]
}

Recording pageviews & events

Normal pageviews need no API at all. The tracking snippet handles them. To record custom events or conversions from a server, script or agent, POST to the public collect endpoint (no API key; it validates the siteId):

curl -X POST -H "Content-Type: application/json" \
  -d '{"siteId": "11111111-2222-3333-4444-555555555555", "url": "/api-event", "event": "Signup", "value": 2900}' \
  https://analytics.lightweightanalytics.com/collect

Returns 202 on success. event names (1-40 chars, letters/numbers/spaces/-/_) that don't exist yet are auto-created as manual goals, so they show up in the dashboard immediately. value is in cents.


Notes for agents

  • Fetch this document any time at https://lightweightanalytics.com/docs/api.md (markdown). The short index is at https://lightweightanalytics.com/llms.txt.
  • GET /me is the cheapest way to verify a key before doing real work.
  • Site and goal ids are GUIDs; discover them via GET /sites and GET /sites/{siteId}/goals rather than guessing.
  • Deletes are destructive and require explicit confirmation parameters by design. Don't retry a confirmation_required error without checking with your human.
  • A native CLI (macOS & Windows) that wraps this API is coming soon; everything it will do is already possible with plain HTTP.