Skip to main content
POST
/
api
/
campaigns
Create Draft Campaign
curl --request POST \
  --url https://app.puffle.ai/api/campaigns \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "type": "<string>",
  "name": "<string>",
  "sender_account_ids": [
    "<string>"
  ],
  "skip_other_campaigns": true,
  "operating_hours": {},
  "daily_limit": 123,
  "stop_on_reply": true,
  "open_tracking": true,
  "signature": "<string>"
}
'
{
  "campaign": {
    "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "user_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
    "name": "<string>",
    "daily_limit": 4503599627370495,
    "stop_on_reply": true,
    "open_tracking": true,
    "signature": "<string>",
    "skip_other_campaigns": true,
    "operating_hours": {},
    "stats": {
      "total": 4503599627370495,
      "sent": 4503599627370495,
      "replied": 4503599627370495,
      "bounced": 4503599627370495,
      "completed": 4503599627370495,
      "timed_out": 4503599627370495,
      "connection_sent": 4503599627370495,
      "connected": 4503599627370495,
      "message_sent": 4503599627370495,
      "contacted": 4503599627370495
    },
    "created_at": "2023-11-07T05:31:56Z",
    "updated_at": "2023-11-07T05:31:56Z",
    "sequence_nodes": [
      {
        "id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
        "campaign_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
        "position": 4503599627370495,
        "subject": "<string>",
        "body": "<string>"
      }
    ]
  }
}
CLI:
puffle campaign create
puffle campaign create --type <type> --name <name> --sender-account-ids <sender-account-ids> --skip-other-campaigns --operating-hours <operating-hours> --daily-limit <daily-limit> --stop-on-reply --open-tracking --signature <signature>

Overview

Creates a draft campaign for one channel (linkedin or email) and seeds it with a two-node default sequence — either [connection_request, end] or [email, end]. The campaign is not yet launchable — the email body, leads, and any extra nodes still need to be added.

Prerequisites

You need at least one connected sender account that matches type:

Typical follow-up sequence

  1. updateCampaign — fill in sequence_nodes (for email, set subject and body; add more steps if needed)
  2. addLeadsToCampaign — add leads directly, or importLeadsFromListToCampaign from a saved list
  3. getCampaign with id — confirm the draft has sender accounts, pending leads, and non-empty sendable nodes
  4. launchCampaign — start sending

AI agent notes

Name uniqueness (409). Names are unique per user — retry with a suffix ("Q2 Enterprise Outreach (2)") if you hit a 409.Channel-specific fields. LinkedIn-only fields (skip_other_campaigns, operating_hours) on an email campaign and email-only fields (daily_limit, stop_on_reply, open_tracking, signature) on a LinkedIn campaign are silently ignored — not rejected. Send only the fields that apply.Default sequence is intentionally empty. Email: subject and body are empty strings. You must populate them via updateCampaign (or use the AI framework chat → generate-messages flow) before launchCampaign will succeed.Sender accounts must match type. A LinkedIn account id on an email campaign (or vice versa) returns 400. Filter GET /api/senders by type before picking.No leads yet. Creation seeds the sequence but adds no leads. launchCampaign on a campaign without leads exits immediately with status: "completed".

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Body

application/json
type
string
name
string
sender_account_ids
string[]
skip_other_campaigns
boolean
operating_hours
object
daily_limit
number
stop_on_reply
boolean
open_tracking
boolean
signature
string
{key}
any

Response

Campaign created as a draft with its seeded sequence.

campaign
object
required