Account

Read API

Query your numbers from scripts and tools with read-only API keys.

The read API gives scripts, spreadsheets, notebooks and internal tools read-only access to a project's numbers: the same overview and insights you see in the dashboard. JSON in, JSON out.

Max plan

Read API keys are part of Max. See Plans and usage or the pricing.

API keys

Owners and admins create keys in the project's Keys & API page, under API keys (read-only). Give each key a name that says what uses it.

  • Keys start with vxr_.
  • A key reads one project only, and can't change anything.
  • A key is shown once, right after you create it. Copy it then: it can't be shown again. The list only shows its first characters, who created it and when it was last used.
  • You can revoke a key at any time. Requests with a revoked key get a 401.

Heads up

Unlike write keys, API keys read your data. Keep them secret: don't put them in a website or a game build.

Making requests

Send the key as a bearer token. Your project id is in the dashboard's address bar, right after /projects/.

terminalsh
curl -H "Authorization: Bearer vxr_YOUR_API_KEY" \
  "https://api.anyanalytics.org/api/v1/projects/<projectId>/overview?range=30d"

Endpoints

All paths are relative to /api/v1/projects/:projectId.

RequestReturns
GET /The project: id, name, kind, timezone and domain.
GET /overviewThe project overview, with the query in the URL.
POST /overviewThe same, with the query as a JSON body.
POST /queryRuns any trends, funnel, retention or paths query.
GET /insightsSaved insights: id, name, description, query and when it was last updated.
GET /insights/:insightIdA saved insight and its current result, as { insight, result }.

Overview

The overview takes these parameters, in the query string or the JSON body:

ParameterValues
rangetoday, 24h, 7d (default), 30d, 90d, 12m or custom
from, toWith custom: the first and last day, inclusive, as YYYY-MM-DD, up to two years apart
intervalhour, day, week or month. Defaults to the range's natural one.
comparetrue adds the previous period's series
filtersA JSON array like [{"dim":"country","value":"FR"}]. A dimension is any breakdown (page, channel, referrer, country, browser, platform, event…) or goal with a goal id. Up to 10.
terminalsh
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"range":"custom","from":"2026-09-01","to":"2026-09-30","filters":[{"dim":"channel","value":"Organic Search"}]}' \
  "https://api.anyanalytics.org/api/v1/projects/<projectId>/overview"

The response has the headline totals and the previous period's, the chart series and their buckets, the breakdowns for every dimension, your goals and the revenue currency. Times are wall-clock in the project's timezone. The numbers are defined in The dashboard.

Insight queries

POST /query takes { "query": { ... } } with the same query a saved insight holds. The easiest way to write one is to build it in the dashboard, save it, and read its query from GET /insights. A query without a kind is a trend; funnels, retention and paths set "kind" to "funnel", "retention" or "paths".

trend.shsh
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"query":{"series":[{"event":"$pageview","metric":"unique_users"}],"dateRange":{"from":"-30d"},"interval":"day"}}' \
  "https://api.anyanalytics.org/api/v1/projects/<projectId>/query"
funnel.shsh
curl -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"query":{"kind":"funnel","steps":[{"kind":"page","value":"/pricing"},{"value":"signup_completed"}],"dateRange":{"from":"-30d"}}}' \
  "https://api.anyanalytics.org/api/v1/projects/<projectId>/query"

Date ranges are relative ("-24h", "-30d") or a YYYY-MM-DD day, read in the project's timezone, and can cover up to two years.

Limits and caching

  • Each key can make 300 requests per minute.
  • Each key can have 8 requests in flight at once.
  • Results are cached for a minute, so asking more often than that returns the same numbers.
  • Browsers can call the API directly (CORS is open), since the key travels in a header.

Errors

Errors come back as JSON with an error field. When a response has a Retry-After header, wait that many seconds before trying again.

StatuserrorMeaning
400validation_failedThe query is invalid; details says why.
400invalid_rangeThe range is too long, or too many buckets for the interval.
401invalid_api_keyThe key is missing, unknown or revoked.
402plan_required or a messageThe organization's plan doesn't include the read API, or its trial has ended.
404Project not foundThe key belongs to another project. Unknown insights also answer 404.
429rate_limitedOver 300 requests in a minute.
429 / 503too_many_concurrent_queriesToo many queries running at once. Retry shortly.