REST API

Realtime

The live "right now" feeds for one of the current team's sites: the online visitor count, a rich profile-resolved visitor feed for a live map, an activity ticker, and a lookup of favicon domains per traffic source. A site is addressed by {siteKey} (UUID or domain). All endpoints require Authorization: Bearer {token}.

Unlike the rest of the reporting API, realtime endpoints take no date range (range/from/to do not apply) — each one reads a fixed live window: [now - 5 minutes, now]. This is independent of the product-wide analytics session duration (config('clickbase.session_duration_minutes'), which only controls session continuity at ingest). The upper now bound keeps a future-dated or clock-skewed event from ever counting as online.

Who counts as online (same rules on the count, visitor markers, and activity feed — they stay in lockstep):

  • Non-engagement events only (event_type = engagement is excluded — a beacon marks a visit that already happened, never someone online right now).
  • payment events are excluded (Stripe/manual revenue rows must not create phantom visitors or wipe a pin with (0, 0) coords).
  • Visitors need a real geolocation: the latest event that carried non-zero latitude/longitude wins. A later custom event with missing geo does not drop them. Exact (0, 0) (ClickHouse's missing-geo sentinel) never counts.
  • The online count is uncapped; live visitor markers are capped at the 500 most recently active visitors (the live UI shows "showing X of Y" when the set is larger).

Most of these endpoints still accept the shared dashboard filters as query parameters (country, path, source, etc.) — see the exceptions noted per endpoint below.

Online visitor count

GET /api/sites/{siteKey}/stats/online

The distinct number of visitors currently online — the badge count. Accepts filters.

Response

Field Type Description
online int Distinct geolocated visitors (visitor_id) active in the 5-minute live window.

Status: 200 OK.

curl "https://clickbase.so/api/sites/example.com/stats/online" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/online', {
  headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests

requests.get(
    'https://clickbase.so/api/sites/example.com/stats/online',
    headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
{ "online": 7 }

Live visitors

GET /api/sites/{siteKey}/stats/live/visitors

One row per geolocated visitor active in the live window, carrying their last-known location (from the latest event that had real coordinates), path, and device context — the feed behind a live map. Identity resolves through the same profile matching as People, so a visitor renders with the same name/avatar there and here. Capped at the 500 most recently active visitors; the online count stays uncapped. Accepts filters.

Responsevisitors, a list of:

Field Type Description
visitor_id string The visitor's tracker-generated id.
user_id string The identify-call identifier; empty string when not identified.
is_identified bool Whether user_id is set.
display_name string Nickname derived from their identity.
avatar_url string Generated (or, once identified, custom) avatar URL.
latitude float Last known non-zero latitude.
longitude float Last known non-zero longitude.
city string City from the same event as the last known coordinates.
region string Region from the same event as the last known coordinates.
country string Country from the same event as the last known coordinates.
path string Last-hit page path.
device string Device type of their last event.
browser string Browser of their last event.
os string OS of their last event.
source string Last non-empty traffic source.
channel string Last non-empty acquisition channel.
referrer_domain string Last non-empty referrer domain.
last_seen_at string (ISO 8601) Timestamp of their most recent event in the window.
session_started_at string (ISO 8601) Earliest event of their current session (full history).
visit_count int Lifetime distinct sessions for this visitor on the site.

Status: 200 OK.

curl "https://clickbase.so/api/sites/example.com/stats/live/visitors" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/live/visitors', {
  headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests

requests.get(
    'https://clickbase.so/api/sites/example.com/stats/live/visitors',
    headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)

Live activity

GET /api/sites/{siteKey}/stats/live/activity

One row per geolocated online visitor in the live window (their latest non-engagement event), newest first — a lightweight ticker (no profile lookup or Postgres join). Accepts filters.

Query parameters

Parameter Type Required Description
limit int No Number of visitors, 1–100. Default 20.

Responsefeed, a list of:

Field Type Description
visitor_id string The visitor's tracker-generated id.
display_name string Nickname derived from the visitor's identity.
avatar_url string Generated avatar URL for that identity.
country string Country from the latest event that had real coordinates.
path string Latest event's page path.
event_type string e.g. pageview, event.
event_name string Custom event name; empty for a plain pageview.
timestamp string (ISO 8601) When the latest event fired.

Status: 200 OK.

curl "https://clickbase.so/api/sites/example.com/stats/live/activity?limit=50" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
const params = new URLSearchParams({ limit: '50' });
await fetch(`https://clickbase.so/api/sites/example.com/stats/live/activity?${params}`, {
  headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests

requests.get(
    'https://clickbase.so/api/sites/example.com/stats/live/activity',
    params={'limit': 50},
    headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)

Live source domains

GET /api/sites/{siteKey}/stats/live/source-domains

A map of traffic source → representative favicon domain, for rendering source icons on the live map/ticker. This endpoint takes no filters and no query parameters. Unlike the other realtime endpoints it is deliberately computed over a broad 30-day history rather than the live window (a favicon domain is a stable property of a source, not something that should flicker based on who's online right now), and the result is cached for one hour.

Responsesource_domains, an object keyed by source name:

Field Type Description
source_domains.{source} string The representative referrer domain for that source.

Status: 200 OK.

curl "https://clickbase.so/api/sites/example.com/stats/live/source-domains" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
await fetch('https://clickbase.so/api/sites/example.com/stats/live/source-domains', {
  headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
});
import requests

requests.get(
    'https://clickbase.so/api/sites/example.com/stats/live/source-domains',
    headers={'Authorization': f'Bearer {token}', 'Accept': 'application/json'},
)
{
    "source_domains": {
        "X (Twitter)": "x.com",
        "Google": "google.com"
    }
}