Skip to main content

Usage Stats & Analytics

Looking for the product view?
The Help Center explains this surface as users see it: Overview & Usage.

Endpoints for viewing app usage statistics, workspace storage, and server route invocation history.

GET /api/apps/{id}/stats

Get aggregated usage statistics for an app including view counts, API invocations, and workspace storage.

Authentication: Required

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
Usage statistics overviewGET /api/apps/00000000-0000-4000-8000-000000000001/stats
One call powers the admin Overview tab: view trends, API and tool invocations, log and agent-run counts, workspace storage, and the sidebar badge counts.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/apps/00000000-0000-4000-8000-000000000001/stats"
}
},
"appId": "00000000-0000-4000-8000-000000000001",
"totalViews": 2,
"uniqueViewers": 1,
"views7d": 2,
"viewsPrev7d": 0,
"views30d": 2,
"lastViewedAt": "2026-01-15T16:20:00.000Z",
"viewsByDay": [
{
"day": "2026-01-15",
"count": 2
}
],
"uniqueUsersByDay": [
{
"day": "2026-01-15",
"count": 1
}
],
"api": {
"totalInvocations": 2,
"invocations7d": 2,
"invocations30d": 2,
"avgDurationMs": 42,
"errorCount30d": 0,
"peakMemoryBytes": 403504,
"totalComputeMs": 42,
"errorRate30d": 0
},
"apiByDay": [
{
"day": "2026-01-15",
"count": 2,
"errorCount": 0
}
],
"recentViewers": [
{
"principalId": "admin",
"displayName": null,
"lastViewedAt": "2026-01-15T16:20:00.000Z",
"viewCount": 2,
"viewsByDay": [
{
"day": "2026-01-15",
"count": 2
}
]
}
],
"topViewers": [
{
"principalId": "admin",
"displayName": null,
"lastViewedAt": "2026-01-15T16:20:00.000Z",
"viewCount": 2,
"viewsByDay": [
{
"day": "2026-01-15",
"count": 2
}
]
}
],
"tools": {
"totalInvocations": 0,
"invocations30d": 0,
"errors30d": 0,
"avgDurationMs": null
},
"logs": {
"logs30d": 0,
"errors30d": 0,
"warnings30d": 0
},
"agents": {
"runs30d": 0,
"errors30d": 0,
"runsByDay": []
},
"storage": {
"hasWorkspace": true,
"schemaSize": 65536,
"tableCount": 1,
"quotaBytes": null,
"quotaPercent": null
},
"counts": {
"shares": 0,
"dependencies": 1,
"apiRoutes": 1,
"webhooks": 0,
"tools": 0,
"agents": 1,
"messages": 0
}
}
Captured from the API examples test suite; ids and timestamps are normalized.

Key Fields:

FieldDescription
totalViews / uniqueViewers / views7d / views30dView counts from the view audit
viewsByDay / uniqueUsersByDayDaily breakdowns over the last 30 days
recentViewers / topViewersPer-person view data, each with a viewsByDay sparkline series
apiServer-route invocation totals (counts, error rate, peak memory, compute time)
tools / logsTool-invocation and developer-log counters
agentsruns30d, errors30d, and a runsByDay series
storage.hasWorkspaceWhether the app has a Postgres workspace
storage.schemaSize / storage.tableCountWorkspace disk usage and table count
storage.quotaBytes / quotaPercentAlways null — no per-app storage quota is currently enforced
countsSidebar badge counts: shares, dependencies, apiRoutes, webhooks, tools, agents, messages

Permissions Required: app:write (Designer for Magic Reports, Admin for full Apps); 404 if the user cannot read the app at all


GET /api/apps/{id}/stats/tables

List all tables in the app's Postgres workspace with column metadata.

Authentication: Required

Permissions Required: app:write (Designer for Magic Reports, Admin for full Apps)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID

Returns an empty array if the app has no workspace schema.

Workspace tablesGET /api/apps/00000000-0000-4000-8000-000000000001/stats/tables
Schema browser for the Database tab: per-table sizes, row counts, columns, and primary keys.
Response · 200
[
{
"name": "order_notes",
"rowCount": 1,
"sizeBytes": 32768,
"columns": [
{
"name": "id",
"type": "integer",
"nullable": false,
"primaryKey": true
},
{
"name": "note",
"type": "text",
"nullable": false
}
]
}
]
Captured from the API examples test suite; ids and timestamps are normalized.

Key Fields:

FieldDescription
rowCountExact row count (COUNT(*); app workspace tables are small enough)
sizeBytesTotal relation size from pg_total_relation_size()
columns[].primaryKeyWhether the column is part of the primary key
Internal Tables

The _migrations table used for tracking applied migrations is excluded from the response.


POST /api/apps/{id}/stats/tables/{table}/preview

Preview rows from a table in the app's workspace.

Authentication: Required

Permissions Required: app:write (Designer for Magic Reports, Admin for full Apps)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
tablestringTable name

Payload:

{
"limit": 25,
"offset": 0
}
FieldTypeDefaultDescription
limitinteger25Rows per page (1-100)
offsetinteger0Row offset for pagination
Preview table rowsPOST /api/apps/00000000-0000-4000-8000-000000000001/stats/tables/order_notes/preview
The table name is validated against information_schema; unknown tables and _migrations are 404.
Request body
{
"limit": 25,
"offset": 0
}
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/apps/00000000-0000-4000-8000-000000000001/stats/tables/order_notes/preview"
}
},
"rows": [
{
"id": 1,
"note": "Expedite #1042"
}
],
"rowCount": 1,
"totalRows": 1,
"fields": [
{
"name": "id",
"dataTypeID": 23
},
{
"name": "note",
"dataTypeID": 25
}
]
}
Captured from the API examples test suite; ids and timestamps are normalized.

Key Fields:

FieldDescription
rowCountNumber of rows returned in this page
totalRowsTotal rows in the table
fieldsColumn metadata with Postgres data type OIDs
Table Validation

The table name is validated against information_schema to prevent SQL injection. Requests for non-existent tables or the _migrations table return 404 Not Found.


GET /api/apps/{id}/stats/api

Get detailed server route invocation history and daily aggregates.

Authentication: Required

Permissions Required: app:write (Designer for Magic Reports, Admin for full Apps)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID
Server-route invocation historyGET /api/apps/00000000-0000-4000-8000-000000000001/stats/api
recent holds the last 100 invocations; daily aggregates the last 30 days. Deploy smoke tests appear here too: one of these rows is the deploy exercising GET /notes.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/apps/00000000-0000-4000-8000-000000000001/stats/api"
}
},
"routes": [
{
"method": "GET",
"path": "/notes",
"invocations30d": 2,
"errors30d": 0
}
],
"recent": [
{
"id": "00000000-0000-4000-8000-000000000002",
"method": "GET",
"path": "/notes",
"username": "admin",
"startedAt": "2026-01-15T16:20:00.000Z",
"durationMs": 42,
"statusCode": 200,
"memoryPeakBytes": "8388608",
"error": null
},
{
"id": "00000000-0000-4000-8000-000000000003",
"method": "GET",
"path": "/notes",
"username": "admin",
"startedAt": "2026-01-15T16:20:00.000Z",
"durationMs": 42,
"statusCode": 200,
"memoryPeakBytes": "8388608",
"error": null
}
],
"daily": [
{
"day": "2026-01-15T16:20:00.000Z",
"count": 2,
"avgDurationMs": 42,
"errorCount": 0
}
]
}
Captured from the API examples test suite; ids and timestamps are normalized.

Key Fields:

FieldDescription
recentLast 100 invocations, ordered by startedAt descending
recent[].memoryPeakBytesPeak memory usage of the V8 isolate
recent[].errorError message if the invocation failed, null otherwise
dailyDaily aggregates for the last 30 days
daily[].avgDurationMsAverage handler execution time for the day

GET /api/apps/{id}/usage

Get this app's AI credit consumption — current-month totals, a trailing monthly trend, a daily breakdown, per-model AI spend, and the top users driving the app. Powers the Usage tab of the App Admin Panel.

Every figure is scoped to this app via the (entityId, entityType = 'app') attribution stamped on usage_event / audit.ai_log rows at capture time, so only usage actually attributed to this app appears.

Authentication: Required

Permissions Required: app:write (403 if the user can read the app but lacks write; 404 if the user cannot read this app at all)

Path Parameters:

ParameterTypeDescription
idstringApp UUID or natural ID

Query Parameters:

ParameterTypeDefaultDescription
monthsinteger12Trailing months for the trend (history), 1-24
daysinteger30Rolling window for topUsers, 1-90

All totalCredits / totalEvents are numbers. Collections are always arrays (empty when the app has no usage).

Credit usage reportGET /api/apps/00000000-0000-4000-8000-000000000001/usage
Powers the Usage tab: current-month credit totals, monthly trend, per-model and per-resource breakdowns, and top users. Server-route compute time bills credits too, which is what this app shows; AI usage would add model rows.
Response · 200
{
"_links": {
"self": {
"href": "https://informer.example.com/api/apps/00000000-0000-4000-8000-000000000001/usage"
}
},
"months": 12,
"windowDays": 30,
"summary": [
{
"entityId": "00000000-0000-4000-8000-000000000001",
"entityType": "app",
"resourceType": "app_compute",
"totalCredits": 0.25,
"totalEvents": 2
}
],
"dailyTotals": [
{
"date": "2026-01-15T16:20:00.000Z",
"resourceType": "app_compute",
"totalCredits": 0.25
}
],
"history": [
{
"month": "2026-06",
"resourceType": "app_compute",
"totalCredits": 0.25,
"totalEvents": 2
}
],
"byModel": [],
"topUsers": [
{
"actor": "admin",
"actorType": "user",
"displayName": "acme Administrator",
"totalCredits": 0.25,
"totalEvents": 2
}
]
}
Captured from the API examples test suite; ids and timestamps are normalized.

Key Fields:

FieldDescription
summaryCurrent-month credits per resource type (ai, agent_run, app_compute, …); each row also carries this app's entityId / entityType
dailyTotalsCurrent-month credits per day and resource type
historyTrailing months of monthly credits by resource type — the trend chart
byModelCurrent-month AI credits grouped by model (from audit.ai_log), biggest first
topUsersTop actors over the trailing days; displayName falls back to the actor id for agents/system actors
AI attribution

byModel and the ai resource type only reflect AI calls tagged with this app's id at capture time (agent runs, app compute, and app-context AI). Usage that isn't app-attributed appears on the tenant-wide Settings → Usage page instead.