Skip to content

Apply a canvas changeset

POST
/workspaces/{workspaceId}/projects/{projectId}/canvas/changeset
import { FloraClient } from '@flora-ai/flora';
const client = new FloraClient({ apiKey: process.env['FLORA_API_KEY'] });
const canva = await client.projects.canvas.applyChangeset({
workspaceId: '<workspaceId>',
projectId: '<projectId>',
add: [
{
ref: 'hero',
type: 'image',
},
],
update: [
{
id: 'n7',
},
],
connect: [
{
from: 'n7',
to: 'n7',
},
],
disconnect: [
{
from: 'n7',
to: 'n7',
},
],
remove: [
{
id: 'n7',
},
],
});
console.log(canva);

Edits a project canvas: add, update, connect, disconnect and remove operations validate together before writes begin. Invalid operations reject the request, and every cause is reported with a machine-readable code in the error’s fields array. Authored content lives in document: an add of type timeline or deck may carry one, and an update replaces a timeline or deck document wholesale, guarded by base_revision so a write based on a stale read is rejected with revision_conflict instead of overwriting someone else’s edit. Documents are validated against their authoring limits. Deck updates require base_revision and use observed Liveblocks revisions; simultaneous collaborators and undo retain the editor’s existing semantics. Deck content and Timeline drafts use separate storage, so a mixed changeset is not a cross-store transaction. Deck writes do not render or export a presentation. Operations apply in the order add, update, connect, disconnect, remove, with groups created before their members — so one call can create a group, fill it, wire the new nodes to existing ones by the ref names it chose, and delete something else. Nodes are addressed by the short id or node UUID the project graph endpoint reports, or by a ref declared by an add operation in the same request. REMOVE IS IMMEDIATE AND IRREVERSIBLE through the API: there is no confirmation step and no undo, deleting a node also deletes its edges and any group members, so confirm destructive changesets with your user before sending them. The revision returned is the same change-detection marker the project graph endpoint reports, so it can be compared directly against a later read. Mutating public API requests support an optional Idempotency-Key header for client retries; duplicate keys within two hours return idempotency_duplicate.

Error responses use the standard error body.

workspaceId
required

Workspace identifier

string
/^ws_\S+$/

Workspace identifier

projectId
required

Project identifier

string
/^prj_\S+$/

Project identifier

Media type application/json
object
add

Nodes to create. Groups are created before their members.

Array<object>
<= 200 items
object
ref
required

Caller-chosen handle for the new node, echoed back in created with its real ids. Usable as a connect or group target inside this same changeset. Must not collide with a live node id.

string
>= 1 characters <= 64 characters
type
required

Node type to create, in the agent vocabulary the graph read reports

string
Allowed values: image video text audio timeline deck notes group static_image layer_editor
label

Display label pinned on the node

string
<= 500 characters
prompt

Generation prompt, stored in the node’s model parameters. Mutually exclusive with content_url.

string
model

Model name or endpoint id, as the graph read reports them. Omit to take the default model for the node’s modality.

string
params

Model parameters, validated against the model’s schema. Invalid values reject the whole changeset rather than being coerced.

object
key
additional properties
any
position

Absolute canvas position. Omit to place the node automatically below the existing canvas content.

object
x
required

Absolute horizontal canvas coordinate

number
y
required

Absolute vertical canvas coordinate

number
group

Group to parent this node into: an existing group’s short id or UUID, or the ref of a group created by this same changeset.

string
content_url

HTTPS URL of existing image, video, or audio to place instead of generating. The media is copied onto Flora’s CDN and the node becomes a static block. Mutually exclusive with prompt, model, and params.

string format: uri
document
Any of:
object
kind
required
Allowed value: timeline
schema_version
required

Document schema version; currently 1

integer
>= 1 <= 1
fps
required

Frames per second of the composition

number
composition_width
required

Even number of pixels

integer
composition_height
required

Even number of pixels

integer
tracks
required

Lanes, first is the bottom-most

Array<object>
>= 1 items <= 100 items
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
name

Display name of the lane

string
<= 200 characters
items
required

Item ids in this lane, bottom to top of the z-order. Every id must exist in items.

Array<string>
hidden
boolean
muted
boolean
items
required

Clips keyed by item id. At least one item is required.

object
key
additional properties
Any of:
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
from
required

Start frame on the composition timeline. Frames, not seconds.

integer
duration_in_frames
required

Length in frames. The cut is never guessed from the media.

integer
top

Top edge in composition pixels

number
left

Left edge in composition pixels

number
width

Width in composition pixels

number
height

Height in composition pixels

number
opacity
number
default: 1 <= 1
type
required
Allowed value: video
asset_id
required

Key of a video asset in assets

string
>= 1 characters <= 200 characters
video_start_from_in_seconds

Offset into the source video where playback starts. Seconds.

number
0
decibel_adjustment

Gain in dB; 0 leaves the source as is

number
0
playback_rate

Speed multiplier; 1 is real time

number
default: 1
audio_fade_in_duration_in_seconds
number
0
audio_fade_out_duration_in_seconds
number
0
fade_in_duration_in_seconds

Visual fade-in length in seconds

number
0
fade_out_duration_in_seconds

Visual fade-out length in seconds

number
0
crop_left

Fraction of the item cropped from the left

number
0 <= 1
crop_top

Fraction of the item cropped from the top

number
0 <= 1
crop_right

Fraction of the item cropped from the right

number
0 <= 1
crop_bottom

Fraction of the item cropped from the bottom

number
0 <= 1
border_radius

Corner radius in composition pixels

number
0
rotation

Rotation in degrees

number
0
keep_aspect_ratio
boolean
default: true
assets
required

Media keyed by asset id. Every media item’s asset_id must be a key here.

object
key
additional properties
Any of:
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
filename

Display name in the editor. Defaults to the last path segment of media_url.

string
>= 1 characters
mime_type

Defaults from the asset type and the media_url extension.

string
>= 1 characters
source_node_id

Canvas node whose output seeded this asset, when known. Read-only.

string
type
required
Allowed value: video
media_url
required

Durable https URL of the media the renderer fetches. Flora’s own asset URLs and any public https URL are accepted.

string format: uri
width
required

Native media width in pixels

number
height
required

Native media height in pixels

number
duration_in_seconds
required
number
has_audio_track
boolean
text

Body of a notes node: plain text, newlines significant, at most 20000 characters. Notes are canvas documentation — they generate nothing and spend nothing. Rejected on every other node type, which take prompt instead.

string
<= 20000 characters
update

Existing nodes to modify. One operation per node.

Array<object>
<= 200 items
object
id
required

Node to modify: its short id or UUID

string
>= 1 characters <= 200 characters
label

Replacement display label

string
<= 500 characters
prompt

Replacement generation prompt

string
model

Replacement model name or endpoint id

string
params

Model parameters, merged key by key into the node’s stored parameters. Omitted keys survive; a named key is overwritten. On an action node these are the action’s own parameter values.

object
key
additional properties
any
position

New absolute canvas position

object
x
required

Absolute horizontal canvas coordinate

number
y
required

Absolute vertical canvas coordinate

number
document
Any of:
object
kind
required
Allowed value: timeline
schema_version
required

Document schema version; currently 1

integer
>= 1 <= 1
fps
required

Frames per second of the composition

number
composition_width
required

Even number of pixels

integer
composition_height
required

Even number of pixels

integer
tracks
required

Lanes, first is the bottom-most

Array<object>
>= 1 items <= 100 items
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
name

Display name of the lane

string
<= 200 characters
items
required

Item ids in this lane, bottom to top of the z-order. Every id must exist in items.

Array<string>
hidden
boolean
muted
boolean
items
required

Clips keyed by item id. At least one item is required.

object
key
additional properties
Any of:
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
from
required

Start frame on the composition timeline. Frames, not seconds.

integer
duration_in_frames
required

Length in frames. The cut is never guessed from the media.

integer
top

Top edge in composition pixels

number
left

Left edge in composition pixels

number
width

Width in composition pixels

number
height

Height in composition pixels

number
opacity
number
default: 1 <= 1
type
required
Allowed value: video
asset_id
required

Key of a video asset in assets

string
>= 1 characters <= 200 characters
video_start_from_in_seconds

Offset into the source video where playback starts. Seconds.

number
0
decibel_adjustment

Gain in dB; 0 leaves the source as is

number
0
playback_rate

Speed multiplier; 1 is real time

number
default: 1
audio_fade_in_duration_in_seconds
number
0
audio_fade_out_duration_in_seconds
number
0
fade_in_duration_in_seconds

Visual fade-in length in seconds

number
0
fade_out_duration_in_seconds

Visual fade-out length in seconds

number
0
crop_left

Fraction of the item cropped from the left

number
0 <= 1
crop_top

Fraction of the item cropped from the top

number
0 <= 1
crop_right

Fraction of the item cropped from the right

number
0 <= 1
crop_bottom

Fraction of the item cropped from the bottom

number
0 <= 1
border_radius

Corner radius in composition pixels

number
0
rotation

Rotation in degrees

number
0
keep_aspect_ratio
boolean
default: true
assets
required

Media keyed by asset id. Every media item’s asset_id must be a key here.

object
key
additional properties
Any of:
object
id
required

Caller-chosen identifier; survives verbatim and is how other fields refer to it

string
>= 1 characters <= 200 characters
filename

Display name in the editor. Defaults to the last path segment of media_url.

string
>= 1 characters
mime_type

Defaults from the asset type and the media_url extension.

string
>= 1 characters
source_node_id

Canvas node whose output seeded this asset, when known. Read-only.

string
type
required
Allowed value: video
media_url
required

Durable https URL of the media the renderer fetches. Flora’s own asset URLs and any public https URL are accepted.

string format: uri
width
required

Native media width in pixels

number
height
required

Native media height in pixels

number
duration_in_seconds
required
number
has_audio_track
boolean
base_revision

The document revision read before editing. Required for Deck replacements. A differing observed revision returns revision_conflict; read again and reapply the intended edit. Deck revisions follow Liveblocks collaboration and undo and do not serialize simultaneous writers. Only meaningful alongside document; 0 is an empty Deck’s initial revision or a Timeline with no document yet.

integer
text

Replacement body for a notes node, whole-body: at most 20000 characters. Rejected on nodes that carry no annotation body.

string
<= 20000 characters
connect

Edges to create. Either endpoint may be a ref created by this same changeset. The canvas carries one edge per pair, so a duplicate pair is skipped with a warning.

Array<object>
<= 500 items
object
from
required

Source node reference

string
>= 1 characters <= 200 characters
to
required

Target node reference

string
>= 1 characters <= 200 characters
in

Target input slot, in the vocabulary the graph read reports: a modality word such as “image”, a named action or technique input, or “enabled” for the boolean gate. Omit to let the target take the edge by modality.

string
disconnect

Edges to remove, addressed by their endpoints as the graph read reports them

Array<object>
<= 500 items
object
from
required

Source node reference

string
>= 1 characters <= 200 characters
to
required

Target node reference

string
>= 1 characters <= 200 characters
in

Input slot of the edge to remove; omit to remove every edge between the pair

string
remove

Nodes to delete. Their edges and any group members go too. Removal is immediate and cannot be undone through the API.

Array<object>
<= 200 items
object
id
required

Node to delete: its short id or UUID

string
>= 1 characters <= 200 characters

Changeset applied.

Media type application/json
object
project_id
required

Project identifier

string
/^prj_\S+$/
canvas_url
required

Project canvas URL

string format: uri
created
required

Each add operation’s ref mapped to the ids of the node it created

object
key
additional properties
object
id
required

Short id the created node answers to from now on

string
>= 1 characters
node_id
required

Created node UUID

string
>= 1 characters
applied
required

What the transaction actually did

object
added
required

Nodes created

integer
updated
required

Update operations that changed at least one field

integer
connected
required

Edges created

integer
disconnected
required

Edges removed

integer
removed
required

Nodes deleted, including group members deleted with their frame

integer
revision
required

Change-detection marker of the canvas after this changeset, identical to the value the project graph endpoint reports

string
>= 1 characters
warnings
required

Operations that resolved but did not change what the caller may have expected, such as an update matching current state or a duplicate connect

Array<string>
Example
{
"project_id": "prj_abc123",
"created": {
"additionalProperty": {
"id": "n9",
"node_id": "7f6ae6da-4a0e-4a2f-9c6a-2c1c6b8d1f21"
}
},
"revision": "4f2c8ab19e3d7c05"
}