Events & ExportExplore query (trend, funnel, paths or attribution)

Explore query (trend, funnel, paths or attribution)

Self-serve analytics over the event stream in one call. A typed spec — no raw SQL — is validated, compiled server-side to ClickHouse SQL over a wide, typed events table, and scoped to your location by the compiler. Sub-second at current scale: a 30-day trend broken down by a property reads tens of megabytes where the same question over raw JSON properties did not finish.

Trend (kind: trend): 1–5 series, each an event (or null for any event) × math (total, dau, unique_sessions, sum, avg, min, max, median, p90, p95, p99; numeric maths need math_property), bucketed by interval (hour|day|week|month) or returned as one number per series when interval is omitted. Optional breakdown by any property (top-N by the first series; the rest fold into "$$other") and compare: previous_period (the immediately preceding window of equal length, aligned by bucket index, and truncated at the same time of day so today-so-far is not compared against a whole day).

Funnel (kind: funnel): 2–10 ordered steps, a conversion window (default 7 days, capped at the range), optional breakdown taken from the first step. Sequential: other events may occur between steps. Per-step users, conversion_from_first, conversion_from_previous.

Paths (kind: paths): the journeys persons took before a goal event, plus first-touch and last-touch counts. By default each session is one step labeled by channel group (Paid Search, Paid Social, Email, Organic Search, Direct, …) over a 90-day lookback, with all of a person's devices and CRM ids joined. touchpoint: event makes each event a step instead (pageviews by pathname).

Properties: typed names resolve to columns — $current_url, $pathname, $referrer, $referring_domain, utm_source, utm_medium, utm_campaign, utm_content, utm_term, $device_type, $browser, $os, $geo_country, $geo_city, $experiment_arm, plus event, distinct_id, session_id, user_id. Any other name is a custom event property (scalar, ≤200 chars; nested objects and meta_* blobs are not queryable). utm_*, $referrer and $referring_domain are session-entry values with an event-level fallback. Discover keys with GET /properties and values with GET /query/values.

Semantics: buckets are UTC and zero-filled; presets resolve to [today-N, today] inclusive; unique counts are uniq() (approximate) on distinct_id, not resolved persons. Excluded events: $replay_summary, $replay_started, $heatmap, $web_vital_*, $set, $set_once, $identify (each has its own surface).

Limits (400 invalid_spec, every problem listed in error.details): unknown keys rejected, ≤5 series, 2–10 steps, ≤20 filters in total, range ≤366 days, hour only for ranges ≤31 days, in lists ≤100 values, breakdown limit ≤50. Rate limit 30 requests / 10 s per location. Cached 120 s when the range touches today, 6 h otherwise (meta.cached).

curl -X POST "https://mythic-analytics.gulp.workers.dev/client/v1/data/query?location_id=example_string&debug=example_string" \
  -H "Content-Type: application/json" \
  -H "X-Location-Id: example_string" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "kind": "trend",
  "date_range": {
    "preset": "30d"
  },
  "interval": "day",
  "series": [
    {
      "event": "$pageview",
      "math": "dau"
    }
  ],
  "breakdown": {
    "property": "utm_source",
    "limit": 5
  },
  "compare": "previous_period",
  "filters": [
    {
      "property": "$device_type",
      "op": "eq",
      "value": "mobile"
    }
  ]
}'
{
  "success": true,
  "data": {
    "kind": "trend",
    "buckets": [
      "2026-08-30",
      "2026-08-31",
      "2026-09-01"
    ],
    "breakdown_values": [
      "google",
      "",
      "$$other"
    ],
    "series": [
      {
        "label": "$pageview · dau",
        "math": "dau",
        "event": "$pageview",
        "breakdown_value": "google",
        "data": [
          412,
          388,
          97
        ],
        "total": 897,
        "previous": [
          390,
          401,
          120
        ]
      }
    ],
    "meta": {
      "from": "2026-08-30",
      "to": "2026-09-01",
      "interval": "day",
      "previous": {
        "from": "2026-08-27",
        "to": "2026-08-29"
      },
      "sql_ms": 212,
      "rows_read": 778534,
      "bytes_read": 36060000,
      "cached": false
    }
  }
}
POST
/query
POST
Base URLstring

Target server for requests. Edit to use your own host.

Bearer Token
Bearer Tokenstring
Required

Agency key (ak_) or location secret key (sk_) as a bearer token. Format: Bearer ak_... or Bearer sk_.... Scoped keys (mcp_) are accepted too and need the read scope of the family the route belongs to (people, events, sessions, replays, exceptions, heatmaps or bigquery_export). See Using an mcp_ key over HTTP.

Agency key (ak_) or location secret key (sk_) as a bearer token. Format: Bearer ak_... or Bearer sk_.... Scoped keys (mcp_) are accepted too and need the read scope of the family the route belongs to (people, events, sessions, replays, exceptions, heatmaps or bigquery_export). See Using an mcp_ key over HTTP.
query
location_idstring

Alternative to the X-Location-Id header for agency (ak_) keys. Ignored for secret (sk_) keys.

query
debugstring

1 adds the compiled SQL to meta.sql (agency keys only).

Content-Typestring
Required

The media type of the request body

Options: application/json
header
X-Location-Idstring

Location to scope the request to. Required for agency (ak_) keys on the event routes. Ignored for secret (sk_) keys, which resolve their own location, and not used by /export.

kindstring
Required
Options: trend, funnel, paths, attribution
intervalstring

Trend only. Omit for one number per series.

Options: hour, day, week, month
seriesarray

Trend only.

comparestring

Trend only.

Options: previous_period
stepsarray

Funnel only. Ordered; other events may occur between steps.

windowobject

Funnel only. Default 7 days, capped at the range length.

grainstring

Funnel (default device) and paths (default person). device counts the raw distinct_id; person resolves each id to its canonical person first, so a journey across devices — or a step that is a server/CRM event keyed by a contact id — links instead of breaking. Slower (it joins the identity map for the window); trends have no grain.

Options: device, person
filtersarray

Applied to every series / step. Not accepted on paths (use goal.filters).

goalobject

Paths: required. Persons who did this in the range; each journey is what they did in the lookback before their first goal in the range. Attribution: the conversion event (or use deals); every occurrence in the range is one conversion, credited to the touches before it.

touchpointstring

Paths only. session: one step per session, labeled by dimension. event: one step per event, pageviews labeled by pathname.

Options: session, event
dimensionstring

Paths with session touchpoints only. Self-referral sessions (referrer on the landing page's own registrable domain) are dropped; a journey made only of them reads as Direct. campaign is case- and URL-encoding-insensitive, and numeric Meta campaign ids are replaced by their names when the client syncs Meta Ads.

Options: channel_group, source_medium, source, campaign
lookback_daysinteger

Paths: default 90 for session touchpoints, 7 for event touchpoints. Attribution: default 30, how far before a conversion a touch can be.

Min: 1 • Max: 180
depthinteger

Paths only. Last N touchpoints kept per journey.

Min: 1 • Max: 10
limitinteger

Paths: default 20, max 50, journeys returned and rows per first/last-touch list. Attribution: default 100, max 500 rows; totals still cover every row.

Min: 1 • Max: 500
excludearray

Paths with event touchpoints only. Added to the default excludes ($pageleave, $engagement, $exception, $autocapture, $experiment_viewed, tag_added, tag_removed).

default_excludesboolean

Paths with event touchpoints only. false keeps the default-excluded events.

value_propertystring

Paths and attribution (with goal). Numeric property of the goal event (e.g. value, activity_value). Paths: adds goal_value, goal_first_value, and value / first_value on journey, first-touch and last-touch rows (value on linear_touch), summed per person over their goal events in the range; first_value is the first goal only. Attribution: the revenue of each conversion. Non-numeric values count as 0.

dealsobject

Attribution only, instead of goal: won CRM deals (GHL opportunities whose latest status is won). One conversion per opportunity, at the time it was first marked won, valued at its latest monetary value.

modelstring

Attribution only. last credits the last non-Direct touch (Direct only when every touch is Direct). first credits the first touch in the lookback. linear splits each conversion evenly across its touches.

Options: first, last, linear
levelstring

Attribution only. Row grain. Ad set and ad ids come from the landing URL (Meta adset_id/ad_id, Google adgroupid/creative, or Meta's utm_term/utm_content id template); spend at those levels is Meta only.

Options: campaign, adset, ad
platformstring

Attribution only. Keep only this platform's rows. Totals still cover every conversion.

Options: meta_ads, google_ads
account_idstring

Attribution only. Keep only rows of this ad account (digits; an act_ prefix is removed).

Request Preview
Response

Response will appear here after sending the request

Authentication

header
Authorizationstring
Required

Bearer token. Agency key (ak_) or location secret key (sk_) as a bearer token. Format: Bearer ak_... or Bearer sk_.... Scoped keys (mcp_) are accepted too and need the read scope of the family the route belongs to (people, events, sessions, replays, exceptions, heatmaps or bigquery_export). See Using an mcp_ key over HTTP.

Query Parameters

location_idstring

Alternative to the X-Location-Id header for agency (ak_) keys. Ignored for secret (sk_) keys.

debugstring

1 adds the compiled SQL to meta.sql (agency keys only).

Headers

X-Location-Idstring

Location to scope the request to. Required for agency (ak_) keys on the event routes. Ignored for secret (sk_) keys, which resolve their own location, and not used by /export.

Body

application/json
kindstring
Required
Allowed values:trendfunnelpathsattribution
intervalstring

Trend only. Omit for one number per series.

Allowed values:hourdayweekmonth
seriesarray

Trend only.

breakdownobject
comparestring

Trend only.

Allowed values:previous_period
stepsarray

Funnel only. Ordered; other events may occur between steps.

windowobject

Funnel only. Default 7 days, capped at the range length.

grainstring

Funnel (default device) and paths (default person). device counts the raw distinct_id; person resolves each id to its canonical person first, so a journey across devices — or a step that is a server/CRM event keyed by a contact id — links instead of breaking. Slower (it joins the identity map for the window); trends have no grain.

Allowed values:deviceperson
filtersarray

Applied to every series / step. Not accepted on paths (use goal.filters).

goalobject

Paths: required. Persons who did this in the range; each journey is what they did in the lookback before their first goal in the range. Attribution: the conversion event (or use deals); every occurrence in the range is one conversion, credited to the touches before it.

touchpointstring

Paths only. session: one step per session, labeled by dimension. event: one step per event, pageviews labeled by pathname.

Allowed values:sessionevent
dimensionstring

Paths with session touchpoints only. Self-referral sessions (referrer on the landing page's own registrable domain) are dropped; a journey made only of them reads as Direct. campaign is case- and URL-encoding-insensitive, and numeric Meta campaign ids are replaced by their names when the client syncs Meta Ads.

Allowed values:channel_groupsource_mediumsourcecampaign
lookback_daysinteger

Paths: default 90 for session touchpoints, 7 for event touchpoints. Attribution: default 30, how far before a conversion a touch can be.

depthinteger

Paths only. Last N touchpoints kept per journey.

limitinteger

Paths: default 20, max 50, journeys returned and rows per first/last-touch list. Attribution: default 100, max 500 rows; totals still cover every row.

excludearray

Paths with event touchpoints only. Added to the default excludes ($pageleave, $engagement, $exception, $autocapture, $experiment_viewed, tag_added, tag_removed).

default_excludesboolean

Paths with event touchpoints only. false keeps the default-excluded events.

value_propertystring

Paths and attribution (with goal). Numeric property of the goal event (e.g. value, activity_value). Paths: adds goal_value, goal_first_value, and value / first_value on journey, first-touch and last-touch rows (value on linear_touch), summed per person over their goal events in the range; first_value is the first goal only. Attribution: the revenue of each conversion. Non-numeric values count as 0.

dealsobject

Attribution only, instead of goal: won CRM deals (GHL opportunities whose latest status is won). One conversion per opportunity, at the time it was first marked won, valued at its latest monetary value.

modelstring

Attribution only. last credits the last non-Direct touch (Direct only when every touch is Direct). first credits the first touch in the lookback. linear splits each conversion evenly across its touches.

Allowed values:firstlastlinear
levelstring

Attribution only. Row grain. Ad set and ad ids come from the landing URL (Meta adset_id/ad_id, Google adgroupid/creative, or Meta's utm_term/utm_content id template); spend at those levels is Meta only.

Allowed values:campaignadsetad
platformstring

Attribution only. Keep only this platform's rows. Totals still cover every conversion.

Allowed values:meta_adsgoogle_ads
account_idstring

Attribution only. Keep only rows of this ad account (digits; an act_ prefix is removed).

Responses

successboolean
dataobject

Trend: buckets[] (ISO, UTC), previous_buckets[] with compare, breakdown_values[] with breakdown, and series[] — one entry per spec series × breakdown value with label, math, event, breakdown_value?, data[] + total (or value without interval) and previous[] / previous_value with compare. Funnel: steps[] and breakdown[] { value, steps[] }. Paths: goal_persons, no_touchpoint, sampled, paths[] { touchpoints[], truncated, persons, share, avg_touchpoints, median_days, avg_days }, median_days, avg_days, at_lookback, linear_touch[] { touchpoint, persons, credit, share }, value fields with value_property, first_touch[] and last_touch[] { touchpoint, persons, share }; meta also echoes goal, touchpoint, dimension/exclude, lookback_days, depth, limit, goal_id_cap, and campaign_names { ids, named, status } when campaign touchpoints were Meta ids. Attribution: totals { conversions, revenue, spend, roas, cpa, ad_conversions, ad_revenue, unmatched_ad_conversions, no_touchpoint, over_cap, mixed_currency } over every row, filtered { rows, conversions, revenue, spend, roas, cpa, mixed_currency } after platform/account_id, sampled (rows cover a sample of converters, so row cpa/roas are null; over_cap counts the rest), and rows[] { type (ad | channel), platform, channel, account_id, campaign_id, campaign_name, adset_id?, adset_name?, ad_id?, ad_name?, currency, spend, impressions, clicks, conversions, revenue, persons, cpa, roas, median_days } (null fields omitted in the example: an ad row has channel: null, a channel row has null platform, ids, names, currency, cpa and roas); meta echoes goal/deals, model, level, lookback_days, limit, platform?, account_id?, value_property?, goal_id_cap. Always meta { from, to, interval?, previous?, window_seconds?, sql_ms, rows_read, bytes_read, cached, sql? }.