Skip to main content
PUT
/
api
/
workflows
/
{id}
/
nodes
Bulk save workflow nodes + edges
curl --request PUT \
  --url https://app.puffle.ai/api/workflows/{id}/nodes \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "nodes": [
    {
      "id": "<string>",
      "type": "<string>",
      "config": {},
      "position_x": 123,
      "position_y": 123,
      "label": "<string>"
    }
  ],
  "edges": [
    {
      "id": "<string>",
      "source_node_id": "<string>",
      "target_node_id": "<string>",
      "source_handle": "<string>",
      "target_handle": "<string>",
      "condition": {}
    }
  ]
}
'
{
  "success": true,
  "nodeCount": 4503599627370495,
  "edgeCount": 4503599627370495
}

Overview

Replace the entire graph state for a workflow. The builder sends every node and edge on every save. The server upserts what’s in the payload and deletes anything missing. Also syncs the parent workflow’s trigger_config column from the signal_trigger node’s config.

AI agent notes

Idempotent. Safe to retry the same payload — upsert is keyed on node/edge id.Guard against accidental wipes. Sending nodes: [] is intentionally treated as a no-op on the delete step — the server keeps existing nodes untouched instead of wiping the graph. To actually clear the graph, delete the workflow.Partial failures. If the node upsert fails, the graph is unchanged (500 Failed to save nodes). If edges fail after nodes succeeded, the nodes are persisted (500 Failed to save edges) — retry with the same payload is safe.trigger_config auto-sync. The server reads any signal_trigger node’s config and mirrors it onto the parent workflow’s trigger_config column so the list view and activation validator stay in sync.Related: List workflow nodes + edges, Toggle workflow active/paused.

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Path Parameters

id
string<uuid>
required

Workflow UUID.

Pattern: ^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$

Body

application/json

Full graph state. The server upserts nodes and edges, then deletes anything not in the new set. Sending both arrays empty is intentionally NOT treated as a wipe — to protect against accidental saves, the server keeps existing graph state if nodes is empty.

nodes
object[]
required
edges
object[]
required

Response

Graph saved. Returns the final node + edge counts.

success
enum<boolean>
required
Available options:
true
nodeCount
integer
required
Required range: 0 <= x <= 9007199254740991
edgeCount
integer
required
Required range: 0 <= x <= 9007199254740991