Skip to content

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.

  • An API key with campaigns:write, icps:write, and workflows:write scopes. See API Keys.
  • Your workspaceId — call campaignstack_whoami to retrieve it.
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.

  1. Create the campaign

    campaignstack_create_campaign — scope campaigns: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 campaignId in every subsequent call.

  2. Define an ICP

    campaignstack_create_icp — scope icps:writefree, no LLM

    ICP 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_scoring to compute scores. Leads scoring above the workflow’s threshold (default 50, configurable via scoreMin) are fed to workflows automatically via the campaign_pool source.

  3. Create a persona

    campaignstack_create_persona — scope campaigns:writefree, no LLM

    Personas are buyer archetypes used to tailor message copy. They are optional but improve craft_message output 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" }
  4. Add a phase

    campaignstack_create_phase — scope campaigns:writefree, no LLM

    Phases 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 phaseType values: sourcing, outreach, content, intelligence, refinement.

  5. Create a workflow

    campaignstack_create_workflow — scope workflows:writefree, no LLM

    Before writing a graph, call campaignstack_get_workflow_node_types to discover all available node types, their configHint shapes, 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 }

    nodeCount includes the hidden anchor (source:entry) node that the platform prepends automatically.

After the campaign is configured:

  • Import leads — use campaignstack_import_leads_csv, campaignstack_import_apollo_list, or campaignstack_create_query_lead_list to populate the lead pool.
  • Score leads — call campaignstack_trigger_icp_scoring with the icpId to compute match scores.
  • Enable the workflow — call campaignstack_update_workflow_status with enabled: true to start processing leads.
  • Monitor — use campaignstack_get_workflow_stats and campaignstack_list_leads_at_node to track progress.
  • Send feedback — call campaignstack_submit_feedback to report issues or request features directly from your agent.

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.

  • Call campaignstack_get_workflow_node_types if your graph is rejected — the configHint field shows the exact required shape for each node type.
  • Call campaignstack_submit_feedback with category: "bug" or category: "feature_request" to report issues. Feedback goes directly to the CampaignStack team.