Skip to content

Limits & Pricing

This table is a derived view of the canonical product kernel in packages/shared/src/lib/product-kernel.ts.

FreeStarterProEnterprise
Monthly price€0€7 excl. VAT€24 excl. VATQuote
Included sites31050Custom
Included events / month25,000100,0001,000,000Custom
Included users1310Custom
Public retention target60 days13 months24 monthsCustom
Additional eventsNo€2 / million€2 / millionCustom
Additional usersNo€3 / user / month€3 / user / monthCustom
Automatic public overage on site countNoNoNoNo

These limits correspond to the public workspace packaging used by pricing, upgrade prompts, and dashboard consumption surfaces.

This table is also derived from the same product kernel. It stays distinct from the public workspace packaging above for route families, unit caps, and rate limits. API retention itself still follows the same canonical plan-retention grid, and remains distinct only from the site-level technical retention setting available in Settings > Sites > Collection.

FreeStarterPro
API availabilityNot includedLimitedStandard
API read retention (derived)Not included395 days730 days
Monthly included API unitsNot included100,0001,000,000
API hard cap (monthly)Not included250,0002,000,000
API rate limitNot included15 req/s30 req/s
API hourly intervalNoYesYes
Reports endpointsNoNoYes
Goals endpointsNoNoYes
Tenant endpointsNoNoYes
Tenant dimensionsNoNoYes

Starter keeps a deliberately limited API surface. Report, goal, and tenant routes stay unavailable until the active API policy enables them.

The runtime API now transports this policy explicitly:

  • GET /v1/me exposes workspace-level product policy in product
  • GET /v1/sites exposes site-level effective policy in product_configuration
  • profile-aware analytics reads expose an availability object and can return 409 when an Extended-only route family is requested outside its compatible data envelope

Compatibility mirrors such as top-level plan_id or retention_days remain derived from that canonical object, but they are now deprecated compatibility fields. New integrations should read product.runtime_plan_id and product.product_retention.api_retention_days instead. No removal will happen before 2026-07-03T00:00:00Z.

Current route classes:

  • Strict-safe: /v1/reports/content, standard /v1/metrics/timeseries, standard /v1/metrics/breakdown
  • Mixed: /v1/reports/overview, /v1/reports/acquisition, /v1/reports/actions
  • Advanced / gated: /v1/goals/conversions, tenant-scoped metrics and tenant breakdowns. These routes depend on the plan, tenant API access, and compatible configuration; do not read them as a single collection type.

For mixed routes, the response stays 200 in Strict for the strict-safe slice, uses availability.readModel to declare that baseline explicitly, and uses availability.sections to mark locked attribution or advanced sections.

Human reading rule: on Strict, the unflagged slice is the complete baseline for that route. Treat flagged sections as optional Extended detail, not as missing baseline analytics.

The same model applies in the dashboard: Audience remains useful in Strict for technical audience dimensions, while campaign-style slices stay enriched.

GET /v1/reports/content exposes two response shapes selected by include:

ModeInclusive UTC rangeResponse
summary1–365 daysTotals and one global daily pageview point; empty days are zero-filled
full1–90 daysTotals, page details, per-page trend data, entry pages, and exit pages
details (deprecated alias)1–90 daysNormalized to full; migrate new integrations to include=full

When include is omitted, ranges through 90 days use full; ranges from 91 through 365 days use summary. Comparison is limited to 30 days in either mode. limit has no effect on summary.

The summary timeseries is dense and ordered by UTC date: it contains exactly one point for every requested day, and its pageview sum equals totals.pageviews. It does not contain page paths, detailed page rows, or top-level entry and exit lists.

Detailed synchronous Content responses and CSV exports remain limited to 90 days. A longer detailed export would require a future asynchronous workflow; none is exposed by the current API.

Every successful metrics request (/v1/metrics/timeseries or /v1/metrics/breakdown) consumes units. Non-metered endpoints (/v1/me, /v1/sites, /v1/usage/*) are free.

Units are computed as:

units = base x interval x range x limit x dimension x metric
FactorValue
base2 (timeseries) or 4 (breakdown)
interval1 (day) or 3 (hour)
rangeceil(days / 30)
limitceil(limit / 100) — breakdown only
dimension2 (page) or 1 (other) — breakdown only
metric2 (pageviews, sessions) or 1 (events)

Content report metering keeps its base and duration factors in both modes. summary does not apply a limit factor; full and the deprecated details alias keep the existing limit factor. A final-cache hit is still billable.

Every report response, including a final-cache hit, is checked against a hard 5 MiB serialized proxy-response budget. Responses are never truncated. If the candidate response exceeds the budget, the API returns HTTP 422 with REPORT_RESPONSE_TOO_LARGE, including include, range_days, measured_bytes, and max_bytes in error.details. The rejected request consumes zero metered units and is not written to the final response cache.

RequestCalculationUnits
Timeseries, pageviews, 7 days, daily2 x 1 x 1 x 1 x 1 x 24
Timeseries, pageviews, 60 days, hourly2 x 3 x 2 x 1 x 1 x 224
Breakdown by referrer, sessions, 30 days, limit 1004 x 1 x 1 x 1 x 1 x 28
Breakdown by page, pageviews, 90 days, limit 5004 x 1 x 3 x 5 x 2 x 2240

When used_units > included_units, requests continue normally. The response metadata indicates the overage:

{
"meta": {
"units_charged": 4,
"billable_overage": true,
"usage": {
"used_units": 104,
"overage_units": 4,
"included_units": 100,
"hard_cap_units": 250
}
}
}

These numbers are illustrative only. The actual included and hard-cap values come from the active plan in the product kernel. Monitor the billable_overage flag to alert before reaching the hard cap.

When the hard cap is reached:

  • HTTP 402 with error code HARD_CAP_REACHED
  • No additional usage is recorded
  • Resets at the start of each billing period (1st of the month, UTC)

Per-token rate limits are enforced in 60-second sliding windows:

  • HTTP 429 with error code RATE_LIMITED
  • Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
  • Wait until X-RateLimit-Reset before retrying
  • Dashboard users can inspect workspace consumption from Settings > Consumption.
  • Site-specific detail and capture settings live in Settings > Sites > Collection.
  • GET /v1/usage/current — current billing period usage
  • GET /v1/usage/history — monthly history (up to 24 months)

These endpoints are free and available to tokens with metrics:read or usage:read scope.