REST API reference
The OakData read API: bearer-authed JSON endpoints for overview, sessions, visitors, journeys, live, events, and replays.
The REST API serves your analytics back as JSON. Every endpoint is GET, lives under https://oakdata.co/api/v1, and is read-only. Requests are authenticated with a secret key and scoped to exactly one project.
Authentication
Pass your secret key (oak_sec_…) as a bearer token. An x-api-key header is accepted as a fallback.
curl https://oakdata.co/api/v1/overview \
-H "Authorization: Bearer oak_sec_xxxxxxxxxxxxxxxxxxxxxxxx"Secret keys only
These endpoints reject public keys (oak_pub_…) with 403 — public keys are browser-side and can only write events. A missing or invalid key returns 401. Because a key resolves to one project, a key for project A can never read project B.
Errors
Errors return a non-2xx status with a JSON body of the shape { "error": "message" }. Common cases: 400 (invalid query parameter, e.g. a bad range), 401 (missing/invalid key), 403 (public key used), and 404 (no such session or replay).
Overview
/api/v1/overviewThe headline view of traffic and conversion for a time window — aggregate stats plus the top dimensions.
| Query param | Type | Description |
|---|---|---|
range | string | Time window: 24h, 7d, 30d, or 90d. Defaults to 7d. |
exclude_bots | boolean | Exclude traffic classified as bots. Defaults to false. |
Response:
rangestringThe resolved time window.
statsobjectpageviews, visitors, sessions, avgSessionDurationSec, avgPagesPerSession, and bounceRate.
timeSeriesarrayPer-bucket points: { bucket, visitors, pageviews, sessions } (hourly for 24h, daily otherwise).
topPages, topReferrers, topSources, topCampaigns, topCountries, topCities, browsers, operatingSystems, deviceTypesarrayRanked breakdowns, each a list of { label, visitors, pageviews }.
eventCountnumberTotal events in the window.
Sessions
/api/v1/sessionsRecent visitor sessions, newest first.
| Query param | Type | Description |
|---|---|---|
range | string | Time window: 24h, 7d, 30d, or 90d. Defaults to 7d. |
limit | number | Max sessions to return (1–200). Defaults to 50. |
Returns { range, count, sessions }, where each session carries:
session_idstringThe session identifier.
distinct_idstringThe visitor (user id if identified, else anonymous id).
started_at / last_atstringISO timestamps for the session's first and last event.
pageviews / eventsnumberCounts within the session.
entry_path / exit_pathstring | nullFirst and last page paths.
referring_domainstring | nullWhere the session came from.
country / citystring | nullGeo, derived from IP at ingest.
browser / os / device_typestring | nullDevice context.
is_bot / bot_nameboolean / string | nullBot classification for the session.
Session detail
/api/v1/sessions/{id}The full ordered event timeline for one session id — every event row, oldest first. Returns 404 if the session has no events.
session_idstringThe session id you requested.
event_countnumberNumber of events returned.
eventsarrayThe raw event rows in chronological order. Each row includes event, timestamp, pathname, properties, and the device/geo columns. See events & properties.
Visitor profile
/api/v1/visitors/{distinctId}A single visitor's full profile, aggregated from the last 90 days. The path segment matches either the distinct_id or the anonymous_id, so activity from before sign-up is included.
distinct_idstringThe id you looked up.
user_idstring | nullThe identified user id, if any.
traitsobjectAccumulated traits (replayed from $identify / $set / $set_once).
groupsobjectGroup memberships, keyed by group type.
first_seen / last_seenstring | nullISO timestamps.
total_eventsnumberLifetime event count in the window.
sessionsarrayRecent sessions for this visitor (same shape as /sessions).
firstTouch / lastTouchobject | nullFirst- and last-touch attribution (referrer, UTM, path, timestamp).
identityTimelinearrayIdentity events with a human summary: { event, timestamp, summary }.
replaysarrayReplay references: { id, session_id, started_at, last_event_at, has_errors }.
Journey
/api/v1/journeyThe aggregated path/funnel tree for a time window — the common routes visitors take and where they drop off.
| Query param | Type | Description |
|---|---|---|
range | string | Time window: 24h, 7d, 30d, or 90d. Defaults to 7d. |
Returns { range, totalSessions, depth, roots }. roots is a tree of nodes; each node is { label, count, children[] }, where count is the number of sessions whose path passes through that node. depth is the maximum path length analyzed (3).
Live
/api/v1/liveWho is on the site right now — sessions active in the last 5 minutes. Takes no parameters.
{
"active_now": 2,
"sessions": [
{ "session_id": "s_a1b2c3", "last_seen": "2026-06-11T14:03:21.000Z" },
{ "session_id": "s_d4e5f6", "last_seen": "2026-06-11T14:01:55.000Z" }
]
}Events
/api/v1/eventsThe raw event firehose, newest first, paginated.
| Query param | Type | Description |
|---|---|---|
offset | number | Row offset for pagination. Defaults to 0 (max 1,000,000). |
limit | number | Max rows (1–500). Defaults to 100. |
Returns { offset, limit, rows, total }, where total is the exact count across all pages and rows are full event records.
Replays
/api/v1/replaysRecorded session replays for the project, newest first.
| Query param | Type | Description |
|---|---|---|
limit | number | Max replays (1–200). Defaults to 100. |
Returns { count, replays }. Each replay includes its recording id, session_id, distinct_id, started_at, last_event_at, duration_ms, chunks_count, entry_url, viewport and device fields, country, and has_errors.
Replay detail
/api/v1/replays/{sessionId}One replay by its recording id (the id from the list above — not the analytics session id). Returns the recording metadata plus short-lived signed URLs for each rrweb chunk.
sessionobjectThe replay metadata (same shape as a row from /replays).
chunk_urlsarrayA list of { url } objects — signed URLs to the gzipped NDJSON rrweb chunks, valid for ~30 minutes. A player fetches, gunzips, and merges them by timestamp.
Note
Returns 404 if no replay matches the id. Chunk URLs expire — fetch them fresh each time you need to play a recording.
Prefer to let an agent query this for you? The same data is available as MCP tools.