Querying your data
Beyond chat and dashboards, you can query your events directly with SQL:
use POST /api/v1/query/execute in the HTTP API, or ask the
assistant to run something specific.
The events view
Section titled “The events view”All of your analytics data is exposed as one queryable view named events,
automatically scoped to your projects server-side. There is no other table, and no
way to address anything outside your scope. The platform enforces that boundary.
SELECT event_name, COUNT(*) AS nFROM eventsWHERE __time > CURRENT_TIMESTAMP - INTERVAL '7' DAYGROUP BY 1ORDER BY 2 DESCLIMIT 10Useful columns: event_name, user_id, session_id, platform, project_id,
properties (JSON), and __time (the event’s timestamp column, used by every
time filter and bucket).
Queries are read-only (SELECT only), resource-capped, and cached briefly
server-side; a cache_ttl field on the request controls the cache window.
- Filter with
__timeand intervals:WHERE __time > CURRENT_TIMESTAMP - INTERVAL '30' DAY - Bucket with
TIME_FLOOR:SELECT TIME_FLOOR(__time, 'P1D') AS bucket, COUNT(*) FROM events GROUP BY 1. Periods are ISO-8601 strings (PT1Hhourly,P1Ddaily,P1Wweekly).
Properties are JSON
Section titled “Properties are JSON”Extract values with JSON_VALUE before filtering or grouping. Direct comparison
against the properties column fails with a type error:
SELECT JSON_VALUE(properties, '$.plan') AS plan, COUNT(*) AS nFROM eventsWHERE event_name = 'signup_completed'GROUP BY 1Dialect quirks (you will hit these)
Section titled “Dialect quirks (you will hit these)”The query engine’s SQL dialect has two rules that trip everyone once:
-
GROUP BY and ORDER BY can’t reference SELECT aliases. Use the ordinal or repeat the expression:
-- ✅ worksSELECT TIME_FLOOR(__time, 'P1D') AS event_day, COUNT(*) AS nFROM events GROUP BY 1 ORDER BY 1-- ❌ "Column not found": GROUP BY event_day -
Some natural aliases are reserved words.
day,hour,month, and friends fail confusingly as bare aliases. WriteAS event_day(or quote the alias) instead ofAS day.
Also: counting distinct users (COUNT(DISTINCT user_id)) is approximate at scale
(the trade every high-volume analytics engine makes), so treat small differences between
runs as noise.
Ready-made aggregates
Section titled “Ready-made aggregates”For simple time series without writing SQL, GET /api/v1/query/metrics/{metric}
returns bucketed counts (count, unique_users, unique_sessions) between two
timestamps at minute/hour/day granularity. It’s what powers the console’s
sparklines. See the HTTP API reference.
Reading dashboards & reports
Section titled “Reading dashboards & reports”The artifacts the assistant builds are readable over the same API: list and fetch
your dashboards (each fetch re-runs the widget queries against live data) and your
reports (frozen snapshots with their query receipts). See the
HTTP API reference for GET /api/v1/query/dashboards and
GET /api/v1/query/reports. Creating them is the assistant’s job, so there’s no
public write surface.