Campaigns

Create a campaign

Creates a campaign in draft status with one or more steps, assigned mailboxes, and (optionally) enrolled prospects. Start it later with the start endpoint. Email, LinkedIn, WhatsApp, Instagram and mixed (multichannel) campaigns are all created here; mailboxes are only required when the campaign sends email. Creating a campaign never sends anything — every message is paced later by the scheduler within that account's safe limits.

Required scope: campaigns:write.

Requires a unique Idempotency-Key request header so retries never duplicate.

post/campaigns

Request

  • Base URL: https://warmysender.com/api/v1
  • URL: https://warmysender.com/api/v1/campaigns
  • Auth: HTTP bearer

Headers

Idempotency-Keystring required

A unique key (e.g. a UUID) that makes this write safe to retry. Reusing a key returns the original result; reusing it with a different body returns 409.

Request body

namestring required

Campaign name.

descriptionstring

Optional description.

channel'email' | 'linkedin' | 'whatsapp' | 'instagram' | 'multichannel'

Campaign channel. A single-channel campaign may only carry steps of that channel (plus condition steps); mix channels only under "multichannel".

linkedinAccountIdstring uuid

LinkedIn account id (for linkedin/multichannel).

instagramAccountIdstring

Instagram account that sends this campaign. Required when the campaign carries Instagram steps. Needs an active Instagram seat.

whatsappAccountIdstring

WhatsApp number that sends this campaign. Required when the campaign carries WhatsApp steps. Needs an active WhatsApp seat.

timezonestring

Timezone the sending window and days are read in, as a name like "Europe/Paris" or "America/New_York". Leave it out to use your workspace timezone (Settings → Workspace), which is UTC unless you changed it.

dailySendLimitinteger

Daily send cap for the campaign.

sendingWindowStartinteger

Start hour (0–23) of the daily sending window.

sendingWindowEndinteger

End hour (0–23) of the daily sending window.

scheduleDaysinteger[]

Days of the week this campaign may send on. Numbers use 0=Sunday, 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday (Sunday is 0, not Monday). Day names such as "mon" or "monday" are accepted too and are the safest choice. Order and repeats do not matter. Leave it out for Monday–Friday [1,2,3,4,5]; an empty list is refused because a campaign with no sending days could never send.

stopOnReplyboolean

Stop a prospect's sequence when they reply.

stopOnBounceboolean

Stop on bounce.

stopOnUnsubscribeboolean

Stop on unsubscribe.

trackOpensboolean

Track opens.

trackClicksboolean

Track clicks.

opt_out_style'link' | 'reply' nullable

This applies to THIS campaign only — useful when one campaign writes to people in a different language from the rest of your outreach. Leave it out and the campaign keeps using your workspace setting; send null (or an empty string) to go back to following it. The choice itself works the same way it does for your workspace: How people opt out of your cold email. "link": The footer carries an Unsubscribe link — on your own verified tracking domain when you have one, otherwise on a shared WarmySender domain. "reply": The footer reads “Reply "unsubscribe" to opt out” and points back at the sending mailbox — no third-party link at all. Either way, a reply asking to unsubscribe is honored automatically and that person is never contacted again. Writing your own sentence? Put the word in quotes — like Reply “stop” — and a reply of just that word is honored too.

opt_out_textstring nullable

This applies to THIS campaign only — useful when one campaign writes to people in a different language from the rest of your outreach. Leave it out and the campaign keeps using your workspace setting; send null (or an empty string) to go back to following it. The wording rules are the same as your workspace setting: The sentence recipients click or reply to in order to opt out — written in your own words, 4–120 characters, one line. Send an empty string to go back to the default for your opt-out style ("Unsubscribe" for link, "Reply "unsubscribe" to opt out" for reply). Put {{opt_out}} inside an email or signature to place the sentence yourself.

company_addressstring nullable

The postal address shown in the footer of THIS campaign's emails — useful when you run campaigns for several companies from one workspace. Leave it out and the campaign keeps using your workspace address; send null (or an empty string) to go back to it.

startDatestring date-time

Optional scheduled start.

endDatestring date-time

Optional end date.

stepsobject[] required

Ordered steps. Each: { stepIndex, type (email|linkedin|instagram|whatsapp|condition), subject, bodyHtml, bodyText, delayDays, delayHours, isActive, … }. See the steps[] fields below for what an email body may contain and how to reuse a saved template. Condition steps additionally take the four condition fields below.

steps[].subjectstring

Subject line of an email step. Merge tags and spintax work here. Optional when the step reuses a template that carries one.

steps[].preheaderstring

Preview text shown after the subject line in the inbox.

steps[].bodyHtmlstring

HTML email body. Use simple HTML: <p>, <br>, <strong>, <em>, <u>, <a href>, <ul>, <ol>, <li>, <h2>, <h3>, <blockquote>, <hr>, <img src>. Inline styles are supported for font-family, font-size, color, background-color, line-height, margin-left and text-align — the same formatting the WarmySender editor produces. Plain text is fine too: send bodyText (or plain body_html without tags) and line breaks are formatted automatically. Scripts and event handlers are removed. Merge tags like {{first_name | default: 'there'}} and spintax {a|b|c} work in both. Keep formatting light: plain-looking emails get more replies.

steps[].bodyTextstring

Plain-text version of the email. Optional — when you send only HTML, the plain-text alternative is written for you. Merge tags like {{first_name | default: 'there'}} and spintax {a|b|c} work here too.

steps[].templateIdstring

Reuse one of your saved email templates for this step: its subject, preview text and body are copied in. Anything you also set on the step overrides the template's version. An unknown id (or one from another workspace) fails the whole request with not_found.

steps[].quotePreviousMessagesboolean

Quote the earlier email underneath a threaded follow-up, the way a hand-written reply does. Default true; only applies to follow-up steps that reply in the same thread.

steps[].instagramActionType'follow' | 'view_profile' | 'like_post' | 'comment_post' | 'send_dm' | 'wait' | 'wait_reply' | 'condition_replied'

Action for a step of type "instagram".

steps[].instagramDmTemplatestring

DM body for a send_dm step (supports {{firstName}} etc).

steps[].instagramCommentTemplatestring

Comment body for a comment_post step.

steps[].whatsappActionType'send_message' | 'wait' | 'wait_reply' | 'condition_replied'

Action for a step of type "whatsapp". WhatsApp outreach is reply-first: send_message is the only outbound action.

steps[].whatsappMessageTemplatestring

Message body for a send_message step (supports {{firstName}} etc).

steps[].conditionType'email_opened' | 'email_replied' | 'email_clicked' | 'email_bounced' | 'linkedin_accepted' | 'linkedin_replied' | 'has_linkedin_profile' | 'timeout'

Required on a step of type "condition": the signal the branch evaluates. Any other value is rejected with 400 validation_error.

steps[].conditionTrueNextinteger

Required on a condition step: stepIndex to jump to when the condition is met. Use -1 to end the sequence on the YES branch. Must point forward.

steps[].conditionFalseNextinteger nullable

stepIndex to jump to when the condition is NOT met. Omit (or use -1) to end the sequence on the NO branch — a first-class outcome, not an error. Must point forward.

steps[].conditionTimeoutDaysinteger

How long the condition waits before the NO branch is taken. Defaults to 3 days when omitted.

mailboxIdsstring[] required

Mailbox ids that send this campaign.

prospectIdsstring[]

Prospect ids to enroll on creation.

Response

Success

Changes

No recorded changes to this operation across all 1 revision of this API.