Skip to content

API Reference

The CloviAnalytics API lets you integrate CloviAnalytics into your own applications and automations. All endpoints are served over HTTPS from https://clovianalytics.clovitek.com.

Authentication

Authenticate every request with a Bearer token in the Authorization header. Generate a token from your account settings on the CloviAnalytics dashboard.

curl https://clovianalytics.clovitek.com/api/me \
  -H "Authorization: Bearer $CLOVI_TOKEN"
import requests

resp = requests.get(
    "https://clovianalytics.clovitek.com/api/me",
    headers={"Authorization": f"Bearer {token}"},
)
resp.raise_for_status()
print(resp.json())
const resp = await fetch("https://clovianalytics.clovitek.com/api/me", {
  headers: { Authorization: `Bearer ${token}` },
});
const data = await resp.json();
console.log(data);
import axios from "axios";

const { data } = await axios.get(
  "https://clovianalytics.clovitek.com/api/me",
  { headers: { Authorization: `Bearer ${token}` } }
);
console.log(data);

Keep your token secret

Treat your API token like a password. Send it only over HTTPS and never commit it to source control — load it from an environment variable instead.

Responses & errors

All responses are JSON. Successful calls return 2xx; client errors return 4xx with a JSON body describing the problem. Common status codes:

Status Meaning
200 Success
400 Bad request — check your parameters
401 Missing or invalid token
404 Resource not found
429 Rate limit exceeded — slow down and retry
500 Server error — retry or contact support

CloviAnalytics API Reference

Service: CloviAnalytics — cookieless, first-party web analytics
Port: 8976 (default; overridden by CLOVIANALYTICS_PORT)
Base URL (internal): http://127.0.0.1:8976
Public hostname: clovianalytics.clovitek.com


Authentication Overview

CloviAnalytics uses two authentication models:

Model Where used Token source
Session cookie (cl_session) All authed dashboard/app routes cl_session cookie or Authorization: Bearer <token> — JWT signed with JWT_SECRET
Site API key (ca_live_*) Event ingestion, webhook, widget, replay ingest x-api-key header or ?api_key= query param or JSON body field api_key/site

There is no separate developer Bearer token / public REST API key system yet. All authenticated application endpoints use the shared CloviTek AI session JWT (cl_session). A public developer API is not yet implemented.


Public Routes (no auth)

GET /api/health

Health check — returns event count and timestamp.

Auth: None
Parameters: None
Example:

curl https://clovianalytics.clovitek.com/api/health
Response:
{ "status": "ok", "service": "clovianalytics", "events_stored": 14203, "ts": "2026-06-16T10:00:00.000Z" }


GET /api/privacy

Returns the platform's privacy posture declaration.

Auth: None
Parameters: None
Example:

curl https://clovianalytics.clovitek.com/api/privacy
Response:
{
  "ok": true,
  "cookieless": true,
  "ip_anonymized": true,
  "pii_stored": false,
  "third_party_cookies": false,
  "ad_blocker_resistant": true,
  "data_residency": "first-party (self-hosted, no GA/3rd-party reseller)",
  "note": "..."
}


GET /api/snapshot

Free-tool lead magnet. Returns a real, point-in-time site-health score (security, SSL, performance, SEO, uptime) for any public domain. No auth required.

Auth: None
Query Parameters: - url or domain (string, required) — the public website to scan (e.g. clovitek.com)

Example:

curl "https://clovianalytics.clovitek.com/api/snapshot?url=clovitek.com"
Response:
{
  "ok": true,
  "snapshot": {
    "domain": "clovitek.com",
    "fetched_at": "...",
    "score": 82,
    "grade": "B",
    "measured": 3,
    "categories": [
      { "key": "security", "label": "Security", "status": "live", "score": 85, "grade": "B" },
      { "key": "ssl", "label": "SSL / Certificate", "status": "live", "valid": true, "days_remaining": 60 },
      { "key": "performance", "label": "Performance (Web Vitals)", "status": "live", "score": 72 }
    ],
    "fixes": [
      { "impact": "medium", "text": "Performance score 72/100 — optimise Core Web Vitals." }
    ],
    "locked": ["Live visitors & traffic (needs the cookieless tracker snippet)", "..."]
  }
}
Errors: 400 Bad Request (invalid URL), 502 Bad Gateway (snapshot service error)


POST /api/snapshot/lead

Captures a lead email after the free snapshot tool. Stores the email and pushes to CloviCRM (best-effort).

Auth: None
Body (JSON): - email (string, required) — visitor email - domain (string, optional) — domain they scanned - score (number, optional) — site health score shown to them

Example:

curl -X POST https://clovianalytics.clovitek.com/api/snapshot/lead \
  -H "Content-Type: application/json" \
  -d '{"email":"user@example.com","domain":"clovitek.com","score":82}'
Response:
{ "ok": true, "next": "https://platform.clovitek.com/" }
Errors: 400 Bad Request (invalid_email)


GET /api/auth/me

Checks whether the current session (cookie or Bearer token) is valid and returns the user identity. Also provisions a default site for new users (first-touch only).

Auth: Session cookie (cl_session) or Authorization: Bearer <token> — accepts either the shared CloviTek AI JWT or the standalone product JWT
Parameters: None
Example:

curl https://clovianalytics.clovitek.com/api/auth/me \
  -H "Cookie: cl_session=<token>"
Response:
{ "ok": true, "user": { "id": "42", "email": "user@example.com", "role": "user", "name": "Alice" } }
Errors: 401 Unauthorized


Event Ingestion Routes (Site API Key)

These endpoints accept requests from the browser tracker or any REST client. Auth is via a per-site API key (ca_live_*), not a session cookie.

POST /api/collect

Ingest a pageview or custom event from the tracker. CORS is open (*).

Auth: Site API key via x-api-key header, ?api_key= query param, or JSON body field api_key or site
Body (JSON): - type (string) — pageview or any custom event name (default: pageview) - name (string, optional) — event name (used for custom events) - url (string, optional) — page URL - referrer (string, optional) — referring URL - visitor_id (string, optional) — stable visitor ID (auto-derived from IP+UA hash if omitted) - session_id (string, optional) — session ID (auto-derived if omitted) - meta or props (object, optional) — custom properties; supports device, browser, os, country, utm_source, utm_medium, utm_campaign

Example:

curl -X POST https://clovianalytics.clovitek.com/api/collect \
  -H "Content-Type: application/json" \
  -H "x-api-key: ca_live_abc123" \
  -d '{"type":"pageview","url":"https://example.com/pricing","referrer":"https://google.com"}'
Response:
{ "ok": true, "accepted": "pageview" }
Errors: 401 Unauthorized (invalid/missing key), 429 Too Many Requests (monthly event limit reached)


POST /api/ingest/webhook

Ingest an event from an external source (Zapier, Make, Stripe webhook, raw HTTP POST). CORS is open. Counts against the same monthly event cap as /api/collect.

Auth: Site API key via x-api-key, x-clovi-key header, ?key= or ?api_key= query param, or JSON body field key, site, or api_key
Body (JSON) — Stripe shape (auto-detected):
When the body matches a Stripe event envelope ({ object: "event", type: "...", data: { object: {...} } }), it is automatically normalized into a stripe.<type> event with value (amount in dollars), currency, status.

Body (JSON) — Generic shape: - name (string, optional) — event name (default: webhook_event) - source (string, optional) — source label (default: webhook) - value (number, optional) — numeric value (e.g. revenue) - visitor_id (string, optional) — visitor/customer identifier - url (string, optional) — associated URL - referrer (string, optional) - props (object, optional) — additional properties - map (object, optional) — JSONPath-style field mapping for Zapier/Make: { name: "$.event", value: "$.amount", visitor: "$.email", props: ["$.plan"] }

Example (Zapier generic):

curl -X POST "https://clovianalytics.clovitek.com/api/ingest/webhook?api_key=ca_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{"name":"signup","value":49,"visitor_id":"user@example.com","props":{"plan":"pro"}}'
Response:
{ "ok": true, "accepted": "signup", "source": "webhook", "event_id": 9182, "normalized": "raw", "value": 49 }
Errors: 401 Unauthorized, 429 Too Many Requests


POST /api/replay/ingest

Ingest a session replay chunk from the browser recorder. CORS is open. Plan-gated: Growth/Pro only.

Auth: Site API key via x-api-key header or ?api_key= query param
Body (JSON): - session_id (string, required) — stable replay session ID - seq (number, required) — chunk sequence number (0-indexed) - events (array, required unless snapshot present) — recorder events - snapshot (object, optional) — initial full DOM snapshot (seq 0) - page (string, optional) — entry page URL - visitor_id (string, optional) - ts_start, ts_end (number, optional) — epoch milliseconds - meta (object, optional) — { device, browser, os, country } (no PII)

Example:

curl -X POST "https://clovianalytics.clovitek.com/api/replay/ingest?api_key=ca_live_abc123" \
  -H "Content-Type: application/json" \
  -d '{"session_id":"rs_abc123","seq":0,"events":[{"t":"click","x":120,"y":80}],"page":"https://example.com/"}'
Response:
{ "ok": true, "session_id": "rs_abc123", "seq": 0, "stored": "s3-key", "bytes": 412 }
Errors: 401 Unauthorized, 400 Bad Request (missing session_id or events), 403 Forbidden (plan gate — Growth/Pro required), 429 Too Many Requests (monthly session replay limit reached), 502 Bad Gateway (S3 store failed)


GET /tracker.js

Serves the client-side tracker script. CORS is open.

Auth: None
Query Parameters: None (the script reads data-site from its own <script> tag)
Usage:

<script src="https://clovianalytics.clovitek.com/tracker.js"
        data-site="ca_live_abc123"
        data-auto="scroll,download,outbound,form"
        data-heatmap="true"
        data-replay="true">
</script>


Widget Routes (Site API Key)

GET /api/widget/data/:metric

Returns a single metric or overview bundle for embedding in external dashboards. CORS is open.

Auth: Site API key via x-api-key header or ?api_key= query param
Path Parameters: - metricpageviews, visitors, sessions, bounce-rate, events, or overview

Example:

curl "https://clovianalytics.clovitek.com/api/widget/data/pageviews?api_key=ca_live_abc123"
Response (single metric):
{ "value": 3420, "period": "7d" }
Response (overview):
{
  "pageviews": { "value": 3420, "period": "7d" },
  "visitors": { "value": 1100, "period": "7d" },
  "sessions": { "value": 1340, "period": "7d" },
  "bounce-rate": { "value": "42.3%", "period": "7d" },
  "events": { "value": 5200, "period": "7d" },
  "series": [{ "date": "2026-06-09", "value": 480 }, ...]
}
Errors: 401 Unauthorized, 404 Not Found (unknown metric)


GET /widget/

Renders an embeddable HTML badge showing a single metric. CORS is open.

Auth: Site API key via ?api_key= query param
Query Parameters: - metric (string) — pageviews, visitors, sessions, bounce-rate, or events (default: pageviews) - theme (string) — light or dark (default: light) - api_key (string, required) — site API key

Example:

<iframe src="https://clovianalytics.clovitek.com/widget/?metric=pageviews&theme=dark&api_key=ca_live_abc123"
        width="180" height="60" frameborder="0"></iframe>
Response: HTML page with a live metric badge


All routes below require a valid cl_session cookie or Authorization: Bearer <token>. Unauthorized requests to JSON endpoints return 401; unauthorized requests to page routes redirect to /login.


GET /api/site

Returns the authenticated user's default (or first) site and its API key.

Auth: Session cookie (cl_session)
Parameters: None
Response:

{ "ok": true, "site": { "id": 1, "name": "My Site", "api_key": "ca_live_abc123", "plan": "free" } }


GET /api/plan

Returns the current plan, enforced limits, and live usage for the authenticated user's account.

Auth: Session cookie (cl_session)
Parameters: None
Response:

{
  "ok": true,
  "early_access": true,
  "plan": "free",
  "plan_label": "Free",
  "limits": { "events_month": 10000, "sites": 1, "history_days": 7, "replay_sessions_month": 0, "replay_retention_days": 0 },
  "usage": { "events_month": 1234, "events_month_limit": 10000, "sites": 1, "sites_limit": 1, "history_days": 7 },
  "all_plans": { "free": {...}, "lite": {...}, "growth": {...}, "pro": {...} }
}


GET /api/metrics/overview

Returns aggregate metrics (pageviews, visitors, sessions, bounce rate, events) for the requested window. Supports segment filters.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — history window in days; clamped to plan ceiling (default: 7) - Segment filters: source, device, browser, os, country, referrer, utm_source, utm_medium, utm_campaign

Example:

curl "https://clovianalytics.clovitek.com/api/metrics/overview?days=30&device=mobile" \
  -H "Cookie: cl_session=<token>"
Response:
{
  "ok": true,
  "site_id": 1,
  "days": 30,
  "segment": { "device": "mobile" },
  "metrics": {
    "pageviews": { "value": 8200, "period": "30d" },
    "visitors": { "value": 3100, "period": "30d" },
    "sessions": { "value": 3800, "period": "30d" },
    "bounce-rate": { "value": "38.5%", "period": "30d" },
    "events": { "value": 12400, "period": "30d" }
  }
}


GET /api/metrics/series/:metric

Returns a daily time series for the requested metric over up to 90 days.

Auth: Session cookie (cl_session)
Path Parameters: - metricpageviews (or events to count all event types)

Query Parameters: - days (number) — window in days, max 90 (default: 30)

Response:

{ "ok": true, "series": [{ "date": "2026-05-17", "value": 340 }, ...] }


GET /api/reports

Returns full MonsterInsights-style report depth: top sources, landing pages, top pages, exit pages, devices, browsers, OS, geography, and top events.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — history window, clamped to plan (default: 7) - Segment filters (same as /api/metrics/overview)

Response:

{
  "ok": true,
  "site_id": 1,
  "days": 7,
  "segment": null,
  "reports": {
    "sources": [{ "source": "google.com", "views": 820 }],
    "landing_pages": [{ "page": "/", "sessions": 610 }],
    "top_pages": [{ "page": "/pricing", "views": 340 }],
    "exit_pages": [{ "page": "/checkout", "sessions": 200 }],
    "devices": [{ "value": "desktop", "count": 900 }],
    "browsers": [{ "value": "Chrome", "count": 740 }],
    "os": [{ "value": "macOS", "count": 420 }],
    "geography": [{ "value": "US", "count": 550 }],
    "top_events": [{ "name": "signup", "count": 48 }]
  }
}


GET /api/realtime

Returns active visitors and events in the last 5 minutes.

Auth: Session cookie (cl_session)
Parameters: None
Response:

{ "ok": true, "active_visitors": 4, "events_5m": 12, "recent": [{ "type": "pageview", "url": "...", "ts": "..." }] }


GET /api/channels

Returns UTM/channel grouping (Direct, Organic Search, Paid Search, Social, Email, Referral, Affiliate, Campaign) with pageview counts and percentages.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{ "ok": true, "days": 7, "segment": null, "channels": [{ "channel": "Organic Search", "views": 410, "pct": 42.1 }] }


GET /api/visitors

Returns a paginated list of visitors with event/session/pageview counts, first/last seen timestamps.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{
  "ok": true, "days": 7,
  "visitors": [{ "visitor_id": "a1b2c3d4...", "events": 14, "sessions": 3, "pageviews": 10, "first_seen": "...", "last_seen": "..." }]
}


GET /api/visitors/:id

Returns the full session timeline for a single visitor.

Auth: Session cookie (cl_session)
Path Parameters: - id — visitor ID (from /api/visitors list)

Query Parameters: - days (number) — max 365 (default: 90)

Response:

{
  "ok": true,
  "profile": {
    "visitor_id": "a1b2c3d4...",
    "first_seen": "...", "last_seen": "...",
    "total_events": 14, "sessions": 3, "pageviews": 10,
    "revenue": 49.00, "country": "US",
    "timeline": [{ "session_id": "...", "started": "...", "events": 5, "items": [...] }]
  }
}
Errors: 404 Not Found (visitor has no events in window)


GET /api/paths

Returns entry pages, exit pages, and next-page transition pairs derived from session sequences.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{
  "ok": true,
  "paths": {
    "top_entry": [{ "page": "/", "count": 480 }],
    "top_exit": [{ "page": "/checkout", "count": 120 }],
    "top_transitions": [{ "path": "/ → /pricing", "count": 95 }]
  }
}


GET /api/trends

Returns period-over-period delta for pageviews, visitors, sessions, and events (current window vs. the prior equal-length window).

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{
  "ok": true,
  "trends": {
    "period_days": 7,
    "current": { "pageviews": 3400, "visitors": 1100, "sessions": 1300, "events": 5200 },
    "previous": { "pageviews": 3000, "visitors": 980, "sessions": 1150, "events": 4700 },
    "delta": {
      "pageviews": { "current": 3400, "previous": 3000, "change": 400, "pct": 13.3 }
    }
  }
}


GET /api/funnels

Lists saved funnel definitions with computed conversion results. Pass ?id=N to compute a single saved funnel. Supports segment filters.

Auth: Session cookie (cl_session)
Query Parameters: - id (number, optional) — compute a specific saved funnel - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{
  "ok": true,
  "funnels": [{
    "id": 1, "name": "Checkout funnel",
    "steps": [{ "step": 1, "label": "Visit /pricing", "count": 800, "dropoff_pct": 0, "conversion_from_start_pct": 100 }],
    "total_entered": 800, "completed": 48, "overall_conversion_pct": 6.0
  }]
}


POST /api/funnels

Compute an ad-hoc multi-step funnel. Pass save: true to persist the definition.

Auth: Session cookie (cl_session)
Body (JSON): - steps (array, required) — array of { type: "url"|"event", value: string, label?: string } - name (string) — required if save: true - save (boolean, optional) — persist this funnel definition

Example:

curl -X POST https://clovianalytics.clovitek.com/api/funnels \
  -H "Content-Type: application/json" \
  -H "Cookie: cl_session=<token>" \
  -d '{"steps":[{"type":"url","value":"/pricing","label":"Pricing"},{"type":"event","value":"signup","label":"Signup"}],"name":"Trial funnel","save":true}'
Response:
{ "ok": true, "saved": true, "id": 3, "funnel": { "id": 3, "name": "Trial funnel", "steps": [...], "total_entered": 600, "completed": 30, "overall_conversion_pct": 5.0 } }
Errors: 400 Bad Request (missing steps, missing name when save: true)


DELETE /api/funnels/:id

Deletes a saved funnel definition.

Auth: Session cookie (cl_session)
Path Parameters: - id — funnel ID

Response:

{ "ok": true }


GET /api/cohorts

Returns a visitor retention triangle grouped by first-seen week (or day). Each cohort row shows how many visitors returned in each subsequent period.

Auth: Session cookie (cl_session)
Query Parameters: - granularity (string) — week (default) or day - days (number) — window; max 365; default 90 (week) or 30 (day) - Segment filters

Response:

{
  "ok": true,
  "cohorts": {
    "granularity": "week",
    "max_offset": 4,
    "cohorts": [{ "cohort": "2026-05-12", "size": 240, "cells": [{ "offset": 0, "count": 240, "pct": 100 }, { "offset": 1, "count": 80, "pct": 33.3 }] }]
  }
}


GET /api/heatmap

Returns click-density grid and scroll-depth buckets for a page. Without ?page=, lists pages that have heatmap data. Requires opt-in data-heatmap="true" on the tracker script.

Auth: Session cookie (cl_session)
Query Parameters: - page (string, optional) — pathname (e.g. /pricing); omit to list available pages - days (number) — clamped to plan (default: 7) - grid (number) — grid resolution, 8–40 (default: 20) - Segment filters

Response:

{
  "ok": true, "days": 7, "page": "/pricing",
  "heatmap": {
    "has_data": true, "clicks": 320, "scroll_samples": 180, "max_cell": 42, "grid": 20,
    "density": [{ "gx": 10, "gy": 3, "count": 42 }],
    "top_selectors": [{ "selector": "#cta-btn", "count": 95 }],
    "scroll_buckets": [{ "depth": 25, "count": 120 }, { "depth": 50, "count": 80 }]
  },
  "pages": [{ "page": "/pricing", "count": 320 }]
}


GET /api/geo

Returns country breakdown derived offline at collection time (raw IPs are never stored).

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - Segment filters

Response:

{ "ok": true, "days": 7, "geography": [{ "value": "US", "count": 550 }], "note": "Country derived offline at collection time; raw IP is never stored." }


GET /api/insights

Returns data-derived, rule-based actionable insights: high bounce rate, anomalous exit pages, mobile vs desktop conversion gaps, low conversion rates, traffic drops, and (when a domain is resolved) Lighthouse performance and CloviScan security dips.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — clamped to plan (default: 7) - domain (string, optional) — domain to fuse performance/security streams (auto-derived from most-recent pageview URL if omitted)

Response:

{
  "ok": true, "days": 7, "domain": "example.com",
  "count": 2,
  "summary": "2 recommended action(s)",
  "insights": [
    { "metric": "bounce_rate", "scope": "site", "observed": "78%", "baseline": "70% (high-bounce threshold)", "severity": "medium", "recommendation": "Site bounce rate is 78%..." },
    { "metric": "performance", "scope": "example.com", "observed": "LCP 5.2s", "baseline": "2.5s (good) / 4s (poor)", "severity": "medium", "recommendation": "..." }
  ]
}


GET /api/trust-health

Fuses CloviScan security, SSL certificate, Lighthouse Web Vitals, and Blackbox uptime into one panel for the authenticated user's site domain.

Auth: Session cookie (cl_session)
Query Parameters: - domain (string, optional) — domain to fuse (auto-derived from most-recent pageview URL if omitted)

Response:

{ "ok": true, "configured": true, "domain": "example.com", "streams": { "security": {...}, "ssl": {...}, "vitals": {...}, "uptime": {...} } }


GET /api/goals

Returns all goals with their conversion counts for the requested window.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — max 365 (default: 30)

Response:

{ "ok": true, "goals": [{ "id": 1, "name": "Signup", "match_type": "event", "match_value": "signup", "conversions": 48 }] }


POST /api/goals

Creates a new conversion goal.

Auth: Session cookie (cl_session)
Body (JSON): - name (string, required) — goal label - match_type (string) — event (default) or url - match_value (string, required) — event name to match (for event) or URL substring (for url)

Example:

curl -X POST https://clovianalytics.clovitek.com/api/goals \
  -H "Content-Type: application/json" \
  -H "Cookie: cl_session=<token>" \
  -d '{"name":"Checkout Complete","match_type":"url","match_value":"/thank-you"}'
Response:
{ "ok": true, "id": 2 }
Errors: 400 Bad Request (missing name or match_value)


DELETE /api/goals/:id

Deletes a goal.

Auth: Session cookie (cl_session)
Response:

{ "ok": true }


GET /api/dimensions

Returns all custom dimensions with live value breakdowns over the requested window.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — max 90 (default: 30)

Response:

{ "ok": true, "dimensions": [{ "id": 1, "key": "plan", "label": "Plan", "breakdown": [{ "value": "pro", "count": 80 }] }] }


POST /api/dimensions

Registers a new custom dimension key to segment by (e.g. utm_source, plan, author).

Auth: Session cookie (cl_session)
Body (JSON): - key (string, required) — meta key to segment by - label (string, optional) — display label

Response:

{ "ok": true, "id": 1 }
Errors: 400 Bad Request (missing key)


GET /api/agency/rollup

Returns per-site aggregate metrics across all sites owned by the authenticated user. Used for the agency multi-site dashboard.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — max 90 (default: 7)

Response:

{
  "ok": true, "site_count": 3,
  "totals": { "pageviews": 9400, "visitors": 3200, "sessions": 3900, "events": 14800 },
  "sites": [{ "site_id": 1, "name": "My Site", "plan": "growth", "api_key": "ca_live_...", "pageviews": 6000, "visitors": 2100, "sessions": 2500, "events": 9800 }]
}


GET /api/sites

Lists all sites for the authenticated user.

Auth: Session cookie (cl_session)
Response:

{ "ok": true, "sites": [{ "id": 1, "name": "My Site", "api_key": "ca_live_abc123", "plan": "free" }] }


POST /api/sites

Creates an additional site (plan enforcement: site count cap applies).

Auth: Session cookie (cl_session)
Body (JSON): - name (string, optional) — site name (default: New Site)

Response:

{ "ok": true, "site": { "id": 2, "name": "Blog", "api_key": "ca_live_xyz789" } }
Errors: 403 Forbidden (site limit reached for plan)


GET /api/replay/sessions

Lists recorded session replay sessions (newest first). Only returns sessions that actually have stored chunks. Growth/Pro plans only; empty for free/lite.

Auth: Session cookie (cl_session)
Query Parameters: - days (number) — max 365 (default: 30); clamped to plan retention window - page (string, optional) — filter by entry page substring - visitor_id (string, optional) — filter by visitor

Response:

{
  "ok": true,
  "enabled": true,
  "early_access": true,
  "plan": "growth",
  "retention_days": 30,
  "sessions_month_limit": 1000,
  "sessions_used_month": 42,
  "days": 30,
  "sessions": [{ "session_id": "rs_abc123", "visitor_id": "...", "page": "https://example.com/", "started_at": "...", "ended_at": "...", "duration_ms": 38000, "event_count": 120, "chunk_count": 3, "has_snapshot": 1, "meta": null }]
}


GET /api/replay/:sessionId

Fetches all replay chunks for a session from S3, merges them into a single ordered timeline (snapshot + events). Growth/Pro only.

Auth: Session cookie (cl_session)
Path Parameters: - sessionId — session ID from /api/replay/sessions

Response:

{
  "ok": true,
  "session": { "session_id": "rs_abc123", "page": "https://example.com/", "started_at": "...", "ended_at": "...", "duration_ms": 38000, "event_count": 120, "meta": null },
  "chunks": 3,
  "snapshot": { "type": 1, "tag": "html", "childNodes": [...] },
  "events": [{ "t": "click", "x": 120, "y": 80 }, ...]
}
Errors: 403 Forbidden (plan gate), 404 Not Found (no such recorded session), 502 Bad Gateway (S3 fetch failed)


POST /api/reports/email

Fires an email summary of site metrics for the requested window via CloviNotify. Best-effort — returns dispatched: false with error detail if CloviNotify is unreachable, without failing the caller.

Auth: Session cookie (cl_session)
Body (JSON): - to (string, optional) — recipient email (defaults to authenticated user's email) - days (number, optional) — max 90, default 7

Response:

{ "ok": true, "dispatched": true, "notify": { ... }, "summary": { "site": "My Site", "period": "7d", "pageviews": 3400, ... } }
Errors: 400 Bad Request (no recipient)


Connector / Source Routes

All return a live/no-data/not-configured state with real data. Auth: session cookie (cl_session).

Route Source Notes
GET /api/sources Connector registry LIVE vs ROADMAP inventory
GET /api/sources/ga4 Google Analytics 4 Weekly report from real GA4 property
GET /api/sources/umami Umami (self-hosted) Pageviews/sessions matched to site domain
GET /api/sources/stability Prometheus node_exporter CPU/mem/disk/uptime
GET /api/sources/stability/series Prometheus Time-series; ?hours=N (max 168, default 6)
GET /api/sources/security CloviScan + SSL Security score, grade, SSL cert status
GET /api/sources/performance Lighthouse (via Trust & Health) Web Vitals — LCP, CLS, TBT, performance score
GET /api/sources/pm2 PM2 Fleet process health, CPU/mem/restarts
GET /api/sources/uptime Blackbox probe Per-domain up/down, HTTP status, response time, 24h availability
GET /api/sources/certs Blackbox probe SSL days-to-expiry per domain

All /api/sources/* endpoints support an optional ?domain= query parameter where applicable.


Cross-Product Routes (Tenant Auto-Connect)

Auth: session cookie (cl_session). These endpoints join the authenticated user's entitlements and data across CloviTek AI sibling products.

GET /api/me/connections

Returns the auto-detected connections from the authenticated user's CloviTek AI subscriptions (entitlement-driven, zero config).

Response:

{ "ok": true, "connections": [{ "product": "CloviScan", "status": "connected", ... }] }


GET /api/me/overview

Returns cross-product KPIs in one payload, including the user's captured revenue from connected Stripe webhooks.

Query Parameters: - days (number) — max 365 (default: 30)

Response:

{ "kpis": { "revenue": 1240.50, ... }, "period_days": 30 }


Shared Auth Routes (mounted from /root/clovitek-shared/auth/auth_node.js)

These routes are mounted from the shared CloviTek AI auth module and use a separate clovianalytics_auth.db SQLite database.

POST /api/auth/register

Creates a standalone CloviAnalytics account and fires a signup lead to CloviCRM.

Auth: None
Body (JSON): email, password, name (fields per shared auth module)
Response: JWT session token set as CloviAnalytics_token cookie


POST /api/auth/login

Authenticates a standalone account.

Auth: None
Body (JSON): email, password
Response: JWT session token set as CloviAnalytics_token cookie


GET /api/auth/me

Also mounted by the shared module (identical to the analytics-native /api/auth/me above; the analytics-native handler takes precedence since it is mounted first).


GET /api/me

Alias for /api/auth/me (mounted by the shared module).


POST /api/auth/logout

Clears the session cookie.

Auth: None required
Response: Clears CloviAnalytics_token cookie


Segment Filter Reference

All authenticated analytics endpoints that accept a days parameter also accept these query-string filters to slice metrics by segment:

Parameter Matches
source Referrer host or utm_source value
device mobile or desktop
browser e.g. Chrome, Firefox, Safari
os e.g. Windows, macOS, iOS
country ISO 3166-1 alpha-2 code (e.g. US)
referrer Referrer URL substring
utm_source UTM source value
utm_medium UTM medium value
utm_campaign UTM campaign value

Segmented views always read only the hot (non-archived) event window — archived rollup data is not segmentable.


Plan Limits

Plan Events/mo Sites History Replay sessions/mo Replay retention
Free 10,000 1 7 days 0 (locked)
Lite 10,000 3 7 days 0 (locked)
Growth 500,000 10 90 days 1,000 30 days
Pro 5,000,000 999 365 days 10,000 90 days

Billing is gated (CT-004 — Early access). Plan limits are enforced in code regardless.


Generated from /root/clovianalytics/server.js — 2026-06-16