Skip to content
Documentation
Stats API

Build with the Stats API

Read pageview, visitor, and session counts plus traffic, signup, and revenue reports from your own backend.

Create a read-only key

Open Profile, select your website, then create a key under Stats API keys. Save the one-time secret in your server environment as TALVESS_STATS_KEY. Each website supports five active Stats API keys.

Send Authorization: Bearer <stats-key> over HTTPS on every request. The key grants read access to aggregate traffic, counts, signup, and revenue reports for its website. Event API keys send data; MCP keys connect AI apps. They cannot authenticate to the Stats API.

Call Talvess from your backend and choose which results to display. Never put the key in browser code, a public environment variable, a URL, or an AI chat. Cross-origin browser requests are not supported. Revoke a key in Profile to stop access, including access to cached reports.

Available reports

GET endpointReport data
/api/v1/stats/countsRead pageview, visitor, session, bounced-session, and continued-session totals for a selected period or lifetime.
/api/v1/stats/pageviewsRead recorded pageview totals for a selected time period or lifetime.
/api/v1/stats/visitorsRead distinct anonymous visitor totals across a selected time period or lifetime.
/api/v1/stats/sessionsRead distinct sessions with recorded pageviews in a selected time period or lifetime.
/api/v1/stats/trafficRead traffic totals, time series, and reports for pages, referrers, campaigns, devices, or countries.
/api/v1/stats/signupsRead confirmed signup totals, time series, the signup funnel, and source reports for your website.
/api/v1/stats/revenueRead payments, refunds, paying customers, and source reports in one selected currency.

Reports use Talvess's existing reporting definitions and contain aggregates only. They do not return visitor journeys, customer or transaction records, raw event metadata, or imported provider history. Only detected referrer hosts establish AI referrals; campaign tags and Direct / unknown traffic do not establish measured AI attribution.

Use Get counts for compact totals: pageviews, distinct anonymous visitors, distinct sessions, sessions with one pageview, and sessions with multiple pageviews. The individual pageview, visitor, and session endpoints return a single count. Each includes the previous period of equal duration when a date range is selected. Add period=lifetime for all retained native history. These use the same definitions as the traffic summary and dashboard. A recorded pageview without identifiers still counts as a pageview. Visitors deduplicate across the entire period; do not sum daily visitor totals to calculate unique visitors for a longer range.

Signup and payment reports count events within the selected period; they are not a shared signup cohort. Do not divide their totals to infer signup-to-paying conversion. Use data.signups from the signup report for confirmed signup counts. The revenue report includes data.summary.payments and data.summary.payingCustomers for one selected currency.

Choose your report options

  • Count endpoint period: lifetime counts all retained native traffic before the report calculation time, with no 365-day limit. Use it on counts, pageviews, visitors, or sessions. Omit days, startDate, endDate, and interval when using lifetime.
  • days: 1, 7, 30 or 90. Defaults to 30. The 1-day preset is a rolling 24 hours; longer presets use UTC calendar days including today.
  • startDate and endDate: inclusive UTC dates in YYYY-MM-DD format, covering up to 365 days through today. Supply both, and omit days.
  • interval: hourly or daily. Defaults to hourly for days=1, otherwise daily. Hourly ranges cover at most seven days. Count endpoints return period totals without a time series; interval does not change those totals.
  • Traffic section: summary (default), pages, referrers, campaigns, devices, or countries.
  • Revenue currency: a supported uppercase ISO currency code, such as USD. Required when the website has multiple currencies; otherwise the available currency is selected.

Unknown, repeated, unsupported, or conflicting parameters return 400. Do not supply a website ID: the key selects the website. Additional filtering and pagination are not available in v1.

Every report includes period with UTC start,endExclusive, seriesEnd, asOf, timezone and interval. Traffic summaries contain summary,previous and series. Dimension reports containmetric, limit and rows. Pages count pageviews; other traffic dimensions count session entries in the period.

Ranges include timestamps at period.start and exclude timestamps at period.endExclusive. For example, startDate=2026-10-01&endDate=2026-10-07 includes October 1 through October 7 in UTC, ending just before midnight on October 8. Count comparisons use the immediately preceding range of equal duration. Empty periods return zero counts.

Lifetime counts return period.range: "lifetime". The start is the first recorded native pageview timestamp, or null for an empty website. The end and calculation time match; period.interval and previous are null. Use the same bearer header, cache timestamps, and error handling as date-based counts. For example, call /api/v1/stats/counts?period=lifetime or /api/v1/stats/visitors?period=lifetime.

Revenue amounts are exact integer strings in minor units. UseminorUnitDigits to display major units. For example,grossMinor: "12345" with two minor-unit digits represents 123.45. Never combine currencies or convert large integer strings to JavaScript Number for accounting calculations.

Freshness and limits

Successful results use { data, meta: { generatedAt, expiresAt } }. Matching report options share a server-side cache for 900 seconds. The next request after expiry calculates a fresh report. Check the ISO UTC timestamps in meta before displaying an updated-at label.

This is a refresh interval. Newly calculated reports can include current activity; Talvess does not intentionally withhold the most recent 15 minutes. HTTP responses use Cache-Control: no-store, and every request checks authentication, revocation and rate limits.

Each key allows 60 requests per minute, including cache hits and invalid queries submitted with an active key. Responses are limited to 256 KiB. Empty reports return 200 with zero totals or empty rows; an unavailable database or failed calculation returns an error.

Errors and retries

Failures use { error: { code: "INVALID_QUERY", message: "..." } }.

Status / codeAction
400 INVALID_QUERYCorrect parameters, dates or currency selection.
401 UNAUTHORIZEDSupply an active Stats API key. Revoked keys cannot be reused.
403 ORIGIN_NOT_ALLOWEDMake the request from your backend.
405 METHOD_NOT_ALLOWEDUse GET. HEAD and other methods are not supported.
413 REPORT_TOO_LARGERequest a shorter date range.
429 RATE_LIMITEDWait for Retry-After seconds (60), then retry.
500 INTERNAL_ERRORRetry with bounded exponential backoff; contact support if it persists.

Fetch data from your server

request.sh
curl 'https://talvess.vercel.app/api/v1/stats/traffic?days=7&section=pages' \
  -H "Authorization: Bearer $TALVESS_STATS_KEY"
stats.js
// Run on your server. Keep the key out of browser bundles.
const key = process.env.TALVESS_STATS_KEY
if (!key) throw new Error("TALVESS_STATS_KEY is missing")

const response = await fetch(
  "https://talvess.vercel.app/api/v1/stats/counts?days=7",
  {
    headers: { Authorization: "Bearer " + key },
    cache: "no-store",
  }
)

if (!response.ok) {
  if (response.status === 429) {
    const retryAfter = Number(response.headers.get("Retry-After") || 60)
    throw new Error("Rate limited. Retry after " + retryAfter + " seconds.")
  }
  throw new Error("Talvess request failed: " + response.status)
}

const { data, meta } = await response.json()
const { pageviews, visitors, sessions } = data.counts
// Render these counts and meta.generatedAt in your own UI.
// Only send the report fields you intend to display to your browser.

Use the same bearer header for /api/v1/stats/pageviews?days=7, /api/v1/stats/visitors?days=7, /api/v1/stats/sessions?days=7, /api/v1/stats/signups?days=7or /api/v1/stats/revenue?days=30&currency=USD. v1 keeps existing response fields and parameter meanings backward compatible.