---
title: "Answer an analytics question"
method: GET
path: "/analytics"
tags: ["Analytics"]
---

# Answer an analytics question

`GET /analytics`

## Request

- Base URL: `https://api.warplink.app/v1`
- URL: `https://api.warplink.app/v1/analytics`
- Auth: HTTP bearer

Reads one of seven analytics surfaces through the same authorized query service the dashboard and the MCP query_analytics tool use: overview, one link's detail, a breakdown of one dimension (explore), a comparison of 2-5 links (change), and the analytics page's own signals, summary (KPIs, headline sentence, top movers, spike flag), trend (the chart series by hour, day or week with the previous period aligned bucket by bucket) and leaderboard (links by change, new links, active links with no taps). Requires an API key with the analytics:read or links:read scope. SDK keys are refused. Retention, the Free plan's 30-day look-back and the Free click-limit freeze apply exactly as on the dashboard. A Free range, or a comparison whose earlier period, that starts before the last 30 days is refused with 403 LOOKBACK_EXCEEDED, and details.earliest_allowed carries the first instant a Free organization may read. A Free organization at its 10,000-click limit still reads: figures stop at the moment the limit was reached, receipt.paused is { reached_at, limit }, window_effective.until is one millisecond after that moment (or at it, when another click shares that millisecond, and then the clicks in that millisecond are left out), and a warning says so. Clicks keep being stored, and a new billing period reads live again. Reports accepted_taps, unique_clicks, installs (observed_attributed_installs, or linked_installs when a filter or own_links scope narrows the view) and, on summary and trend, tap_to_install_rate and app_open_share as numerator and denominator. Days, weeks and hours are labeled in the organization's reporting time zone unless timezone is sent. metrics optionally narrows the response to a subset of a surface's own metrics. app_id filters every surface to links of one app in the org. On the overview surface the rows also carry the top countries, referrers and devices, idle links, recent clicks and the previous-period comparison row, and attempt_match_rate is reported with an additive tap_found object ({ numerator, denominator, display, status }): the match rate among new installs where a tap was found, with status healthy (80% or more), needs_attention (50% to under 80%), low (under 50%), or not_enough_installs (fewer than 50 such installs); on the link surface the tap-source split; on change the per-compared-link breakdowns. A parameter not applicable to the chosen surface, and any unrecognized query parameter, is a 400 VALIDATION_ERROR. A parameter other than filter sent more than once is also a 400 VALIDATION_ERROR, and so is org: the API key's own organization is always the one queried. On the leaderboard surface, insight.silent_through and insight.silent_state say whether silence can be claimed for the silent tab. A sparkline point that cannot be computed, such as a rate with no denominator, is null.

## Query parameters

- `surface` 'overview' | 'link' | 'explore' | 'change' | 'summary' | 'trend' | 'leaderboard', required
- `window_preset` 'last_7_days' | 'last_30_days' | 'this_month' | 'previous_month'
- `from` string, date-time
- `to` string, date-time
- `timezone` string
- `link_id` string, uuid
- `link_ids` string
- `dimension` 'country' | 'device' | 'os' | 'browser' | 'referrer' | 'utm_source' | 'source' | 'app'
- `dimensions` 'country' | 'device' | 'os' | 'browser' | 'referrer' | 'utm_source' | 'source' | 'app'
- `metrics` string
- `filter` string[]
- `app_id` union
  - string, uuid
  - 'none'
- `compare` 'previous' | 'none' | 'true' | 'false'
- `granularity` 'hour' | 'day' | 'week'
- `metric` 'taps' | 'unique' | 'installs' | 'install_rate' | 'app_share'
- `tab` 'movers' | 'new' | 'silent'
- `search` string
- `row_series` boolean
- `cursor` string
- `limit` integer

## Response `200`

The query result: schema_version, the query receipt, totals/units, rows, and next_cursor

- object

## Other responses

- `400`: Invalid request (unknown surface, missing window, a filter or granularity the surface can't honor)
- `401`: Unauthorized
- `403`: Forbidden (including a link outside a member's own_links scope) or missing scope. A Free organization that asks for a range, or a comparison, starting before its last 30 days gets LOOKBACK_EXCEEDED, with details.subject (range or comparison), details.lookback_days and details.earliest_allowed
- `404`: Not found (a link outside the org, or a nonexistent link/org)

---

[API](https://skmtc.dev/warplink/apis/warplink-api.md) · [All operations](https://skmtc.dev/warplink/apis/warplink-api/llms.txt) · [OpenAPI document](https://skmtc.dev/warplink/apis/warplink-api/revisions/2a90ae8c44e8?raw)
