Skip to main content
POST
Create a draft campaign

Authorizations

Authorization
string
header
required

Your API token (af_…) as the Basic-auth username, with an empty password.

Body

application/json
campaignName
string
required

Display name of the campaign (1-200 characters, trimmed); also the stem of the CSV export filename.

Required string length: 1 - 200
listId
string

Id of the single Fuse list the campaign sources contacts from; mutually exclusive with listIds (exactly one of the two is required). The list must belong to your team and not be archived, else 404 LIST_NOT_FOUND.

listIds
string[]

Ids of 1-10 Fuse lists the campaign sources; mutually exclusive with listId. Every list must belong to your team and not be archived, else 404 LIST_NOT_FOUND. Take the ids from GET /business/lists with entityType=contactList — a campaign enrolls contacts. The lists are OR-joined into a deduplicated union: they are read in the order given and a contact that sits in two of them is enrolled once, up to the campaign's 10000-contact cap, after which the remaining lists are skipped.

Required array length: 1 - 10 elements

A Fuse list id (24-character hex ObjectId), as the id of a GET /business/lists row.

channels
enum<string>[]

Ordered channel scaffold: one empty sequence step (sequenceNumber 0, 1, 2 ...) is created per entry, 1-10 entries, default ["email"]. At most one linkedin_connection, and it must precede every linkedin_message (422 INVALID_CAMPAIGN_CHANNELS). Forbidden together with templateId, whose steps decide the channels.

Required array length: 1 - 10 elements

A step channel: email, linkedin_connection (connection request with optional note), linkedin_message (message to an accepted connection) or inmail (LinkedIn InMail, consumes the sender's InMail credits).

Available options:
email,
linkedin_connection,
linkedin_message,
inmail
campaignStartDate
string

ISO 8601 date-time before which nothing is sent (default: now); evaluated in timezone together with emailDays.

timezone
string
default:UTC

Time zone in which the daily sending window (09:00-17:00 local) and emailDays are evaluated; default UTC. Accepted values are IANA time zone names, for example America/New_York, Europe/Berlin, Asia/Kolkata or UTC. Do not send an abbreviation: EST is in the tz database but resolves to a fixed UTC-5 zone that never observes daylight saving, so name the region instead. A name the tz database does not know is rejected rather than silently evaluated as UTC.

emailDays
enum<string>[]

Weekdays on which sends may go out; default Monday to Friday. One of exactly: Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday — capitalised English names, nothing else. The days are OR-joined: a send that comes due is pushed forward to the next day named in the set, so a weekday you leave out is never used. 1-7 unique names; naming all seven removes the weekday restriction.

Required array length: 1 - 7 elements

An English weekday name with a capital first letter (Monday ... Sunday).

Available options:
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday
excludeLists
string[]

Ids of up to 10 Fuse people lists whose members are excluded from enrollment (a list that is also a source list is ignored here); default []. Take the ids from GET /business/lists with entityType=contactList. The lists are OR-joined: a contact is skipped when it appears in any one of them, matched on contact id, email address (case-insensitively) or LinkedIn URL. These ids are stored without an ownership check, so an id that is not one of your lists is accepted and silently excludes nobody — and a companyList here excludes nobody either, use excludeCompanyLists for that.

Maximum array length: 10

A Fuse list id (24-character hex ObjectId), as the id of a GET /business/lists row.

excludeCompanyLists
string[]

Ids of up to 20 company or people lists owned by your team whose companies' contacts are skipped at enrollment; default []. Take the ids from GET /business/lists — either entityType: a companyList contributes its companies, a contactList contributes the companies its contacts work at. The lists are OR-joined: a contact is skipped when its company appears in any one of them, matched by company id and by the company's web domain (personal-email domains are never used). Unlike excludeLists these ids are checked, so one that is unknown, archived or not your team's answers 422 EXCLUDE_COMPANY_LISTS_INVALID.

Maximum array length: 20

A Fuse list id (24-character hex ObjectId), as the id of a GET /business/lists row.

excludeContacted
enum<string>
default:none

Skips contacts your campaigns already reached: none keeps them, ever excludes anyone ever messaged, last_1_month / last_3_months / last_6_months / last_1_year exclude those messaged within that window; contacts with a pending send in an active campaign are always excluded. Default none.

Available options:
none,
ever,
last_1_month,
last_3_months,
last_6_months,
last_1_year
excludeEngagedContacts
boolean
default:false

When true, contacts who have already replied to one of your campaigns are excluded from enrollment. Default false.

isDynamic
boolean
default:false

When true, contacts added to the source lists after activation are enrolled automatically by a background refresh. Default false.

useLinkedinPosts
boolean
default:false

When true, each contact's recent LinkedIn posts are fetched at activation and fed to AI personalization (needs a LinkedIn URL on the contact). Default false.

When true, every email step appends a one-click unsubscribe footer (email channel only). Default true.

openRateTrackingEnabledAt
string | null

ISO 8601 timestamp that switches on the open-tracking pixel for outgoing emails (it records when tracking was enabled); null (default) keeps open tracking off.

sendOnlyToValidatedEmailsEnabledAt
string | null

ISO 8601 timestamp from which enrollment only accepts contacts whose email verified as valid (catch-all and never-verified uploaded addresses are skipped); null (default) also allows catch-all and never-verified uploaded emails. Applies to enrollment only.

delegates
string[]

User ids of teammates allowed to view and edit this campaign in the app besides you; default []. Take each id from the id of a GET /business/team/members row (a row whose id is null has no linked user account and cannot be a delegate). Access is OR-joined — any one of the listed users gets it — and there is no cap on how many you list. Nothing checks the ids against your team on the way in, and the app's delegate test is a plain membership check on this array that runs ahead of every team rule, so an id belonging to any real Fuse user — teammate or not — grants that user the access the owner has: opening the campaign, editing its settings and steps, activating it so it sends, and seeing it in their own campaign list. Only a well-formed id that matches no user grants nobody anything. The grant stops at the app: every campaign endpoint here resolves the token owner's own campaigns, so a delegate calling with their own key still gets 404.

A Fuse user id (24-character hex ObjectId) of a teammate, as the id of a GET /business/team/members row.

campaignType
enum<string>
default:manual

manual (default): you write every step's subject/body and the draft is ready to author immediately. ai-generated: prompt analysis and topic generation run in the background; poll GET /business/campaigns/{campaignId} until initializationStatus is completed before editing or approving.

Available options:
ai-generated,
manual
templateId
string | null

Id of a saved campaign template (GET /business/campaign-templates) whose steps are copied into the new campaign; its channels replace the channels field, so the two cannot be combined. null means no template. An unknown or inaccessible template answers 404 TEMPLATE_NOT_FOUND.

userPrompt
string | null

ai-generated only: free-text brief (up to 5000 characters) describing the offer and goal; the AI analyses it to derive the campaign topics. Forbidden for manual campaigns.

Maximum string length: 5000
websiteUrls
string[]

ai-generated only: up to 10 URLs whose page content grounds the generated copy. Forbidden for manual campaigns.

Maximum array length: 10

An absolute http(s) URL (up to 2000 characters).

Maximum string length: 2000
additionalInfo
string

ai-generated only: free text in your own words (up to 10000 characters) — product details, positioning, proof points; there is no fixed set of values. It is stored as one note on the knowledge profile built for this campaign, alongside websiteUrls, and grounds the generated copy. Forbidden for manual campaigns.

Maximum string length: 10000

The campaign's call-to-action link, honoured for either campaign type; null or an empty string means no link. Accepted values: one absolute URL whose scheme is http:// or https:// (up to 2000 characters); anything else, a bare domain or a mailto: link included, is rejected. The URL is inserted verbatim wherever a step's text uses {CTA Link} or one of its aliases {Calendar Link}, {cta_link}, {calendar_link}, {{calendarLink}}.

Maximum string length: 2000
writingStyleId
string | null

ai-generated only: id of one of your writing styles whose rules steer the generated copy; null or omitted uses your default style; an unknown id answers 404 WRITING_STYLE_NOT_FOUND. Forbidden for manual campaigns.

knowledgeHubId
string

ai-generated only: id of the knowledge hub (GET /business/knowledge-hubs) that grounds the generated content; omitted means your default hub; an unknown id answers 404 KNOWLEDGE_HUB_NOT_FOUND. Forbidden for manual campaigns.

Response

Success

campaignId
string
required

Id of the new campaign; use it for every other campaign endpoint.

status
enum<string>
required

A new campaign always starts as a draft in status initializing.

Available options:
initializing