Docs

Campaigns

What it does

Campaigns group a sales motion so members, products, and the ICP you are aiming at stay on one record.

Open Campaigns (/campaigns). campaign_type is outbound_marketing or internal_initiative. Status is draft, active, paused, completed, or archived. People on the motion, and the intake queue, are on Pipeline. Deals that belong to the motion are on Deals.

The list is a thin client. A signed-in person can create a campaign through the entity route. Agents change membership, products, and ICP with the tools below.

MCP tools

ToolScopeRole
campaign_listcampaigns:readList campaigns
campaign_members_listcampaigns:readMembers of one campaign
campaign_member_addcampaigns:writeAdd a contact or an account
campaign_member_updatecampaigns:writeChange member status and merge SDR metadata
campaign_products_listcampaigns:readProducts linked to the campaign
campaign_product_linkcampaigns:writeLink or unlink a product
campaign_icp_setcampaigns:writeAttach ICP profiles

campaign_member_update merges metadata_sdr. It does not replace that object blindly.

HTTP endpoints

MethodPathRole
GET/cockpit/api/campaignsList on this screen
POST/cockpit/api/entities/campaignsCreate from a signed-in session
GET, PATCH, DELETE/cockpit/api/entities/campaigns/:idDrawer read, update, delete
GET, POST/cockpit/api/campaigns/:id/productsProducts on the campaign
DELETE/cockpit/api/campaigns/:id/products/:productIdUnlink a product

Permissions

Token scopes come from one permission-set layer. Reads need campaigns:read. Membership, product, and ICP writes need campaigns:write. The screen uses the signed-in session.

Row access is RLS by creator. Admins see all rows. Members see their own.

Agent example

Call campaign_member_add with the campaign and either a contact or an account, not both as a guess.

{
  "tool": "campaign_member_add",
  "arguments": {
    "campaign_id": "campaign-1",
    "contact_id": "contact-1"
  }
}

Expected result: one member row. Listing with campaign_members_list returns that contact. Adding the same pair again does not create a second membership.

{
  "ok": true,
  "campaign_id": "campaign-1",
  "contact_id": "contact-1"
}