Skip to main content
PUT
/
api
/
campaigns
/
{id}
/
sequence
/
nodes
/
{nodeId}
Update Node
curl --request PUT \
  --url https://app.puffle.ai/api/campaigns/{id}/sequence/nodes/{nodeId} \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "subject": "<string>",
  "body": "<string>",
  "body_html": "<string>",
  "signature": "<string>",
  "from_name": "<string>",
  "reply_to": "<string>",
  "cc": "<string>",
  "bcc": "<string>",
  "attachments": [
    "<unknown>"
  ],
  "include_message": true,
  "is_reply": true,
  "delay_days": 4503599627370495,
  "delay_hours": 4503599627370495,
  "delay_minutes": 4503599627370495,
  "ai_node": {
    "purpose": "<string>"
  }
}
'
{
  "node": {
    "id": "<string>",
    "campaign_id": "<string>",
    "position": 4503599627370495,
    "subject": "<string>",
    "body": "<string>",
    "body_html": "<string>",
    "signature": "<string>",
    "from_name": "<string>",
    "reply_to": "<string>",
    "cc": "<string>",
    "bcc": "<string>",
    "attachments": [
      "<unknown>"
    ],
    "include_message": true,
    "is_reply": true,
    "delay_days": 4503599627370495,
    "delay_hours": 4503599627370495,
    "delay_minutes": 4503599627370495,
    "ai_node": {}
  }
}
CLI:
puffle campaign sequence node update --id <id> --node-id <node-id>
puffle campaign sequence node update --id <id> --node-id <node-id> --subject <subject> --body <body> --body-html <body-html> --signature <signature> --from-name <from-name> --reply-to <reply-to> --cc <cc> --bcc <bcc> --attachments <attachments> --include-message <include-message> --is-reply <is-reply> --delay-days <delay-days> --delay-hours <delay-hours> --delay-minutes <delay-minutes> --ai-node <ai-node>

Overview

Partial update of a single sequence node. Only fields present in the body are applied. Draft campaigns only — on any other status the server returns 400 without writing. Immutable fields:
  • type — to change a node’s kind, delete it and add a new one with addSequenceNode.
  • position — to reorder, use the PATCH verb on the collection (moveSequenceNode).
  • campaign_id — set at creation.

Editable fields by node type

FieldApplies to
subjectemail
bodyconnection_request, message, email
include_messageconnection_request
is_replyemail
delay_days / delay_hoursdelay
ai_node.purpose / ai_node.output_typeai
AI extension fields are silently ignored unless the existing node type === "ai". If the extension row doesn’t exist yet, the server creates it; otherwise it’s updated in place.

AI agent notes

Two-step AI node setup. After addSequenceNode with { type: "ai" }, immediately PUT the same node with ai_node: { purpose, output_type } to populate the extension row. The builder UI does this in one motion; agents should do the same.Delay validation happens at launch. This endpoint does not enforce the “total delay must be 1 minute to 30 days” rule — that’s checked when you call POST /api/campaigns/{id}/launch. Read the campaign before launch and make sure the full draft sequence is intentional.Read-after-write. The response includes the fully-refreshed node with its AI extension flattened into node.ai_node. No separate GET needed.

Authorizations

Authorization
string
header
required

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

Path Parameters

id
string
required

Campaign UUID

nodeId
string
required

Sequence node UUID

Body

application/json
subject
string | null
body
string | null
body_html
string | null
signature
string | null
from_name
string | null
reply_to
string | null
cc
string | null
bcc
string | null
attachments
any[] | null
include_message
boolean | null
is_reply
boolean | null
delay_days
integer | null
Required range: 0 <= x <= 9007199254740991
delay_hours
integer | null
Required range: 0 <= x <= 9007199254740991
delay_minutes
integer | null
Required range: 0 <= x <= 9007199254740991
ai_node
object

Response

Node updated successfully.

node
object
required