API reference

Build a REST analytics report

Use the Query API to read last week's summary and top pages for one website. This walkthrough keeps your API key on the server, selects the destination explicitly, and checks each query result before producing a report.

Reading analytics does not install a tracker or send events. First verify that the website already has the data you expect using the installation guide.

1. Create a read-only key

Create a key in Organization settings → API keys with read:data access to the website you want to report on. Use website-specific access when the integration only needs one site. You do not need track:events for this reporting task.

Store the key in your server or local environment as DATABUDDY_API_KEY. A browser's public Client ID is not an API key. Do not put the key in NEXT_PUBLIC_ variables, client components, a shared notebook, or a committed example file. See authentication and scopes.

2. Find the website ID

List websites accessible to the key:

curl --fail --silent --show-error \
  -H "x-api-key: $DATABUDDY_API_KEY" \
  https://api.databuddy.cc/v1/query/websites

The response has success, a websites array and total. Match the intended site by its name, domain and organization, then copy its returned id into DATABUDDY_WEBSITE_ID. Do not silently pick the first site: keys can have access to several websites.

An empty list does not mean the organization has no traffic. Check the key's organization, website access and read permission. If the request is rejected, fix authentication before querying reports.

3. Discover the current query contract

Query-type discovery is public:

curl --fail --silent --show-error \
  'https://api.databuddy.cc/v1/query/types?include_meta=true'

Check that summary_metrics and top_pages are present. Each entry under configs describes supported filters and optional metadata, including meta.output_fields. Use these fields to interpret the response rather than assuming every query returns the same metric names.

For these queries, the summary exposes unique_visitors, while top pages exposes name for the path and visitors for its visitor count. Top-page visitor counts overlap when someone visits several pages, so summing those rows does not produce the site's unique-visitor total.

4. Query a complete calendar week

Set DATABUDDY_TIMEZONE to the timezone you use when reviewing the website, such as UTC or Europe/Berlin. It does not automatically inherit the dashboard's selected timezone.

This request uses last_week: the previous Sunday through Saturday in the requested timezone. It avoids comparing a partial current day with a completed week. The overview and pages IDs let your code match returned results even if their order changes.

curl --fail --silent --show-error \
  -X POST \
  -H "x-api-key: $DATABUDDY_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "parameters": [
      { "name": "summary_metrics", "id": "overview" },
      { "name": "top_pages", "id": "pages" }
    ],
    "preset": "last_week",
    "limit": 10,
    "page": 1
  }' \
  "https://api.databuddy.cc/v1/query?website_id=$DATABUDDY_WEBSITE_ID&timezone=$DATABUDDY_TIMEZONE"

limit: 10 returns a top-page shortlist, not a complete export. For a complete page inventory, use the query reference's pagination controls and verify how many rows you actually fetched. If you need a fixed historical period, use startDate and endDate instead of preset and retain those dates with the report.

5. Run the checked JavaScript example

Download query-analytics.mjs. It uses built-in fetch, needs no dependencies, and runs with Bun or Node.js 22+. With your key, website ID and timezone already in the environment:

bun query-analytics.mjs
# Or: node query-analytics.mjs

The script requests the same two reports and prints JSON only after both succeed. It validates the timezone before making a request, uses a 20-second timeout, checks HTTP status and the response envelope, and requires one successful result for each requested ID. Missing, duplicated or failed results cause a nonzero exit instead of a misleading complete report.

The example intentionally stops on errors rather than retrying automatically. An automated scheduler should preserve failure details and apply bounded retries appropriate to the error. For 429, respect the server's cooldown or Retry-After guidance and add backoff; do not spin in a tight loop. See rate limits.

Interpret success, failure and empty data

HTTP success and a top-level success: true do not prove every query succeeded. For a single request, inspect each item in data:

{
  "success": true,
  "data": [
    { "parameter": "overview", "success": true, "data": [] },
    { "parameter": "pages", "success": false, "data": [], "error": "..." }
  ]
}

This synthetic example is incomplete: the pages query failed. Do not label its empty array as zero pageviews. The downloadable script rejects the report.

A successful result with an empty array is different. The script preserves it with empty: true; it does not invent zero-valued metrics. Depending on the query, an empty period can also return a row containing zero counts. Inspect the returned fields and compare the intended website, dates and timezone before interpreting either case.

For an unexpectedly empty result, check that collection was enabled during that period, the website ID is correct, and any filters match data that exists. Remove optional filters one at a time. An empty response alone does not diagnose a tracking failure.

Verify before scheduling

Run the report against a separate test website with a known small journey. Compare the same period and timezone in the dashboard, then check both results independently. Reconcile differences in limits, filters and metric definitions rather than summing per-page visitors or treating a request counter as a traffic total.

If you add parameters, discover their supported filters first. A filter accepted by one query can fail another query in the same request. For a batch of requests, inspect each object in results and then its nested parameter results; the downloadable example intentionally handles a single request only.

Authentication or authorization errors need a valid key and resource access. A 402 FEATURE_UNAVAILABLE response requires reviewing the requested feature and plan, not adding broader scopes. Invalid parameters need a corrected request. See API error handling and keep request IDs with your operational logs when the API supplies them.

Continue with the reference

How is this guide?