The Actions API provides a centralized way to manage and customize actions when running CE.SDK headlessly on Node.js.
The Action Registry#
An action is a named function stored under a string id, such as history.undo, text.toggleBold, or zoom. You run actions by id, override what a built-in id does, add your own, or list what is available.
Registries are isolated per engine: actions registered on one CreativeEngine instance are not visible to another.
Running an Action#
Call run(id, ...args) to execute an action. It returns a Promise that resolves to the action’s result — most engine defaults resolve to true or false (changed or no-change), a few to null.
// Undo the last change.await engine.actions.run('history.undo');
// Nudge the current selection 10px to the right.await engine.actions.run('nudge', { dx: 10, dy: 0 });
// Set the fill color of the selected blocks.await engine.actions.run('fill.color', { color: { r: 1, g: 0, b: 0, a: 1 } });Selection verbs act on the current selection (engine.block.findAllSelected()); explicitly targeted actions take ids in their arguments. In a headless script there are no pointer events, so select blocks programmatically with engine.block.setSelected() before running a selection verb — without a selection it is a no-op and resolves to false.
Registering and Overriding#
Call register(id, fn) to add a new action or replace an existing one. Re-registering a default id overrides its behavior everywhere that id is used — including the engine’s own dispatches.
// Add your own command.engine.actions.register('myCompany.report', async (payload) => { await sendAnalytics(payload); return { ok: true };});
// Override a built-in: hide instead of destroy.engine.actions.register('selection.delete', () => { engine.block .findAllSelected() .forEach((id) => engine.block.setVisible(id, false));});An action you register runs directly in JavaScript, so arguments and results pass by reference — non-serializable values such as Buffers or callbacks work. The engine’s own dispatches and calls that reach an engine-default native action go through a JSON boundary, so values that cross it must be JSON-serializable.
Listing and Inspecting#
Call list(options?) to discover registered actions. It returns an array of { id, enabled, argSchema } objects. Pass a matcher glob to filter by id.
// Every registered action.const all = engine.actions.list();
// Just the engine defaults under the `text.` namespace.const textActions = engine.actions.list({ matcher: 'text.*' });// => [{ id: 'text.toggleBold', enabled: true, argSchema: '…' }, …]Use has(id) to test for an action, unregister(id) to remove a custom action or revert an overridden built-in to its default, and get(id) to read back a function you registered so you can call it synchronously (it returns undefined for engine-default native actions; use run for those).
engine.actions.has('zoom'); // trueconst report = engine.actions.get('myCompany.report'); // the raw fnAPI Methods#
The Actions API provides four methods:
register(actionId, handler)- Register an action function for a specific eventget(actionId)- Retrieve a registered action functionrun(actionId, ...args)- Execute a registered action with the provided arguments (throws if not registered)list(matcher)- Lists registered action IDs, optionally filtered by wildcard pattern
Getting Started#
Register actions after initializing the headless engine:
import CreativeEngine from '@cesdk/node';
const engine = await CreativeEngine.init({ // license: 'YOUR_CESDK_LICENSE_KEY',});
try { // Register an action engine.actions.register('actionType', async (...args) => { // Your custom implementation return result; });
// Execute a registered action await engine.actions.run('actionType', arg1, arg2);
// Or retrieve an action to call it later const action = engine.actions.get('actionType');
// List all registered actions const allActions = engine.actions.list();
// List actions matching a pattern const textActions = engine.actions.list({ matcher: 'text.*' });} finally { // Dispose the engine when your script is done engine.dispose();}Engine-Default Actions#
The engine seeds its registry with the editor’s command vocabulary. These run wherever the engine runs, including headless mode via @cesdk/node. Run any of them by id or override them. The full set is discoverable at runtime with list():
History#
history.undo- Undo the last changehistory.redo- Redo the last undone change
Lifecycle / selection#
selection.delete- Delete the selected blocksselection.duplicate- Duplicate the selected blocksselection.group- Group the selected blocksselection.ungroup- Ungroup the selected groupgroup.enter- Enter the selected group for editinggroup.exit- Exit the current groupselect- Select blocks by id (dispatched by the engine on click)selection.all- Select all blocks on the current pageselect.byType- Select all blocks of a given typeselection.parentOrDeselect- Select the parent group, or deselect if nonerename- Rename the selected blocklock.toggle- Toggle the lock state of the selected blocks
Transform / arrange#
nudge- Move the selection by a pixel delta ({ dx, dy })transform- Apply position/size/rotation to blocksresize- Resize the selection by a delta or scalescale- Scale the selection around an anchorrotate- Rotate the selection by degrees (absolute or relative)flip.horizontal- Flip the selection horizontallyflip.vertical- Flip the selection verticallyalign.horizontal- Align the selection horizontally (left/center/right)align.vertical- Align the selection vertically (top/center/bottom)distribute.horizontal- Distribute the selection horizontallydistribute.vertical- Distribute the selection verticallymatchSize- Match the size of the selection to a reference blockbringToFront- Bring the selection to the frontbringForward- Bring the selection forward one stepsendBackward- Send the selection backward one stepsendToBack- Send the selection to the backreorder.moveToIndex- Move the selection to a specific layer indexreparent- Move the selection under a new parent
Appearance#
opacity- Set the opacity of the selectionvisibility.toggle- Toggle visibility of the selectionblendMode- Set the blend mode of the selectionfill.color- Set the solid fill colorfill.toggle- Toggle the fill on or offcontentFillMode- Set the content fill mode (crop/cover/contain)stroke.toggle- Toggle the stroke on or offstroke.color- Set the stroke colorstroke.width- Set the stroke widthdropShadow.toggle- Toggle the drop shadow on or offdropShadow.color- Set the drop shadow colordropShadow.offset- Set the drop shadow offsetdropShadow.blur- Set the drop shadow blurblur.toggle- Toggle the block blur on or offblur.set- Set the block blur typeeffect.append- Append an effect to the selectioneffect.remove- Remove an effect by indexeffect.clear- Remove all effects from the selection
Crop / edit mode#
crop.enter- Enter crop mode (dispatched by the engine on double-click)crop.reset- Reset the crop to its defaultcrop.fillFrame- Fill the frame with the cropped contenteditmode.exit- Exit the current edit modetext.edit- Enter text editing (dispatched by the engine on double-click)
Text#
text.toggleBold- Toggle bold on the selected texttext.toggleItalic- Toggle italic on the selected texttext.fontSize- Set the font sizetext.align- Set the text alignment (left/center/right)text.case- Set the text case (normal/upper/lower/title)text.color- Set the text colortext.lineHeight- Set the line heighttext.letterSpacing- Set the letter spacingtext.list- Set the list style (none/unordered/ordered)text.typeface- Set the typeface
Pages#
page.add- Add a new pagepage.selectNext- Scroll to the next pagepage.selectPrevious- Scroll to the previous pagepage.remove- Remove a pagepage.duplicate- Duplicate a pagepage.size- Set a page’s sizepage.background.toggle- Toggle a page’s background fillpage.title.edit- Edit a page’s title (dispatched by the engine)
Scene / view#
scene.layout- Set the scene layout (free/stacks)scene.size- Set the scene sizezoom- Set the zoom level/factor around a pivotzoom.toBlock- Zoom the camera to fit a blockzoom.toPage- Zoom the camera to fit a pagezoom.autoFit.toggle- Toggle auto-fit zoom on an axispan- Pan the viewport by a delta
Video / timeline / playback#
selection.split- Split the selected clip at the playheadvideo.playPause- Toggle playback of the current pageplayback.seek- Seek playback to a timeduration- Set the duration of the selectiontrim.offset- Set the trim offset of the selectiontrim.length- Set the trim length of the selectionplaybackSpeed- Set the playback speed of the selectionvolume- Set the volume of the selectionmute.toggle- Toggle mute on the selectionloop.toggle- Toggle looping on the selectiontimeOffset- Set the time offset of the selectionanimation.in/animation.in.remove- Set or remove the in animationanimation.out/animation.out.remove- Set or remove the out animationanimation.loop/animation.loop.remove- Set or remove the loop animation
Canvas interaction primitives#
These exist for editor hosts that forward pointer input; they are rarely useful in a headless script.
drag.begin- Begin a drag gesture on blocksdrag.end- End a drag gesture on blockssecondaryAction- The secondary (context) action at a position
Overriding Engine Defaults Safely#
Some actions are dispatched by the engine itself in response to user input — for example select (on click), crop.enter and text.edit (on double-click), and page.title.edit. The engine reads the result of these within the same update, so an override of one of them must apply its effect synchronously.
// Synchronous override — runs in the same tick, so the engine sees the result.engine.actions.register('select', ({ ids }) => { applyMySelection(ids);});Registering Custom Actions with Custom IDs#
Beyond the predefined action types, you can register actions with custom IDs for your own application-specific needs:
// Register a custom actionengine.actions.register('myCustomAction', async data => { console.log('Custom action triggered with:', data); return { success: true, processedData: data };});
// Execute the custom action using runconst result = await engine.actions.run('myCustomAction', { someData: 'value' });
// Or retrieve it for conditional executionconst customAction = engine.actions.get('myCustomAction');if (customAction) { const result = await customAction({ someData: 'value' });}Discovering Registered Actions#
Use list() to get all registered action IDs or find actions matching a pattern:
// Get all registered action IDsconst registeredActions = engine.actions.list();console.log('Available actions:', registeredActions);
// Find actions matching a patternconst selectionActions = engine.actions.list({ matcher: 'selection.*' });console.log('Selection actions:', selectionActions);Differences from the Browser#
The actions API itself is identical across @cesdk/node, @cesdk/engine, and the prebuilt editor’s cesdk.actions — they all write to the same kind of registry. What differs on Node.js is which ids are pre-registered:
- Host UI actions are absent. The prebuilt browser editor registers convenience actions such as
saveScene,shareScene,importScene,exportScene,exportDesign,uploadFile,asset.delete,scene.create, and thevideo.*.checkSupportandtimeline.*actions. On Node.js these ids do not exist — use the engine APIs directly (for exampleengine.scene.saveToString()orengine.block.export()), or register your own implementations under the same ids. - Editor keyboard adapters are absent. Ids the browser editor layers on top of the engine defaults —
copy,cut,paste,zoom.toFit,group.enterOrExit,selection.nudgeUp/Down/Left/Right(and their…Extendedvariants),text.toggleUnderline,text.toggleStrikethrough,vectorPath.deleteNodeOrPoint- are not registered. The underlying engine defaults (nudge,group.enter,group.exit,zoom.toBlock, and so on) cover the same operations. - No dialogs or downloads. Engine defaults never open UI, so everything in the registry runs headlessly. Anything you register yourself should also avoid DOM APIs.
Prefer list() over hardcoding assumptions when your code needs to know whether an id is available in the current environment.