Loopfour
API Reference

Dashboards

Save a dashboard's complete widget layout without changing its data connections.

Save widget layout

PUT /api/v1/dashboards/:id/layout

Requires an authenticated user who owns the dashboard in their active company, with workflows:write access. Company viewers and invited viewers cannot change layout. Public share links are read-only snapshots.

Send every widget in the dashboard, using IDs and positions from GET /api/v1/dashboards/:id. The grid has 12 columns. Studio offers widths of 4, 6, or 12 columns and heights of 4 or 8 rows.

FieldRequirements
widgetsComplete array, at most 40 entries; empty only for an empty dashboard
widgets[].idUnique widget UUID belonging to this dashboard
widgets[].xInteger from 0 through 11
widgets[].yNonnegative safe integer, at most Number.MAX_SAFE_INTEGER - 12
widgets[].wPositive integer, at most 12; x + w must not exceed 12
widgets[].hPositive integer, at most 12
curl -X PUT 'https://API_HOST/api/v1/dashboards/DASHBOARD_ID/layout' \
  -H 'Content-Type: application/json' \
  -H 'Cookie: better-auth.session_token=SESSION_TOKEN' \
  --data '{"widgets":[{"id":"00000000-0000-0000-0000-000000000001","x":0,"y":0,"w":6,"h":8}]}'

The server closes vertical gaps, resolves overlaps in row/column order, and saves all positions atomically. Always apply the returned positions: they can differ from the submitted Y coordinates. Merge them into your existing widgets by ID. This endpoint never replaces widget configs, query connections, refresh settings, or snapshot data, and does not create a dashboard version.

{
  "success": true,
  "data": {
    "widgets": [
      { "id": "00000000-0000-0000-0000-000000000001", "x": 0, "y": 0, "w": 6, "h": 8 }
    ],
    "updatedAt": "2026-09-18T12:00:00.000Z"
  }
}

A successful save updates the dashboard timestamp and records one audit event. Send a request after a completed edit, rather than when rendering or polling.

StatusMeaning
200Complete accepted layout saved
400Invalid coordinates, duplicate IDs, or an ID outside this dashboard
401 / 403Missing authentication or insufficient scope
404Dashboard is unavailable to the caller as its owner
409The layout omits widgets added since the client loaded it; reload before saving
413Request exceeds 1 MB
429Write rate limit reached

Invalid or stale sets save nothing. A concurrent widget creation is serialized with a layout save. Creation remains server-placed: POST /:id/widgets accepts optional width/height hints, and ignores requested X/Y positions. The existing PATCH /:id/widgets/:widgetId also accepts a complete position within the same bounds, compacts affected widgets, and preserves omitted config/source fields.

On this page