Files
umami/docs/report-api-migration.md
T

6.6 KiB

Report API migration

The website analytics APIs replace report execution endpoints. Analytics use GET; saved funnels and goals have dedicated resource routes. The application and MCP use the new routes. The report table and existing definition IDs are retained. No database migration is required.

Calculation endpoints

Paths in the replacement column are relative to /api/websites/{websiteId}.

Legacy POST endpoint Replacement GET endpoint(s)
/api/reports/attribution /attribution
/api/reports/breakdown /breakdown
/api/reports/funnel /funnels/stats or /funnels/{funnelId}/stats
/api/reports/goal /goals/stats or /goals/{goalId}/stats
/api/reports/heatmap /heatmaps
/api/reports/journey /journeys
/api/reports/performance /performance/stats, /performance/chart, /performance/metrics
/api/reports/retention /retention
/api/reports/revenue Existing /revenue/stats, /revenue/chart, /revenue/metrics
/api/reports/utm /utm/metrics

New requests use startAt and endAt in epoch milliseconds, with optional timezone, unit, and existing filter parameters. Dates are normalized through the shared website filter pipeline, including reset dates and account history limits. The report envelope and discriminator are gone. Use a single date range; do not send separate filter dates and calculation dates.

steps on funnel previews and fields on breakdowns are JSON strings, URL-encoded normally. Other criteria are individual query parameters. For example:

await client.getWebsiteFunnelStats({
  websiteId,
  startAt,
  endAt,
  timezone: 'UTC',
  window: 60,
  steps: JSON.stringify([
    { type: 'path', value: '/pricing' },
    { type: 'event', value: 'signup' },
  ]),
});

The calculation criteria remain feature-specific: journeys accept steps, startStep, endStep, and eventType; attribution accepts model, type, and step; goal previews accept type and value; heatmaps accept urlPath and mode. See /openapi.json for contracts.

Performance stats return the old summary object directly. Performance chart returns { chart }. Performance metrics return a single dimension array; type is path, title, device, or browser. Chart and metrics accept metric (lcp, inp, cls, fcp, ttfb). Stats calculate all metrics independently of the chart selection. The same percentile SQL is used by legacy and new handlers.

UTM metrics return { utm, views }[] for one type: utm_source, utm_medium, utm_campaign, utm_term, or utm_content. The existing pageview counting rules, empty-value exclusion, and 50-row limit are preserved. UTM board widgets request only their configured dimension.

Revenue endpoints retain their existing contracts. MCP get_revenue composes stats, chart, and four dimension requests, preserving its previous output and comparison data.

Saved definitions

Method Path (relative to website) Purpose
GET /funnels List definitions, with pagination/search
POST /funnels Create { name, description?, parameters }
GET /funnels/{funnelId} Read definition
POST /funnels/{funnelId} Update { name, description?, parameters }
DELETE /funnels/{funnelId} Delete definition
GET /funnels/{funnelId}/stats Calculate saved criteria with supplied dates/filters
GET /funnels/stats Calculate supplied criteria without saving

Goals expose the same structure under /goals. Website and definition type are fixed by the route and cannot be changed in an update body. IDs, names, descriptions, and board reportId references are preserved. Saved stats validate stored criteria and require both definition access and analytics-section access. Unsupported or malformed legacy criteria return 400 for stats; the definition remains readable/editable through the compatibility API.

Section-based sharing is preserved. Heatmaps remain authenticated-only. New definition lists support type-specific section sharing and exclude deleted websites. Legacy report list routes retain their original, differing authentication behavior during the transition.

Compatibility routing and removal gate

All legacy calculation and saved-report routes remain callable with their existing contracts. Next.js rewrites the old URLs to handlers under src/app/(compat)/compat/api without changing request methods, bodies, query parameters, or response shapes. These handlers live outside src/app/api, so contract discovery, OpenAPI, and the generated SDK expose only the new feature APIs. Existing clients can continue calling the old URLs; new SDK versions use the replacements above. HTTP redirects to the feature APIs would not preserve compatibility because the methods, request envelopes, and some response shapes differ. Legacy handlers and new feature routes call the same SQL functions; no internal HTTP forwarding is involved. Legacy calculation envelopes and date precedence remain unchanged.

Do not remove generic report CRUD solely because the current UI only saves funnels and goals. Before scheduling removal:

  1. Audit persisted report counts by type, including older definitions outside funnel/goal.
  2. Audit malformed funnel/goal criteria that stricter feature APIs cannot calculate.
  3. Decide how users can export, edit, migrate, or retain every other saved type.
  4. Confirm external API clients have replacements for their operations and payloads.
  5. Announce a compatibility window and the breaking release that will remove legacy routes.
  6. Verify the application, boards, SDK examples, and MCP no longer call legacy endpoints.

No removal date or version is scheduled by this change. Historical records are preserved.

Validation

Unit tests cover GET serialization, invalid structured input, normalized ranges, permission checks, definition website/type mismatches, immutable update scope, SQL dataset separation for PostgreSQL and ClickHouse, cache keys, SDK requests, MCP composition, and compatibility routing.

tests/api/report-migration.spec.ts exercises legacy/new result parity, saved-definition lifecycles, shared access, and split datasets against the existing disposable API test stack. It is intended to run in both database modes. Do not point it at a development or production database: the API suite seeds and mutates test data. This migration was developed without a running disposable API server; live backend parity remains a release verification step.

Regenerate and verify contracts with pnpm generate:api, pnpm openapi:check, and pnpm check:api:client. Build packages before their tests so MCP resolves the current API client.