API Tester Set your auth token to use "Try it" buttons

Overview

GET /api/v1/analytics/overview ?days=30 — global stats for the period
Response:
{
  "total_clicks":   4820,
  "total_installs": 347,
  "conversion_rate":"7.2%",
  "by_platform":    [{"platform":"ios", "clicks":2100}],
  "by_country":     [{"country":"FR",  "clicks":2400}],
  "top_links":      [{"slug":"summer-sale", "clicks":1200}],
  "daily":          [{"date":"2025-08-01", "clicks":120, "installs":9}]
}

Realtime

GET /api/v1/analytics/realtime Live view of the current UTC day — polled every 5s by the dashboard
Response:
{
  "now":         "2026-04-11T09:40:04.615Z",
  "today_start": "2026-04-11T00:00:00.000Z",
  "today": {
    "impressions": 18, "app_opens": 5, "deferred": 0,
    "ios": 13, "android": 4, "desktop": 1,
    "conversion_rate": "27.8%"
  },
  "hourly":    [ { "hour": 0, "impressions": 0, "app_opens": 0, "deferred": 0 } /* zero-filled to current hour */ ],
  "recent":    [ /* last 30 clicks joined with link */ ],
  "top_links": [ /* top 10 links today */ ],
  "by_country":[ /* top 10 countries today */ ]
}

The day is calculated in UTC (midnight → now). The dashboard polls this endpoint every 5 seconds when the Realtime page is active.

GET /api/v1/analytics/links/:slug ?days=30 — stats + by_country + daily + recent_clicks

Returns full analytics for a single link: totals, by-country breakdown, daily time series, and the 20 most recent clicks.

GET /api/v1/analytics/links/:slug/daily ?days=90 — time series for a single link

Lightweight endpoint for charting. Returns an array of { date, clicks, installs } objects.

Cohort Analysis

GET /api/v1/analytics/cohort ?days=30&cohort_by=day — cohort retention grid

Groups users by acquisition date and tracks their return behavior over time. Useful for measuring long-term engagement from deep link campaigns.

GET /api/v1/analytics/retention ?days=30 — day-N retention rates

Returns D1, D7, D14, D30 retention rates for users who clicked links in the period.

Query Engine

The analytics query engine lets you build arbitrary queries over clicks and events with flexible filtering, grouping, and aggregation — without any risk of SQL injection.

POST /api/v1/analytics/query Flexible query — filters + aggregations on any axes
Request body:
{
  "from": "2026-04-01T00:00:00Z",       // optional — ISO date/time
  "to":   "2026-04-11T23:59:59Z",
  "filters": {
    "platform": ["ios", "android"],    // array = IN operator
    "country":  "FR",                  // string = equality
    "campaign": "summer-sale",
    "matched":  1                    // deferred installs only
  },
  "group_by": ["date", "platform"],  // 0..N dimensions
  "metrics":  ["clicks", "installs", "conversion_rate"],
  "order_by": "clicks",
  "order":    "desc",
  "limit":    500                    // max 10000
}
Response:
{
  "query":       { /* echoed back, normalized */ },
  "sql":         "SELECT ...",         // generated SQL (debug/transparency)
  "row_count":   12,
  "duration_ms": 1,
  "rows": [
    { "date": "2026-04-11", "platform": "ios",     "clicks": 1024, "installs": 130, "conversion_rate": 0.127 },
    { "date": "2026-04-11", "platform": "android", "clicks":  856, "installs":  98, "conversion_rate": 0.1145 }
  ]
}
GET /api/v1/analytics/query GET version — for shareable URLs
/api/v1/analytics/query?from=2026-04-01&platform=ios,android&group_by=country,date&metrics=clicks,installs

Dimensions can be passed as query parameters (comma-separated for IN). Equivalent to the POST version, same validation.

GET /api/v1/analytics/query/schema Available dimensions, metrics, and distinct values (for UI dropdowns)
{
  "dimensions": ["platform", "country", "matched", "slug", "title",
                  "campaign", "source", "medium", "date", "hour", "dow"],
  "metrics":    ["clicks", "installs", "conversion_rate",
                  "unique_countries", "unique_links", "unique_ips"],
  "values": {
    "platform": ["ios", "android", "desktop"],
    "country":  ["FR", "US", "DE" /* ... */]
  }
}

Used by the Explorer page in the dashboard to populate filter dropdowns.

🛡️
SQL injection safe — all dimensions and metrics are whitelisted. An attempt to inject via order_by or group_by returns 400 Bad Request.

Conversion Funnel

GET /api/v1/funnel ?days=30&link_slug=abc — conversion pipeline
Response:
{
  "steps": [
    { "name": "Impressions",    "count": 10000, "rate": 1.0,   "revenue": null },
    { "name": "App Opens",      "count":  4200, "rate": 0.42,  "revenue": null },
    { "name": "Deferred Installs","count":   347, "rate": 0.035, "revenue": null },
    { "name": "Purchases",       "count":   128, "rate": 0.369, "revenue": 3840.00 }
  ]
}

Steps are ordered: Impressions → App Opens → Deferred → custom events (sorted by count). Revenue is non-null only for events with revenue field.

Attribution

GET /api/v1/attribution/:slug Attribution details for a specific link

Returns click → install attribution chain for a link: matched clicks, time-to-install distribution, and attributed events.