Move and resize widgets in one batch

Saves the position and size of several widgets at once, as dragging and resizing on the dashboard does. Each breakpoint (xs, sm, md, lg) lists placements in grid units: i is the widget id, x and w count columns (12 on lg, 8 on md, 4 on sm, 2 on xs, and x + w must fit), and y and h count rows of 54 px with 12 px gaps. A widget named in any breakpoint has its whole stored layout replaced by the placements sent for it, so send all four breakpoints for every widget you move; a breakpoint it is missing from loses its stored position and is placed automatically. Layouts are per dashboard view because a widget belongs to one view. expectedVersions must name the version you last read for every widget in layouts; when a widget changed, was deleted or is not yours, nothing is saved and the request fails with 409 widgetLayoutChanged, so read again and retry. A large-breakpoint (lg) placement that overlaps another widget of the same dashboard view fails with 400 widgetLayoutOverlap; empty rows between widgets are allowed, and the dashboard moves widgets up into them, and one smaller than its widget minimum (2 rows for charts and numbers, 2 columns and 6 rows for activity timelines, 2 columns and 5 rows for calendars, 3 columns and 5 rows for maps) fails with 400 widgetLayoutTooSmall. Unchanged placements are omitted from the result. Read positions and versions with /v1/widgets/list first.

Requires: ownership of the widgets; the list holds only the caller's own widgets and their results stay filtered by read access to the widgets' lists.

POST
/v1/widgets/layout

Authorization

apiKeyAuth
x-api-key<token>

API key authentication. Create an API key in your user profile and include it in the x-api-key header.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://customermates.com/api/v1/widgets/layout" \  -H "Content-Type: application/json" \  -d '{    "layouts": {      "xs": [        {          "i": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",          "x": 0,          "y": 0,          "w": 2,          "h": 3        },        {          "i": "4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e",          "x": 0,          "y": 3,          "w": 2,          "h": 3        }      ],      "sm": [        {          "i": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",          "x": 0,          "y": 0,          "w": 4,          "h": 3        },        {          "i": "4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e",          "x": 0,          "y": 3,          "w": 4,          "h": 3        }      ],      "md": [        {          "i": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",          "x": 0,          "y": 0,          "w": 4,          "h": 3        },        {          "i": "4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e",          "x": 4,          "y": 0,          "w": 4,          "h": 3        }      ],      "lg": [        {          "i": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",          "x": 0,          "y": 0,          "w": 6,          "h": 3        },        {          "i": "4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e",          "x": 6,          "y": 0,          "w": 6,          "h": 3        }      ]    },    "expectedVersions": {      "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d": 1,      "4b5c6d7e-8f9a-4b2c-8d3e-4f5a6b7c8d9e": 1    }  }'
[
  {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "version": 9007199254740991,
    "layout": {
      "xs": {
        "i": "string",
        "x": 0,
        "y": 0,
        "w": 0,
        "h": 0,
        "minW": 0,
        "maxW": 0,
        "minH": 0,
        "maxH": 0
      },
      "sm": {
        "i": "string",
        "x": 0,
        "y": 0,
        "w": 0,
        "h": 0,
        "minW": 0,
        "maxW": 0,
        "minH": 0,
        "maxH": 0
      },
      "md": {
        "i": "string",
        "x": 0,
        "y": 0,
        "w": 0,
        "h": 0,
        "minW": 0,
        "maxW": 0,
        "minH": 0,
        "maxH": 0
      },
      "lg": {
        "i": "string",
        "x": 0,
        "y": 0,
        "w": 0,
        "h": 0,
        "minW": 0,
        "maxW": 0,
        "minH": 0,
        "maxH": 0
      }
    }
  }
]
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
{
  "error": {
    "kind": "validation",
    "issues": [
      {
        "code": "string",
        "path": [
          "string"
        ],
        "message": "string",
        "customCode": "recordNotFound",
        "entitlement": "string"
      }
    ],
    "retryable": true
  }
}
Empty