Layers API
Widgets on an overlay (layers): add, move, resize, hide, lock and remove.
On this page
Authenticate with a personal token as Authorization: Bearer pxp_...; the operations are also MCP tools unless noted. The full machine-readable definition is in the OpenAPI specification.
| Operation | Method and path | Scope |
|---|---|---|
| List layers | GET /overlays/{overlayId}/members | overlays:read |
| Add layer | POST /overlays/{overlayId}/members | members:write |
| Move, hide, lock or rename a layer | PATCH /overlays/{overlayId}/members/{memberId} | overlays:write |
| Update several layers at once | PATCH /overlays/{overlayId}/members | overlays:write |
| Remove layer | DELETE /overlays/{overlayId}/members/{memberId} | members:write |
| Duplicate layer | POST /overlays/{overlayId}/members/{memberId}/duplicate | members:write |
| Group layers | POST /overlays/{overlayId}/groups | overlays:write |
| Rename, collapse, hide or lock a group | PATCH /overlays/{overlayId}/groups/{groupId} | overlays:write |
| Add or remove layers in a group | PUT /overlays/{overlayId}/groups/{groupId}/layers | overlays:write |
| Move a group | POST /overlays/{overlayId}/groups/{groupId}/move | overlays:write |
| Ungroup layers | POST /overlays/{overlayId}/groups/{groupId}/ungroup | overlays:write |
| Duplicate group | POST /overlays/{overlayId}/groups/{groupId}/duplicate | members:write |
| Change a layer's stacking order | POST /overlays/{overlayId}/members/{memberId}/restack | overlays:write |
| Align or distribute layers | POST /overlays/{overlayId}/members/align | overlays:write |
Operations
List layers
/api/v1/overlays/{overlayId}/membersLists the layers (widgets) on an overlay with position, measured size (w, h in design pixels, when known), stacking, visibility, settings values and declared commands.
Scope: overlays:read (Read overlays) · MCP tool: list_members · Notes: read only
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
curl -X GET "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members" \
-H "Authorization: Bearer $PX_TOKEN"const overlayId = '<overlayId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members`, {
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
},
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Add layer
/api/v1/overlays/{overlayId}/membersAdds a widget (by its catalog slug) as a new layer, optionally with a name, settings values, a look kit (list_presets lookKits), a position, stacking and the scene it should be visible in. In the live scene the new layer shows up on air. Supports the Idempotency-Key header.
Scope: members:write (Add and remove layers) · MCP tool: add_member · Notes: supports Idempotency-Key
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
widget | body | string | required | Widget slug, e.g. "element-text", "element-image", "alertbox". Up to 80 characters |
name | body | string | optional | Up to 40 characters |
values | body | object | optional | Settings values (keys and types from get_widget fields). Unknown keys are dropped. A dropdown takes the option key (e.g. "miami"), not its label; a value that is not an option answers 422 invalid_option with the allowed options (key and label), a wrong type 422 invalid_value, and no layer is created. Numbers are clamped to min/max. For element-image/element-media use the url of an uploaded file |
lookKit | body | string | optional | Look kit id from list_presets: applies its values for this widget (explicit values win). Up to 40 characters |
sceneId | body | integer | optional | Scene the layer is visible in (default: the live scene). It starts hidden in every other scene. At least 1 |
layout | body | object | optional | Placement in design-space pixels (canvas 1920 wide): x/y move the layer from the canvas center, scale 0.05-4, rot in degrees, opacity 0-1, optional crop (cropL/cropT/cropR/cropB in native px) |
z | body | integer | optional | Stacking position (0 = bottom); other layers move to fill the gap. 0 to 1000 |
hidden | body | boolean | optional | Hide or show the layer (on the live output when this overlay is on air) |
locked | body | boolean | optional | Editor lock (prevents accidental dragging in the editor) |
animEntrance | body | none, fade-up, pop, slide-left, slide-right, slide-top, slide-bottom | optional | |
animLoop | body | none, float, pulse | optional | |
animDuration | body | number | optional | 0.1 to 3 |
animDelay | body | number | optional | 0 to 2 |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "widget": "..." }'const overlayId = '<overlayId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ widget: "..." }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Move, hide, lock or rename a layer
/api/v1/overlays/{overlayId}/members/{memberId}Updates one layer: position/scale/rotation (layout), stacking (z), visibility (hidden), editor lock, entrance/loop animation, or its name. Changes to the live scene show on air immediately.
Scope: overlays:write (Design overlays) · MCP tool: update_member
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberId | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
layout | body | object | optional | Placement in design-space pixels (canvas 1920 wide): x/y move the layer from the canvas center, scale 0.05-4, rot in degrees, opacity 0-1, optional crop (cropL/cropT/cropR/cropB in native px) |
z | body | integer | optional | Stacking position (0 = bottom); other layers move to fill the gap. 0 to 1000 |
hidden | body | boolean | optional | Hide or show the layer (on the live output when this overlay is on air) |
locked | body | boolean | optional | Editor lock (prevents accidental dragging in the editor) |
animEntrance | body | none, fade-up, pop, slide-left, slide-right, slide-top, slide-bottom | optional | |
animLoop | body | none, float, pulse | optional | |
animDuration | body | number | optional | 0.1 to 3 |
animDelay | body | number | optional | 0 to 2 |
name | body | string | optional | Up to 40 characters |
expectedRev | body | integer | optional | Optional optimistic concurrency guard: the overlay rev you last saw. A stale value answers 409 rev_conflict with the current state. At least 0 |
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/<memberId>" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "layout": {}, "z": 1 }'const overlayId = '<overlayId>';
const memberId = '<memberId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ layout: {}, z: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Update several layers at once
/api/v1/overlays/{overlayId}/membersApplies up to 100 layer changes atomically (one transaction, one rev). With expectedRev, a stale rev answers 409 rev_conflict instead of overwriting concurrent edits. Changes to the live scene show on air immediately.
Scope: overlays:write (Design overlays) · MCP tool: update_members
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
changes | body | array of object | required | Up to 100 items |
expectedRev | body | integer | optional | Optional optimistic concurrency guard: the overlay rev you last saw. A stale value answers 409 rev_conflict with the current state. At least 0 |
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "changes": [] }'const overlayId = '<overlayId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ changes: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Remove layer
/api/v1/overlays/{overlayId}/members/{memberId}DESTRUCTIVE: removes a layer from the overlay (it disappears from the stream output if visible). The widget setup can be restored in the editor history.
Scope: members:write (Add and remove layers) · MCP tool: remove_member · Notes: destructive, needs confirmation in MCP
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberId | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
curl -X DELETE "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/<memberId>" \
-H "Authorization: Bearer $PX_TOKEN"const overlayId = '<overlayId>';
const memberId = '<memberId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}`, {
method: 'DELETE',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
},
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Duplicate layer
/api/v1/overlays/{overlayId}/members/{memberId}/duplicateCopies a layer with its current settings, slightly offset from the original. With sceneId the copy is visible only in that scene (default: the live scene, where it shows up on air).
Scope: members:write (Add and remove layers) · MCP tool: duplicate_member
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberId | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
sceneId | body | integer | optional | Scene the copy is visible in (default: the live scene). At least 1 |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/<memberId>/duplicate" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "sceneId": 1 }'const overlayId = '<overlayId>';
const memberId = '<memberId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}/duplicate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ sceneId: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Group layers
/api/v1/overlays/{overlayId}/groupsGroups two or more layers in the layer list (editor organization). The grouped layers move next to each other in the stack; positions and visibility stay the same.
Scope: overlays:write (Design overlays) · MCP tool: create_group
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberIds | body | array of integer | required | The layers to group (at least two). Up to 50 items |
name | body | string | optional | Group name (default "Group"). Up to 40 characters |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "memberIds": [] }'const overlayId = '<overlayId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ memberIds: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Rename, collapse, hide or lock a group
/api/v1/overlays/{overlayId}/groups/{groupId}Renames a layer group, collapses it in the layer list, hides or shows all its layers (hidden, on air immediately when this overlay is live) or locks all its layers in the editor (locked). Name, collapsed and locked change nothing on air.
Scope: overlays:write (Design overlays) · MCP tool: update_group
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
groupId | path | string | required | Layer group id (from get_overlay groups). Up to 64 characters |
name | body | string | optional | Up to 40 characters |
collapsed | body | boolean | optional | Collapse the group in the layer list |
hidden | body | boolean | optional | Hide or show every layer of the group in the live scene |
locked | body | boolean | optional | Editor lock for every layer of the group (prevents accidental dragging) |
curl -X PATCH "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups/<groupId>" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "name": "...", "collapsed": true }'const overlayId = '<overlayId>';
const groupId = '<groupId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups/${groupId}`, {
method: 'PATCH',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ name: "...", collapsed: true }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Add or remove layers in a group
/api/v1/overlays/{overlayId}/groups/{groupId}/layersMoves layers into a layer group (add) or takes them out of it (remove). Layers in remove that are not in this group stay where they are. Positions and visibility stay the same; nothing changes on air.
Scope: overlays:write (Design overlays) · MCP tool: set_group_layers
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
groupId | path | string | required | Layer group id (from get_overlay groups). Up to 64 characters |
add | body | array of integer | optional | Layers to put into the group (a layer leaves its old group). Up to 50 items |
remove | body | array of integer | optional | Layers to take out of the group. Up to 50 items |
curl -X PUT "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups/<groupId>/layers" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "add": [], "remove": [] }'const overlayId = '<overlayId>';
const groupId = '<groupId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups/${groupId}/layers`, {
method: 'PUT',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ add: [], remove: [] }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Move a group
/api/v1/overlays/{overlayId}/groups/{groupId}/moveMoves every unlocked layer of a group by dx/dy (design-space pixels of a 1920 wide canvas) in the live scene; scale, rotation and opacity stay the same. Locked layers stay where they are. Shows on air immediately when this overlay is live.
Scope: overlays:write (Design overlays) · MCP tool: move_group
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
groupId | path | string | required | Layer group id (from get_overlay groups). Up to 64 characters |
dx | body | number | optional | Horizontal offset in design pixels (positive = right). -4000 to 4000 |
dy | body | number | optional | Vertical offset in design pixels (positive = down). -4000 to 4000 |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups/<groupId>/move" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "dx": 1, "dy": 1 }'const overlayId = '<overlayId>';
const groupId = '<groupId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups/${groupId}/move`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ dx: 1, dy: 1 }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Ungroup layers
/api/v1/overlays/{overlayId}/groups/{groupId}/ungroupUngroups the layers. The layers themselves stay on the overlay with their positions and visibility.
Scope: overlays:write (Design overlays) · MCP tool: delete_group
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
groupId | path | string | required | Layer group id (from get_overlay groups). Up to 64 characters |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups/<groupId>/ungroup" \
-H "Authorization: Bearer $PX_TOKEN"const overlayId = '<overlayId>';
const groupId = '<groupId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups/${groupId}/ungroup`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
},
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Duplicate group
/api/v1/overlays/{overlayId}/groups/{groupId}/duplicateCopies every layer of a group (slightly offset) into a new group "<name> copy". The copies show up in the live scene like any new layer and count against the layer limit.
Scope: members:write (Add and remove layers) · MCP tool: duplicate_group
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
groupId | path | string | required | Layer group id (from get_overlay groups). Up to 64 characters |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/groups/<groupId>/duplicate" \
-H "Authorization: Bearer $PX_TOKEN"const overlayId = '<overlayId>';
const groupId = '<groupId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/groups/${groupId}/duplicate`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
},
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Change a layer's stacking order
/api/v1/overlays/{overlayId}/members/{memberId}/restackPuts one layer behind or in front of another layer (behind / in_front with relativeToMemberId), or to the very back or front of the stack. The server renumbers the stacking order, so no z values are needed. back keeps the layer above full-canvas backgrounds at the bottom. Only the stacking order changes, in one step that the overlay history can undo.
Scope: overlays:write (Design overlays) · MCP tool: restack_member
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberId | path | integer | required | Layer (member) id (from get_overlay or list_members). At least 1 |
position | body | behind, in_front, back, front | required | Behind or in_front of relativeToMemberId; back or front of the whole stack |
relativeToMemberId | body | integer | optional | The other layer, required for behind and in_front. At least 1 |
expectedRev | body | integer | optional | Optional optimistic concurrency guard: the overlay rev you last saw. A stale value answers 409 rev_conflict with the current state. At least 0 |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/<memberId>/restack" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "position": "behind" }'const overlayId = '<overlayId>';
const memberId = '<memberId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/${memberId}/restack`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ position: "behind" }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Align or distribute layers
/api/v1/overlays/{overlayId}/members/alignAligns 2 to 50 layers by their visible box on the canvas: left, center, right, top, middle or bottom edges, or distribute-h / distribute-v for equal gaps. relativeTo selection (default) aligns to the box around all named layers; canvas aligns to the canvas. Only x/y change, in one step that the overlay history can undo. Locked layers and layers that position themselves stay put. Layers whose size was never measured answer 422 size_unknown. Changes to the live scene show on air immediately.
Scope: overlays:write (Design overlays) · MCP tool: align_members
| Name | In | Type | Required | Description |
|---|---|---|---|---|
overlayId | path | string | required | Overlay id (from list_overlays). Up to 64 characters |
memberIds | body | array of integer | required | The layers to align (from get_overlay). Up to 50 items |
mode | body | left, center, right, top, middle, bottom, distribute-h, distribute-v | required | Left/center/right align horizontally, top/middle/bottom vertically; distribute-h/distribute-v make the gaps equal |
relativeTo | body | selection, canvas | optional | Selection (default): the box around the named layers; canvas: the whole canvas |
expectedRev | body | integer | optional | Optional optimistic concurrency guard: the overlay rev you last saw. A stale value answers 409 rev_conflict with the current state. At least 0 |
curl -X POST "https://pxstudio.cloud/api/v1/overlays/<overlayId>/members/align" \
-H "Authorization: Bearer $PX_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "memberIds": [], "mode": "left" }'const overlayId = '<overlayId>';
const res = await fetch(`https://pxstudio.cloud/api/v1/overlays/${overlayId}/members/align`, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.PX_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({ memberIds: [], mode: "left" }),
});
if (!res.ok) throw new Error(`PX Studio API: ${res.status}`);
const data = await res.json();Was this page helpful?