Build a Campaign over the API
This guide walks through the free primitive sequence: creating a complete campaign configuration via the API without triggering any server-side LLM calls. All five tools in this sequence (create_campaign, create_icp, create_persona, create_phase, create_workflow) are credit-free — you supply the data, the platform stores it.
Prerequisites
Section titled “Prerequisites”- An API key with
campaigns:write,icps:write, andworkflows:writescopes. See API Keys. - Your
workspaceId— callcampaignstack_whoamito retrieve it.
The sequence
Section titled “The sequence”create_campaign └── create_icp (criteria for lead scoring) └── create_persona (buyer archetype) └── create_phase (roadmap milestone) └── create_workflow (automation graph)All five calls are independent after create_campaign returns a campaignId.
-
Create the campaign
campaignstack_create_campaign— scopecampaigns:write{"workspaceId": "ws_abc123","title": "Series B Fintech Founders — Q3","goal": "Book discovery calls with CTOs at fintech companies that raised Series B in the last 18 months","description": "Outbound sequence targeting warm fintech leads via LinkedIn"}Returns:
{ "campaignId": "camp_xyz789", "title": "Series B Fintech Founders — Q3" }Use
campaignIdin every subsequent call. -
Define an ICP
campaignstack_create_icp— scopeicps:write— free, no LLMICP criteria control how leads are scored. Omit any field you don’t need — all criteria fields are optional.
{"campaignId": "camp_xyz789","titles": ["CTO", "VP Engineering", "Head of Technology"],"industries": ["Financial Services", "Fintech"],"seniorities": ["Director", "VP", "C-Suite"],"companySizes": ["11-50", "51-200", "201-500"],"keywords": ["Series B", "payments", "banking", "embedded finance"]}Returns:
{ "icpId": "icp_def456" }After leads are imported, call
campaignstack_trigger_icp_scoringto compute scores. Leads scoring above the workflow’s threshold (default 50, configurable viascoreMin) are fed to workflows automatically via thecampaign_poolsource. -
Create a persona
campaignstack_create_persona— scopecampaigns:write— free, no LLMPersonas are buyer archetypes used to tailor message copy. They are optional but improve
craft_messageoutput quality when you later draft outreach.{"campaignId": "camp_xyz789","name": "Technical Co-founder","description": "CTO or VP Eng at a recently funded fintech. Owns the build-vs-buy decision for infrastructure.","painPoints": ["Scaling payment rails without adding headcount","Compliance overhead from new banking regulations"],"goals": ["Ship faster without sacrificing reliability","Reduce operational cost of treasury ops"],"objections": ["We already have a vendor for this","Not the right time — just closed our round"]}Returns:
{ "personaId": "persona_ghi012" } -
Add a phase
campaignstack_create_phase— scopecampaigns:write— free, no LLMPhases are roadmap milestones that organize a campaign into sequential steps. At least one phase is recommended for clarity.
{"campaignId": "camp_xyz789","name": "Initial Outreach","description": "First-touch LinkedIn connection sequence targeting warm leads.","objectives": ["Connect with 50 qualified leads per week","Achieve >25% connection acceptance rate","Generate 5 discovery call bookings"],"phaseType": "outreach","order": 0}Returns:
{ "phaseId": "phase_jkl345" }Valid
phaseTypevalues:sourcing,outreach,content,intelligence,refinement. -
Create a workflow
campaignstack_create_workflow— scopeworkflows:write— free, no LLMBefore writing a graph, call
campaignstack_get_workflow_node_typesto discover all available node types, theirconfigHintshapes, and the required graph format. This is the authoritative source — node types are versioned and can change.{ }Returns
{ nodeTypes, graphShape, exampleGraph }.Once you have the vocabulary, author your graph:
{"campaignId": "camp_xyz789","name": "LinkedIn Connection Sequence","graph": {"nodes": [{"nodeType": "linkedin:profile_view","label": "View Profile","config": {}},{"nodeType": "flow:wait","label": "Wait 2 days","config": { "waitType": "duration", "durationMs": 172800000 }},{"nodeType": "linkedin:connection_request","label": "Send Connection Request","config": {"noteMode": "static","noteTemplate": "Hi {{lead:firstName}}, I noticed your work at {{lead:company}} — would love to connect."}}],"edges": [{ "sourceIndex": 0, "targetIndex": 1 },{ "sourceIndex": 1, "targetIndex": 2 }]}}Returns:
{ "workflowId": "wf_mno678", "nodeCount": 4 }nodeCountincludes the hidden anchor (source:entry) node that the platform prepends automatically.
What’s next
Section titled “What’s next”After the campaign is configured:
- Import leads — use
campaignstack_import_leads_csv,campaignstack_import_apollo_list, orcampaignstack_create_query_lead_listto populate the lead pool. - Score leads — call
campaignstack_trigger_icp_scoringwith theicpIdto compute match scores. - Enable the workflow — call
campaignstack_update_workflow_statuswithenabled: trueto start processing leads. - Monitor — use
campaignstack_get_workflow_statsandcampaignstack_list_leads_at_nodeto track progress. - Send feedback — call
campaignstack_submit_feedbackto report issues or request features directly from your agent.
Signal agent automation
Section titled “Signal agent automation”If you want signal-driven, event-triggered outreach (e.g. engage leads who just changed jobs or liked a post), use campaignstack_create_signal_agent instead of a manual workflow. Signal agents monitor LinkedIn signals and automatically enqueue matching leads into workflows. They are a separate concept from the manual campaign primitive sequence described in this guide.
Troubleshooting and feedback
Section titled “Troubleshooting and feedback”- Call
campaignstack_get_workflow_node_typesif your graph is rejected — theconfigHintfield shows the exact required shape for each node type. - Call
campaignstack_submit_feedbackwithcategory: "bug"orcategory: "feature_request"to report issues. Feedback goes directly to the CampaignStack team.