REFERENCE
API Reference
Complete reference for Floww's internal APIs, events, and data model.
The floww object is passed to every plugin lifecycle hook and provides access to all of Floww's internal systems. This page documents every available method, event, and data structure.
Canvas API
The floww.canvas namespace provides methods to manipulate the visual canvas — adding/removing nodes, controlling the viewport, and querying positions.
| Method | Returns | Description |
|---|---|---|
pan(x, y) |
void |
Pan the canvas by the given delta in world coordinates. |
panTo(x, y) |
void |
Center the viewport on the given world coordinates. |
zoom(level) |
void |
Set the zoom level. 1.0 is 100%. Range: 0.1 to 5.0. |
zoomBy(delta) |
void |
Adjust zoom by a relative amount (e.g., 0.1 to zoom in, -0.1 to zoom out). |
fitToView(padding?) |
void |
Auto-zoom and pan to fit all nodes in the viewport. Optional padding in pixels (default: 50). |
getViewport() |
Viewport |
Returns { x, y, width, height, zoom } describing the visible area in world coordinates. |
addNode(type, position, config?) |
Node |
Create a new node on the canvas. position is { x, y }. Returns the created Node object. |
removeNode(nodeId) |
boolean |
Remove a node and all its connected edges. Returns true if the node existed. |
addEdge(sourceNodeId, sourcePort, targetNodeId, targetPort) |
Edge |
Connect two ports. Returns the created Edge object. Throws if the connection would create a cycle. |
removeEdge(edgeId) |
boolean |
Remove a wire between two ports. Returns true if the edge existed. |
getSelectedNodes() |
Node[] |
Returns an array of currently selected nodes. |
selectNodes(nodeIds) |
void |
Set the selection to the given node IDs. |
clearSelection() |
void |
Deselect all nodes. |
Example
// Create two nodes and wire them together
const httpNode = floww.canvas.addNode('http-request', { x: 100, y: 200 }, {
method: 'GET',
url: 'https://api.example.com/data'
});
const parseNode = floww.canvas.addNode('json-parse', { x: 400, y: 200 });
floww.canvas.addEdge(httpNode.id, 'response', parseNode.id, 'input');
floww.canvas.fitToView(80);
Nodes API
The floww.nodes namespace handles node type registration and runtime interaction with node instances.
| Method | Returns | Description |
|---|---|---|
register(definition) |
void |
Register a custom node type. The definition object must include type, displayName, inputs, outputs, and execute. See Custom Node Development. |
registerAll(definitions[]) |
void |
Register multiple node types at once. |
unregister(type) |
boolean |
Remove a registered node type. Existing instances on the canvas become inert. |
get(nodeId) |
Node | null |
Get a node instance by its ID. Returns null if not found. |
getAll() |
Node[] |
Get all node instances in the current workflow. |
getByType(type) |
Node[] |
Get all node instances of a specific type. |
execute(nodeId) |
Promise<object> |
Trigger execution of a single node. Returns a promise that resolves with the node's outputs. |
validate(nodeId) |
ValidationResult |
Validate a node's configuration and input connections. Returns { valid: boolean, errors: string[] }. |
getRegisteredTypes() |
string[] |
List all registered node type identifiers (built-in and custom). |
Events
The floww.events namespace provides a pub/sub event bus for inter-system and inter-plugin communication.
Methods
| Method | Description |
|---|---|
on(event, callback) | Subscribe to an event. The callback receives an event data object. |
off(event, callback) | Unsubscribe a previously registered callback. |
once(event, callback) | Subscribe to an event, but auto-unsubscribe after the first invocation. |
emit(event, data) | Emit a custom event with associated data. |
Built-in events
| Event | Data shape | Emitted when |
|---|---|---|
node:added |
{ nodeId, type, position } |
A new node is placed on the canvas |
node:removed |
{ nodeId, type } |
A node is deleted from the canvas |
node:executed |
{ nodeId, outputs, duration, status } |
A node finishes execution (success or error) |
edge:connected |
{ edgeId, source: { nodeId, port }, target: { nodeId, port } } |
Two ports are wired together |
edge:disconnected |
{ edgeId, source: { nodeId, port }, target: { nodeId, port } } |
A wire is removed |
workflow:started |
{ workflowName, nodeCount } |
A workflow execution begins |
workflow:completed |
{ workflowName, duration, nodesExecuted } |
All nodes have finished successfully |
workflow:error |
{ workflowName, error, failedNodeId } |
A workflow-level error occurs |
myplugin:event-name. Built-in events use the namespace:action format.
Hooks
Hooks are synchronous interceptors that let you modify behavior at specific points in the execution pipeline. Unlike events (which are notifications after something happened), hooks run before the action completes and can modify or cancel it.
onNodeExecute
floww.hooks.onNodeExecute((nodeId, inputs, config) => {
// Inspect or modify inputs before the node runs
console.log(`About to execute ${nodeId}`);
// Return modified inputs, or return undefined to leave them unchanged
return {
...inputs,
timestamp: Date.now() // inject extra data
};
});
onWorkflowComplete
floww.hooks.onWorkflowComplete((result) => {
// Called after all nodes finish but before the UI updates
console.log(`Workflow done. ${result.nodesExecuted} nodes in ${result.duration}ms`);
// Send metrics to an external service
fetch('https://metrics.example.com/track', {
method: 'POST',
body: JSON.stringify(result)
});
});
onNodeError
floww.hooks.onNodeError((nodeId, error) => {
// Intercept errors before they reach the default handler
console.error(`Node ${nodeId} failed:`, error.message);
// Return a replacement error, or return null to suppress
if (error.message.includes('rate limit')) {
return new Error('Service rate-limited. Try again in 60 seconds.');
}
return error; // pass through unchanged
});
onCanvasChange
floww.hooks.onCanvasChange((change) => {
// Fires on any canvas modification: node add/remove/move, edge add/remove
// change.type: 'node:add' | 'node:remove' | 'node:move' | 'edge:add' | 'edge:remove'
console.log(`Canvas changed: ${change.type}`, change.data);
});
Data Model
These are the core data structures used throughout the Floww API. Shown in TypeScript-style interface notation for clarity.
Node
interface Node {
id: string; // Unique identifier (UUID)
type: string; // Registered node type (e.g., 'http-request')
displayName: string; // Human-readable name
position: { x: number; y: number };
config: Record<string, any>; // User-configured values
state: 'idle' | 'init' | 'validate' | 'execute' | 'complete' | 'error';
inputs: Port[];
outputs: Port[];
error?: {
message: string;
stack?: string;
};
lastExecuted?: string; // ISO 8601 timestamp
duration?: number; // Last execution time in ms
}
Edge
interface Edge {
id: string; // Unique identifier (UUID)
source: {
nodeId: string; // Source node ID
port: string; // Output port name
};
target: {
nodeId: string; // Target node ID
port: string; // Input port name
};
}
Port
interface Port {
name: string; // Port identifier
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'any';
description?: string;
optional?: boolean; // Default: false
}
Variable
interface Variable {
name: string; // Variable key
type: 'string' | 'number' | 'boolean' | 'object';
value: any; // Current value
sensitive: boolean; // If true, encrypted at rest and masked in UI
description?: string;
}
Viewport
interface Viewport {
x: number; // Left edge in world coordinates
y: number; // Top edge in world coordinates
width: number; // Visible width in world coordinates
height: number; // Visible height in world coordinates
zoom: number; // Current zoom level (1.0 = 100%)
}
Variables API
The floww.variables namespace provides access to workflow-level variables. Variables are key-value pairs that persist across executions and can be referenced from node configurations using the {{variableName}} syntax.
| Method | Returns | Description |
|---|---|---|
get(name) |
any |
Get the current value of a variable. Returns undefined if the variable does not exist. |
set(name, value) |
void |
Set a variable's value. Creates the variable if it doesn't exist. Emits variable:changed. |
getAll() |
Variable[] |
Get all variables in the current workflow as an array of Variable objects. |
delete(name) |
boolean |
Remove a variable. Returns true if it existed. |
subscribe(name, callback) |
() => void |
Watch a specific variable for changes. The callback receives { name, oldValue, newValue }. Returns an unsubscribe function. |
Example
// Set and read variables
floww.variables.set('apiBaseUrl', 'https://api.example.com');
floww.variables.set('maxRetries', 3);
const baseUrl = floww.variables.get('apiBaseUrl');
console.log(baseUrl); // 'https://api.example.com'
// Watch for changes
const unsubscribe = floww.variables.subscribe('maxRetries', (change) => {
console.log(`maxRetries changed from ${change.oldValue} to ${change.newValue}`);
});
// Later, stop watching
unsubscribe();
sensitive (like API keys) are encrypted at rest and their values are masked in the UI. Your plugin can still read them via floww.variables.get(), but this requires the variables:read permission.