API reference

Analytics queries

The Query API lets you fetch analytics data for your websites with flexible date ranges, filters, and aggregations.

For a complete task using a scoped key, a selected website and checked query results, follow the REST reporting walkthrough. It includes a runnable script and explains empty responses, timezones and partial failures.

Endpoints

MethodEndpointDescription
GET/v1/query/websitesList accessible websites
GET/v1/query/typesGet available query types
POST/v1/query/compileValidate and compile a query without executing it
POST/v1/queryExecute analytics query

Public website access

When a website owner enables public sharing, anonymous viewers can request only the unfiltered aggregate overview. The /v1/query/types response marks these query types with publicAccess: true. Date ranges and the overview's fixed breakdowns remain available.

Custom events, arbitrary event properties, error diagnostics, audience details, web vitals, profiles, and revenue require authenticated website permission. Filters also require website permission, including trait, visitor identifier, and ordinary dimension filters. A batch containing a private query or any filter is rejected before execution unless the caller has website permission. The same policy applies to /v1/query/compile.

Public overview counts can include small groups, and page, referrer, or campaign labels can contain information supplied by your application. Public sharing does not apply a minimum group size or guarantee statistical anonymity. Review these labels and your traffic before publishing an overview, and keep sharing disabled when the overview itself could reveal personal information.

List websites

Get all websites you have access to:

http
GET /v1/query/websites

Response:

json
{
"success": true,
"websites": [
  {
    "id": "web_123",
    "name": "My Website",
    "domain": "example.com",
    "isPublic": false,
    "createdAt": "2024-01-01T00:00:00.000Z"
  }
],
"total": 1
}

Get query types

Discover available query types and their configurations. This endpoint is public and doesn't require authentication.

http
GET /v1/query/types?include_meta=true

Set include_meta=true to get descriptions, output fields, and visualization hints.

Response:

json
{
"success": true,
"types": ["summary_metrics", "top_pages", "traffic_sources", "browser_name", "..."],
"configs": {
  "summary_metrics": {
    "allowedFilters": ["country", "device_type", "browser_name"],
    "customizable": true,
    "defaultLimit": 100,
    "meta": {
      "description": "Overall website metrics and KPIs",
      "output_fields": [
        { "name": "pageviews", "type": "number" },
        { "name": "unique_visitors", "type": "number" },
        { "name": "sessions", "type": "number" }
      ]
    }
  }
}
}

Execute query

Query analytics data with full parameter control:

http
POST /v1/query?website_id={id}

Query parameters:

ParameterRequiredDescription
website_idYes*Website to query
link_idYes*Link shortener ID (for link analytics)
schedule_idYes*Uptime monitor ID (for uptime analytics)
organization_idYes*Organization ID for organization-scoped query types
timezoneNoTimezone for date calculations (default: UTC)

*One of website_id, link_id, schedule_id, or organization_id is required unless the signed-in session or global API key supplies an organization context.

Request body:

json
{
"parameters": ["summary_metrics", "top_pages", "browser_name"],
"startDate": "2024-01-01",
"endDate": "2024-01-31",
"limit": 100,
"page": 1,
"filters": [
  {
    "field": "country",
    "op": "in",
    "value": ["US", "CA"]
  }
],
"granularity": "daily"
}

Request body fields:

FieldTypeRequiredDescription
parametersarrayYesQuery types to execute
startDatestringConditionalStart date (YYYY-MM-DD). Required if no preset
endDatestringConditionalEnd date (YYYY-MM-DD). Required if no preset
presetstringConditionalDate preset instead of explicit dates
idstringNoQuery identifier returned in response
limitnumberNoMax results per parameter (default: 100, max: 10000)
pagenumberNoPage number for pagination (default: 1)
filtersarrayNoFilter conditions
granularitystringNo"hourly" or "daily", aliases "hour" and "day" (default: daily). Can also be set per parameter
sortBystringNoField to sort results by
sortOrderstringNo"asc" or "desc"
timeZonestringNoTimezone for date calculations

Error tracking starts on the Hobby plan. On the free plan, every query type in the Errors category returns 402 with code FEATURE_UNAVAILABLE, for website and organization queries alike. GET /v1/query/types?include_meta=true lists each type's category.

Date presets

Instead of specifying startDate and endDate, use a preset for common date ranges:

PresetDescription
todayCurrent day
yesterdayPrevious day
last_7dLast 7 days including today
last_14dLast 14 days including today
last_3_weeksLast 21 days including today
last_30dLast 30 days including today
last_60dLast 60 days including today
last_90dLast 90 days including today
this_weekCurrent week (Sunday to today)
last_weekPrevious full week
this_monthCurrent month to date
last_monthPrevious full month
this_yearCurrent year to date

Example with preset:

json
{
"parameters": ["summary_metrics", "top_pages"],
"preset": "last_30d",
"limit": 10
}

Parameters with custom date ranges

Each parameter can have its own date range:

json
{
"parameters": [
  "summary_metrics",
  {
    "name": "top_pages",
    "start_date": "2024-01-01",
    "end_date": "2024-01-15",
    "id": "pages-first-half"
  }
],
"startDate": "2024-01-01",
"endDate": "2024-01-31"
}

Response format

json
{
"success": true,
"queryId": "my-query-123",
"data": [
  {
    "parameter": "summary_metrics",
    "success": true,
    "data": [
      {
        "date": "2024-01-01",
        "pageviews": 1250,
        "unique_visitors": 890,
        "sessions": 1100
      }
    ]
  },
  {
    "parameter": "top_pages",
    "success": true,
    "data": [
      {
        "name": "/",
        "pageviews": 450,
        "visitors": 320
      }
    ]
  }
],
"meta": {
  "parameters": ["summary_metrics", "top_pages"],
  "total_parameters": 2,
  "page": 1,
  "limit": 100,
  "filters_applied": 2
}
}

The top-level success: true means the request was valid. Check each parameter's success field to confirm individual query results.

Batch queries

Execute multiple queries in a single request by sending an array:

json
[
{
  "id": "query-1",
  "parameters": ["summary_metrics", "top_pages"],
  "startDate": "2024-01-01",
  "endDate": "2024-01-31",
  "limit": 100
},
{
  "id": "query-2", 
  "parameters": ["browser_name", "os_name"],
  "startDate": "2024-01-01",
  "endDate": "2024-01-31",
  "limit": 50
}
]

Batch response:

json
{
"success": true,
"batch": true,
"results": [
  {
    "queryId": "query-1",
    "data": [...],
    "meta": {...}
  },
  {
    "queryId": "query-2",
    "data": [...],
    "meta": {...}
  }
]
}

Filter operations

OperatorDescriptionExample value
eqEquals"US"
neNot equals"bot"
containsContains substring"chrome"
not_containsDoes not contain"preview"
starts_withStarts with prefix"/blog"
inValue in array["US", "CA", "UK"]
not_inValue not in array["bot", "crawler"]

Common filter fields

FieldAvailable onExample
countryMost queries{"field": "country", "op": "eq", "value": "US"}
device_typeMost queries{"field": "device_type", "op": "in", "value": ["mobile", "tablet"]}
browser_nameMost queries{"field": "browser_name", "op": "eq", "value": "Chrome"}
os_nameMost queries{"field": "os_name", "op": "eq", "value": "iOS"}
pathpage and session queries{"field": "path", "op": "starts_with", "value": "/blog"}
referrertraffic queries{"field": "referrer", "op": "contains", "value": "google"}

Use GET /v1/query/types?include_meta=true to see which filters are allowed for each query type.

Granularity

Control time-based aggregation:

  • "daily": group by day (default)
  • "hourly": group by hour (max 30 day range)
json
{
"parameters": ["summary_metrics"],
"startDate": "2024-01-01",
"endDate": "2024-01-07",
"granularity": "hourly"
}

Pagination

Use page and limit for large result sets:

json
{
"parameters": ["top_pages"],
"startDate": "2024-01-01",
"endDate": "2024-01-31",
"limit": 50,
"page": 2
}

Page numbering starts at 1.

Continue with this workflow

For questions about step completion, review the conversion funnel measurement guide before comparing counts. If you want an assistant to help investigate the results, see the AI-assisted analytics comparison.

How is this guide?