Campaigns / REST API

Update campaign workflow

Replace the complete delivery graph of an exact draft campaign. Read get-campaign first and pass its updated_at as expectedUpdatedAt. Saves the graph in Advanced Mode so old Easy Mode steps cannot return. Rejects stale edits and non-draft campaigns. Does not start the campaign or send anything. Use this to remove unwanted steps; update-workflow edits separate Agent Workflows. Campaign delivery graphs are distinct from Agent Workflows. Supply the complete nodes and edges to create-campaign or update-campaign-workflow. Start -> optional icp_scoring -> outreach. If scoring is present, all outreach paths must pass qualified; not_qualified ends without sending. Scoring must precede all sends or email campaign pushes. connection_request has accepted and no_response outputs. accepted continues to optional messages or End. no_response fires after wait_for_response_days and can go to optional cancel_invitation -> End, or an explicitly requested InMail/email fallback. Never withdraw an accepted invitation. message, template_message, enhanced_message and inmail have replied and no_reply outputs. Every replied output goes directly to End. no_reply waits reply_wait_days, then goes to an optional follow-up or End. Do not add a second delay for that same waiting period. Withdrawal, scoring, InMail, follow-ups and email destinations are optional; never add them unless requested. A connection-only graph wires accepted and no_response to End. instantly, smartlead and emailbison require credential_id and campaign_id for the selected external campaign. InMail requires a Sales Navigator sender; open profiles can use free InMail subject to provider limits. No cycles, dangling outputs or unreachable nodes. Every branch terminates at End. Saving creates a draft only; inspect the saved graph and obtain launch authorization before starting.

PUT /api/campaigns/{campaignId}/workflowDeterministic operation

Parameters

workspaceIdOptional · string
Optional workspace ID or slug. Required when this credential can access multiple workspaces and no workspace was configured on the client.
workflow_definitionRequired · object
Campaign delivery graphs are distinct from Agent Workflows. Supply the complete nodes and edges to create-campaign or update-campaign-workflow. Start -> optional icp_scoring -> outreach. If scoring is present, all outreach paths must pass qualified; not_qualified ends without sending. Scoring must precede all sends or email campaign pushes. connection_request has accepted and no_response outputs. accepted continues to optional messages or End. no_response fires after wait_for_response_days and can go to optional cancel_invitation -> End, or an explicitly requested InMail/email fallback. Never withdraw an accepted invitation. message, template_message, enhanced_message and inmail have replied and no_reply outputs. Every replied output goes directly to End. no_reply waits reply_wait_days, then goes to an optional follow-up or End. Do not add a second delay for that same waiting period. Withdrawal, scoring, InMail, follow-ups and email destinations are optional; never add them unless requested. A connection-only graph wires accepted and no_response to End. instantly, smartlead and emailbison require credential_id and campaign_id for the selected external campaign. InMail requires a Sales Navigator sender; open profiles can use free InMail subject to provider limits. No cycles, dangling outputs or unreachable nodes. Every branch terminates at End. Saving creates a draft only; inspect the saved graph and obtain launch authorization before starting.
expectedUpdatedAtRequired · string
See the input schema for this field.
campaignIdRequired · string
See the input schema for this field.
Request example
curl -X PUT "https://app.pipeline.help/api/campaigns/00000000-0000-4000-8000-000000000000/workflow" \
  -H "Authorization: Bearer $PIPELINE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"workflow_definition":{"nodes":[{"id":"00000000-0000-4000-8000-000000000000","type":"start","position":{"x":1,"y":1},"data":{}}],"edges":[{"id":"00000000-0000-4000-8000-000000000000","source":"example","target":"example"}]},"expectedUpdatedAt":"2026-01-01T00:00:00.000Z"}'
Full input schema
Input schema
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "workspaceId": {
      "type": "string",
      "minLength": 1,
      "description": "Optional workspace ID or slug. Required when this credential can access multiple workspaces and no workspace was configured on the client."
    },
    "workflow_definition": {
      "type": "object",
      "properties": {
        "nodes": {
          "minItems": 1,
          "maxItems": 500,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1
              },
              "type": {
                "type": "string",
                "enum": [
                  "start",
                  "end",
                  "website_visitor_trigger",
                  "new_connection_trigger",
                  "post_keyword_trigger",
                  "icp_scoring",
                  "connection_request",
                  "cancel_invitation",
                  "message",
                  "template_message",
                  "enhanced_message",
                  "inmail",
                  "delay",
                  "condition",
                  "is_connected",
                  "profile_visit",
                  "follow",
                  "like_post",
                  "post_comment_reply",
                  "research_agent",
                  "reply_agent",
                  "whatsapp_message",
                  "trykitt",
                  "findymail",
                  "leadmagic",
                  "icypeas",
                  "prospeo",
                  "quickenrich",
                  "instantly",
                  "smartlead",
                  "emailbison",
                  "webhook",
                  "exa",
                  "firecrawl",
                  "spider",
                  "http_request",
                  "google_sheets",
                  "slack_notification",
                  "openai_processor",
                  "claude_processor"
                ],
                "description": "Supported campaign delivery node types. Withdrawal is cancel_invitation, not cancel_connection_request. These are distinct from Agent Workflow play nodes."
              },
              "position": {
                "type": "object",
                "properties": {
                  "x": {
                    "type": "number"
                  },
                  "y": {
                    "type": "number"
                  }
                },
                "required": [
                  "x",
                  "y"
                ],
                "additionalProperties": false
              },
              "data": {
                "type": "object",
                "properties": {
                  "message_template": {
                    "type": "string"
                  },
                  "outputVariable": {
                    "type": "string"
                  },
                  "subject": {
                    "type": "string"
                  },
                  "post_url": {
                    "type": "string"
                  },
                  "keyword": {
                    "type": "string"
                  },
                  "reply_message": {
                    "type": "string"
                  },
                  "customInstructions": {
                    "type": "string"
                  },
                  "send_empty_request": {
                    "type": "boolean"
                  },
                  "only_open_profiles": {
                    "type": "boolean"
                  },
                  "icpThreshold": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 100
                  },
                  "thresholdOperator": {
                    "type": "string",
                    "enum": [
                      ">=",
                      ">",
                      "<=",
                      "<",
                      "=="
                    ]
                  },
                  "wait_for_response_days": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "reply_wait_days": {
                    "type": "number",
                    "exclusiveMinimum": 0
                  },
                  "credential_id": {
                    "type": "string"
                  },
                  "campaign_id": {
                    "type": "string"
                  }
                },
                "additionalProperties": {},
                "description": "Node config: icp_scoring {icpThreshold:0..100, thresholdOperator:\">=\", outputVariable:\"icp_score\"}; connection_request {send_empty_request:boolean, message_template:string, wait_for_response_days:positive number}; message/template_message {message_template:string, reply_wait_days:positive number}; inmail {subject:string, message_template:string, reply_wait_days:positive number, only_open_profiles:boolean}; cancel_invitation {}; delay {delay_type:\"minutes\"|\"hours\"|\"days\", delay_amount:positive number}; instantly/smartlead/emailbison {credential_id:string, campaign_id:string, field_mappings:object, custom_variables:object}. Templates use {{fieldName}} from supplied prospect customFields; nested templates must be rendered before import."
              }
            },
            "required": [
              "id",
              "type",
              "position",
              "data"
            ],
            "additionalProperties": {}
          }
        },
        "edges": {
          "maxItems": 2000,
          "type": "array",
          "items": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string",
                "minLength": 1
              },
              "source": {
                "type": "string",
                "minLength": 1
              },
              "target": {
                "type": "string",
                "minLength": 1
              },
              "sourceHandle": {
                "description": "Required for branching nodes: icp_scoring qualified/not_qualified; connection_request accepted/no_response; messages and InMail replied/no_reply. Omit for single-output nodes. One edge per output handle.",
                "type": "string"
              }
            },
            "required": [
              "id",
              "source",
              "target"
            ],
            "additionalProperties": {}
          }
        }
      },
      "required": [
        "nodes",
        "edges"
      ],
      "additionalProperties": false,
      "description": "Campaign delivery graphs are distinct from Agent Workflows. Supply the complete nodes and edges to create-campaign or update-campaign-workflow. Start -> optional icp_scoring -> outreach. If scoring is present, all outreach paths must pass qualified; not_qualified ends without sending. Scoring must precede all sends or email campaign pushes. connection_request has accepted and no_response outputs. accepted continues to optional messages or End. no_response fires after wait_for_response_days and can go to optional cancel_invitation -> End, or an explicitly requested InMail/email fallback. Never withdraw an accepted invitation. message, template_message, enhanced_message and inmail have replied and no_reply outputs. Every replied output goes directly to End. no_reply waits reply_wait_days, then goes to an optional follow-up or End. Do not add a second delay for that same waiting period. Withdrawal, scoring, InMail, follow-ups and email destinations are optional; never add them unless requested. A connection-only graph wires accepted and no_response to End. instantly, smartlead and emailbison require credential_id and campaign_id for the selected external campaign. InMail requires a Sales Navigator sender; open profiles can use free InMail subject to provider limits. No cycles, dangling outputs or unreachable nodes. Every branch terminates at End. Saving creates a draft only; inspect the saved graph and obtain launch authorization before starting."
    },
    "expectedUpdatedAt": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"
    },
    "campaignId": {
      "type": "string",
      "format": "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)$"
    }
  },
  "required": [
    "workflow_definition",
    "expectedUpdatedAt",
    "campaignId"
  ],
  "additionalProperties": false
}
See this operation inCLI MCP TypeScript SDK
API reference | Pipeline v2 preview