Dashboard API
API endpoints for managing user dashboard layouts, widget configurations, and dashboard analytics.
Overview
The Dashboard API provides endpoints for the organization-level analytics dashboard. It includes dashboard layout management (save/restore widget positions per user), summary statistics, and performance widgets.
Dashboard layouts are stored per-user and per-organization, allowing each user to customize their dashboard independently across different organizations.
Save Layout
Save (create or update) the current user’s dashboard widget layout. Uses PostgreSQL upsert to handle both first-time saves and subsequent updates in a single operation.
POST /api/trpc/dashboard.saveLayout
Request:
{
"json": {
"layout": {
"lg": [
{ "i": "stats", "x": 0, "y": 0, "w": 12, "h": 2, "minW": 6, "minH": 2 },
{ "i": "kpi-summary", "x": 0, "y": 2, "w": 6, "h": 4, "minW": 4, "minH": 3 },
{ "i": "action-summary", "x": 6, "y": 2, "w": 6, "h": 4, "minW": 4, "minH": 3 },
{ "i": "my-tasks", "x": 0, "y": 6, "w": 8, "h": 5, "minW": 4, "minH": 3 },
{ "i": "recent-activity", "x": 8, "y": 6, "w": 4, "h": 5, "minW": 3, "minH": 3 }
],
"md": [
{ "i": "stats", "x": 0, "y": 0, "w": 10, "h": 2, "minW": 6, "minH": 2 },
{ "i": "kpi-summary", "x": 0, "y": 2, "w": 5, "h": 4, "minW": 4, "minH": 3 },
{ "i": "action-summary", "x": 5, "y": 2, "w": 5, "h": 4, "minW": 4, "minH": 3 }
]
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
layout | object | Yes | react-grid-layout Layouts object mapping breakpoint names to widget position arrays |
Layout Item Fields
Each layout item within a breakpoint array has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
i | string | Yes | Widget identifier (e.g., stats, kpi-summary, my-tasks) |
x | number | Yes | X position in grid units |
y | number | Yes | Y position in grid units |
w | number | Yes | Width in grid units |
h | number | Yes | Height in grid units |
minW | number | No | Minimum width constraint |
minH | number | No | Minimum height constraint |
Breakpoint Names
| Breakpoint | Description |
|---|---|
lg | Large screens (desktop) |
md | Medium screens (tablet landscape) |
sm | Small screens (tablet portrait) |
xs | Extra-small screens (mobile landscape) |
xxs | Smallest screens (mobile portrait) |
Response:
{
"result": {
"data": {
"json": {
"id": "lay_01HXK5QJBN3YZXM8KJP2RSNV4C",
"updatedAt": "2026-03-31T08:15:00.000Z"
}
}
}
}
The userId and organizationId are always taken from the authenticated session context, never from client input. This ensures users can only modify their own dashboard layout and prevents cross-tenant access.
Get Layout
Retrieve the current user’s saved dashboard layout for the current organization. Returns null if no layout has been saved yet, allowing the frontend to fall back to the default layout.
GET /api/trpc/dashboard.getLayout
Response:
{
"result": {
"data": {
"json": {
"id": "lay_01HXK5QJBN3YZXM8KJP2RSNV4C",
"layout": {
"lg": [
{ "i": "stats", "x": 0, "y": 0, "w": 12, "h": 2, "minW": 6, "minH": 2 }
]
},
"updatedAt": "2026-03-31T08:15:00.000Z"
}
}
}
}
Returns null when no layout has been saved:
{
"result": {
"data": {
"json": null
}
}
}
When the response is null, the dashboard frontend should render widgets using the default layout configuration. The first time the user rearranges widgets, saveLayout is called to persist their customization.
Add Widget
Add a new widget to the user’s dashboard. If no layout exists yet, one is created automatically.
POST /api/trpc/dashboard.addWidget
Request:
{
"json": {
"widgetType": "kpi-summary",
"title": "KPI Overview",
"config": {
"boardId": "brd_01HXK5...",
"refreshInterval": 300
},
"position": {
"x": 0,
"y": 6,
"w": 6,
"h": 4
}
}
}
| Field | Type | Required | Description |
|---|---|---|---|
widgetType | string | Yes | Widget type identifier |
title | string | Yes | Display title for the widget |
config | object | No | Widget-specific configuration (stored as JSONB) |
position | object | Yes | Grid position (x, y, w, h) |
layoutId | string | No | Target layout ID (auto-resolved if omitted) |
Remove Widget
Remove a single widget from the user’s dashboard by widget ID.
POST /api/trpc/dashboard.removeWidget
Request:
{
"json": {
"widgetId": "wgt_01HXK5QJBN3YZXM8KJP2RSNV4C"
}
}
| Field | Type | Required | Description |
|---|---|---|---|
widgetId | string | Yes | The widget ID to remove |
Widget ownership is verified through the parent layout record, which must belong to the current user in the current organization. This prevents cross-user widget deletion.