Campaigns / TypeScript SDK
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.
pipeline.updateCampaignWorkflowDeterministic operationParameters
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.
await pipeline.updateCampaignWorkflow({
"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",
"campaignId": "00000000-0000-4000-8000-000000000000"
})Full 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
}