Metrics & Analytics API
PandaStack separates two families of project telemetry, both backed by ClickHouse:
- Metrics — performance and health (requests, errors, latency, bandwidth). The “Metrics” tab.
- Analytics — audience and traffic (visitors, geography, referrers, devices). The “Analytics” tab.
When ClickHouse is unreachable or unconfigured, responses carry enabled: false and empty data rather than failing. Time-series values are nullable on a densified grid, where null marks a gap (no sample in that bucket).
Concept guides: Metrics and Analytics.
All routes require authentication and are available to any member. Every range-based endpoint takes a ?range query param of type MetricRange: one of 1h, 24h, 7d, 30d (default 24h).
Metrics
Section titled “Metrics”Summary tiles
Section titled “Summary tiles”GET /v1/projects/:name/metrics/summary
Performance/health summary tiles for a project.
Query: ?range (default 24h). Response (MetricsSummary):
| Field | Type | Notes |
|---|---|---|
range | MetricRange | |
enabled | boolean | false = ClickHouse unreachable. |
requests | number | |
errors | number | |
error_rate | number | Percentage, 0–100. |
latency_ms | object | { p50, p95, p99, avg }. |
bandwidth_bytes | number | |
unique_visitors | number | |
rps | number | Requests per second. |
curl "https://api.pandastack.io/v1/projects/my-app/metrics/summary?range=24h" \ -H "Authorization: Bearer $PANDASTACK_TOKEN"{ "success": true, "data": { "range": "24h", "enabled": true, "requests": 128400, "errors": 312, "error_rate": 0.24, "latency_ms": { "p50": 18, "p95": 140, "p99": 420, "avg": 34 }, "bandwidth_bytes": 8123456789, "unique_visitors": 9021, "rps": 1.49 }}Time-series
Section titled “Time-series”GET /v1/projects/:name/metrics/timeseries
Query: ?range. Response (MetricsTimeseries): { range, enabled, points: MetricsPoint[] } where each MetricsPoint is { t (ISO), requests, errors, p95, bytes_out } and all values are nullable (null = gap).
Breakdown (top-N)
Section titled “Breakdown (top-N)”GET /v1/projects/:name/metrics/breakdown
Query: ?range, ?limit (default 10). Response (MetricsBreakdown):
| Field | Type | Notes |
|---|---|---|
range | MetricRange | |
enabled | boolean | |
top_paths | array | { path, requests, p95 }. |
status_codes | array | { status, requests }. |
top_countries | array | { country, requests }. |
Batch sparklines
Section titled “Batch sparklines”GET /v1/projects/metrics/sparklines
24-hour request sparklines for every project in the org, in one call (cached ~60s) — used to render the projects list.
Response (ProjectsSparklines): { enabled, projects } where projects is a record keyed by project name, each value { total (24h request total), points: [{ t, requests, errors }] }.
curl https://api.pandastack.io/v1/projects/metrics/sparklines \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Live metrics stream
Section titled “Live metrics stream”GET /v1/projects/:name/metrics/stream
Server-Sent Events stream that pushes a fresh MetricsSummary roughly every 5 seconds (live KPI tiles).
Because this is SSE, pass the token (and org, for JWTs) as query params: ?range=<range>&access_token=<token>&organization_id=<orgId>. See SSE authentication.
Event: summary, whose data is a MetricsSummary.
curl -N "https://api.pandastack.io/v1/projects/my-app/metrics/stream?range=1h&access_token=$PANDASTACK_TOKEN&organization_id=1907"event: summarydata: {"range":"1h","enabled":true,"requests":204,"errors":0,"error_rate":0,"latency_ms":{"p50":12,"p95":88,"p99":210,"avg":21},"bandwidth_bytes":10240000,"unique_visitors":31,"rps":0.06}Analytics
Section titled “Analytics”Audience/traffic insights. Note that analytics carries two boolean flags: enabled (ClickHouse configured at the platform level) and analyticsEnabled (this specific project has analytics turned on).
Summary
Section titled “Summary”GET /v1/projects/:name/analytics/summary
Query: ?range. Response (AnalyticsSummary):
| Field | Type | Notes |
|---|---|---|
range | MetricRange | |
enabled | boolean | ClickHouse configured platform-wide. |
analyticsEnabled | boolean | This project has analytics on. |
uniqueVisitors | number | |
totalViews | number | Non-bot requests. |
botViews | number | |
returningVisitors | number | |
viewsPerVisitor | number |
Time-series
Section titled “Time-series”GET /v1/projects/:name/analytics/timeseries
Query: ?range. Response (AnalyticsTimeseries): { range, enabled, points: [{ t, visitors, views }] } (values nullable).
Breakdown (top-N)
Section titled “Breakdown (top-N)”GET /v1/projects/:name/analytics/breakdown
Query: ?range, ?limit (default 8). Response (AnalyticsBreakdown):
| Field | Type | Notes |
|---|---|---|
range | MetricRange | |
enabled | boolean | |
top_countries | DimensionRow[] | Each { label, visitors, views }. |
top_referrers | DimensionRow[] | |
top_pages | DimensionRow[] | |
browsers | DimensionRow[] | |
devices | DimensionRow[] |
curl "https://api.pandastack.io/v1/projects/my-app/analytics/breakdown?range=7d&limit=8" \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Activity feed
Section titled “Activity feed”GET /v1/activity
The org-scoped audit/activity feed — “who did what, when” — cursor-paginated, backed by the shared Events table.
Auth: any member. Query (ActivityQuery):
| Param | Type | Notes |
|---|---|---|
cursor | string | Opaque cursor from nextCursor. |
limit | int | 1–100, default 50. |
serviceType | string | Filter by service (e.g. project, database, cronjob). |
q | string | Free-text match on the event sentence. |
projectId | int | Filter by project. |
Response: paged(ActivityEvent) — { items: ActivityEvent[], nextCursor }.
ActivityEvent:
| Field | Type | Notes |
|---|---|---|
id | number | |
event | string | null | Human-readable sentence. |
serviceType | enum | string | null | project | cronjob | database | edge | monitor | team | organization | managed_app (forward-compatible passthrough). |
method | string | null | POST | PUT | DELETE. |
status | string | null | success | failed. |
organizationId | string | |
projectId | number | null | |
deploymentId | number | null | |
actor | object | { userId, name, username, avatarUrl }. |
resourceName | string | null | |
createdAt | string | ISO 8601. |
curl "https://api.pandastack.io/v1/activity?serviceType=database&limit=25" \ -H "Authorization: Bearer $PANDASTACK_TOKEN"Related
Section titled “Related”- Monitors API — active uptime checks (vs. passive traffic metrics).
- Databases API — metrics — database-specific telemetry.
- Usage & limits API — metered analytics events.