Skip to Content
API ReferenceVisual Builder API

Visual Builder API

The Visual Sequence Builder provides a drag-and-drop canvas for designing multi-step sequences and automations. These endpoints manage the canvas state, nodes, edges, and AI-powered generation.

All endpoints require authentication via Bearer token with the appropriate scope.


Canvas State

Load Canvas

GET /api/sequences/:sequenceId/canvas

Scope: sequences:read

Returns the full canvas state including all nodes and edges for a sequence.

Response (200)

{ "canvas": { "sequence_id": "uuid", "nodes": [ { "id": "node-1", "type": "email", "position": { "x": 250, "y": 100 }, "data": { "label": "Welcome Email", "config": { "subject": "Welcome aboard!", "templateId": "uuid" } } }, { "id": "node-2", "type": "delay", "position": { "x": 250, "y": 250 }, "data": { "label": "Wait 2 days", "config": { "delayDays": 2, "delayHours": 0 } } } ], "edges": [ { "id": "edge-1", "source": "node-1", "target": "node-2", "type": "default" } ] } }

Bulk Save Canvas

PUT /api/sequences/:sequenceId/canvas

Scope: sequences:write

Replaces the entire canvas state. This is a bulk operation that overwrites all nodes and edges.

Request Body

{ "nodes": [ { "id": "node-1", "type": "email", "position": { "x": 250, "y": 100 }, "data": { "label": "Welcome Email", "config": { "subject": "Welcome aboard!", "templateId": "uuid" } } }, { "id": "node-2", "type": "delay", "position": { "x": 250, "y": 250 }, "data": { "label": "Wait 2 days", "config": { "delayDays": 2, "delayHours": 0 } } } ], "edges": [ { "id": "edge-1", "source": "node-1", "target": "node-2", "type": "default" } ] }

Response (200)

{ "saved": true, "node_count": 2, "edge_count": 1 }

Error Codes

StatusDescription
400Invalid node or edge structure
404Sequence not found
403Insufficient permissions

Nodes CRUD

List Nodes

GET /api/sequences/:sequenceId/nodes

Scope: sequences:read

Returns all nodes for the specified sequence.

Response (200)

{ "nodes": [ { "id": "node-1", "sequence_id": "uuid", "type": "email", "position": { "x": 250, "y": 100 }, "data": { "label": "Welcome Email", "config": { "subject": "Welcome aboard!", "templateId": "uuid" } }, "created_at": "2026-03-28T10:00:00Z", "updated_at": "2026-03-28T10:00:00Z" } ] }

Create Node

POST /api/sequences/:sequenceId/nodes

Scope: sequences:write

Creates a new node on the canvas.

Request Body

{ "type": "email", "position": { "x": 250, "y": 100 }, "data": { "label": "Follow-Up Email", "config": { "subject": "Just checking in", "templateId": "uuid" } } }
FieldRequiredDescription
typeYesNode type (e.g. email, delay, condition, webhook_trigger, http_request, slack_message, crm_update, create_record, data_transform, schedule_trigger, crm_event_trigger)
positionYesCanvas position { x, y }
dataYesNode data including label and config

Response (201)

{ "node": { "id": "node-3", "sequence_id": "uuid", "type": "email", "position": { "x": 250, "y": 100 }, "data": { "label": "Follow-Up Email", "config": { "subject": "Just checking in", "templateId": "uuid" } }, "created_at": "2026-03-28T12:00:00Z", "updated_at": "2026-03-28T12:00:00Z" } }

Update Node

PATCH /api/sequences/:sequenceId/nodes/:nodeId

Scope: sequences:write

Updates an existing node. Supports partial updates.

Request Body

{ "position": { "x": 300, "y": 150 }, "data": { "label": "Updated Label", "config": { "subject": "New subject line" } } }

Response (200)

{ "node": { "id": "node-1", "sequence_id": "uuid", "type": "email", "position": { "x": 300, "y": 150 }, "data": { "label": "Updated Label", "config": { "subject": "New subject line", "templateId": "uuid" } }, "updated_at": "2026-03-28T14:00:00Z" } }

Delete Node

DELETE /api/sequences/:sequenceId/nodes/:nodeId

Scope: sequences:write

Deletes a node and all connected edges.

Response (200)

{ "deleted": true, "edges_removed": 2 }

Error Codes

StatusDescription
400Invalid node data
404Sequence or node not found
403Insufficient permissions

Edges CRUD

List Edges

GET /api/sequences/:sequenceId/edges

Scope: sequences:read

Returns all edges (connections between nodes) for the sequence.

Response (200)

{ "edges": [ { "id": "edge-1", "sequence_id": "uuid", "source": "node-1", "target": "node-2", "type": "default", "label": null, "created_at": "2026-03-28T10:00:00Z" } ] }

Create Edge

POST /api/sequences/:sequenceId/edges

Scope: sequences:write

Creates a connection between two nodes.

Request Body

{ "source": "node-1", "target": "node-3", "type": "default", "label": "Yes" }
FieldRequiredDescription
sourceYesID of the source node
targetYesID of the target node
typeNoEdge type (default, conditional). Defaults to default
labelNoDisplay label for the edge (e.g. "Yes", "No" for condition branches)

Response (201)

{ "edge": { "id": "edge-2", "sequence_id": "uuid", "source": "node-1", "target": "node-3", "type": "default", "label": "Yes", "created_at": "2026-03-28T12:00:00Z" } }

Delete Edge

DELETE /api/sequences/:sequenceId/edges/:edgeId

Scope: sequences:write

Removes a connection between nodes.

Response (200)

{ "deleted": true }

Error Codes

StatusDescription
400Invalid edge (source or target node not found)
404Sequence or edge not found
403Insufficient permissions

AI Generation

Generate Flow from Prompt

POST /api/sequences/:sequenceId/generate

Scope: sequences:write

Uses AI to generate a complete node-and-edge flow from a natural language description. The generated flow replaces the current canvas state.

Request Body

{ "prompt": "Create a 3-step onboarding sequence: send a welcome email, wait 2 days, then send a follow-up with a meeting link" }
FieldRequiredDescription
promptYesNatural language description of the desired flow

Response (200)

{ "nodes": [ { "id": "gen-node-1", "type": "email", "position": { "x": 250, "y": 50 }, "data": { "label": "Welcome Email", "config": { "subject": "Welcome to the team!", "bodyHint": "Warm welcome with key resources" } } }, { "id": "gen-node-2", "type": "delay", "position": { "x": 250, "y": 200 }, "data": { "label": "Wait 2 Days", "config": { "delayDays": 2, "delayHours": 0 } } }, { "id": "gen-node-3", "type": "email", "position": { "x": 250, "y": 350 }, "data": { "label": "Follow-Up with Meeting Link", "config": { "subject": "Let's schedule a quick call", "bodyHint": "Include calendar booking link" } } } ], "edges": [ { "id": "gen-edge-1", "source": "gen-node-1", "target": "gen-node-2", "type": "default" }, { "id": "gen-edge-2", "source": "gen-node-2", "target": "gen-node-3", "type": "default" } ] }

Error Codes

StatusDescription
400Prompt is empty or too long
404Sequence not found
422AI could not generate a valid flow from the prompt
429AI generation rate limited

AI Optimize

Get Optimization Suggestions

POST /api/sequences/:sequenceId/optimize

Scope: sequences:write

Analyzes the current canvas and returns AI-powered suggestions to improve the flow.

Request Body

No request body required. The endpoint reads the current canvas state.

Response (200)

{ "suggestions": [ { "type": "add_step", "title": "Add a condition check", "description": "Consider adding an email-opened condition after the first email to branch between engaged and unengaged contacts.", "priority": "high", "target_node_id": "node-1" }, { "type": "adjust_timing", "title": "Reduce delay to 1 day", "description": "Data shows higher engagement when follow-ups are sent within 24 hours.", "priority": "medium", "target_node_id": "node-2" }, { "type": "improve_content", "title": "Personalize subject line", "description": "Adding the contact's first name to the subject line typically increases open rates by 20%.", "priority": "low", "target_node_id": "node-3" } ] }

Suggestion Types

TypeDescription
add_stepSuggests adding a new node to the flow
remove_stepSuggests removing an unnecessary node
adjust_timingSuggests changing delay durations
improve_contentSuggests content improvements for email/message nodes
add_conditionSuggests adding a conditional branch
reorderSuggests reordering steps for better results

Error Codes

StatusDescription
404Sequence not found
422Canvas is empty — nothing to optimize

Sequence Fields for Visual Builder

When creating or updating sequences via the Sequences API, the following fields control builder behavior:

FieldTypeDescription
builder_mode"linear" | "visual"Whether the sequence uses the classic step list (linear) or the drag-and-drop canvas (visual). Default: "linear"
flow_type"sequence" | "automation"Whether this is a contact-enrollment sequence or an event-driven automation. Default: "sequence"

These fields are returned in all sequence list and detail responses. See also:

Last updated on