Campaigns

Intro

Endpoint: https://api.omnisend.com/api/campaigns

Manage marketing campaigns across email and SMS channels. Create campaigns, configure audience and content, then send immediately or schedule for later.

Campaign Status

StatusDescription
draftCampaign is being prepared and can be edited
scheduledCampaign is queued to send at a future time
startedCampaign is actively sending
pausedCampaign is undergoing verification — a ~60 min automated check of bounce/spam metrics before sending to the full audience
sentCampaign has finished sending to all recipients
canceledCampaign was explicitly canceled via the cancel endpoint
onHoldCampaign did not pass the automated content verification check and is held from sending. Requires review before it can be resent
errorCampaign encountered an error during sending
stoppedA/B test winner-selection phase has been halted via the stop endpoint. Can be resumed
expiredCampaign scheduling window has expired

Note: Only campaigns in draft status can be edited. Attempting to update a campaign in any other status returns 409 Conflict.

Campaign Types

TypeDescription
regularStandard one-time campaign
abTestSends two variants to a test audience, then sends the winner to the rest (see A/B Test Campaigns)
boosterRe-sends to contacts who did not open or click in a parent campaign (see Booster Campaigns)

Channels

Each campaign targets a single message channel, set at creation and immutable.

ChannelDescription
emailEmail campaign
smsSMS campaign

Content

Content is channel-specific. When creating or updating a campaign, provide content under the matching channel key.

Email Content (creation)

FieldRequiredDescription
subjectYesEmail subject line (max 250 chars)
senderNameYesSender display name (max 250 chars)
templateIDYesID of an existing email template to use as the email body
senderEmailNoSender email — must belong to a verified brand domain. Omit to use brand default
replyToEmailNoReply-to address — must be a verified email
preheaderNoPreview text shown after the subject line (max 250 chars)

Note: The templateID references an email template created via the Email Templates API. The template content is copied into the campaign at creation time. After creation, the campaign's email design can be edited using the contentID from the response via the Email Content API.

SMS Content (creation)

FieldRequiredDescription
messageYesSMS message body. Including compliance text, must not exceed 9 SMS segments (US/CA) or equivalent
compliance.stopKeywordTextYesSTOP opt-out text appended to messages for US/CA recipients (max 250 chars)
compliance.unsubscribeLinkTextYesUnsubscribe text appended for non-US/CA recipients (max 250 chars). Must include [[unsubscribe_link]]
imageIDNoImage ID from the Images API. Causes MMS delivery to US/CA; other regions receive SMS without image
isLinkShorteningEnabledNoAuto-shorten links in the message body. Default: true

Sending Strategies

Control when a campaign is sent using sendingSettings.strategy.

StrategyDescription
immediateCampaign sends as soon as the send endpoint is called.
scheduledCampaign sends at the specified scheduledAt time. Must be in the future and within one year from now

When strategy is scheduled, you can enable isTZOptimizationEnabled to deliver at the scheduled local time in each recipient's timezone.

Warning: sendingSettings uses full object replacement on update. When updating a scheduled campaign, provide the full object including strategy, scheduledAt, and isTZOptimizationEnabled — omitted fields will be reset to defaults.

Audience

Target specific subscriber segments using audience.

FieldDescription
includedSegmentIDsSegment IDs to include. Empty array or omitted = all subscribers
excludedSegmentIDsSegment IDs to exclude from the audience

Note: Included and excluded segment lists must not overlap. Overlapping IDs will return a validation error.

Campaign Lifecycle Actions

Beyond CRUD, the API provides these lifecycle actions:

ActionEndpointDescription
SendPOST /api/campaigns/{id}/sendStart sending or schedule the campaign
CancelPOST /api/campaigns/{id}/cancelCancel a scheduled, started, or paused campaign
CopyPOST /api/campaigns/{id}/copyCreate a draft copy with name prefixed "Copy of: "
Stop A/BPOST /api/campaigns/{id}/ab-test/stopHalt winner selection on a started A/B test
Resume A/BPOST /api/campaigns/{id}/ab-test/resumeResume winner selection on a stopped A/B test
Select winnerPOST /api/campaigns/{id}/ab-test/winnerManually pick the winning variant

Note: For started email campaigns, cancellation is best-effort — messages already in flight may still be delivered.

Note: The send endpoint returns 402 Payment Required when the campaign's audience exceeds the brand's current billing tier limits (e.g., email credits or subscriber count). A plan upgrade is required to proceed.

Booster Campaigns

A booster re-sends a message to contacts who did not open or click in a parent campaign. To create one, POST a campaign with type: "booster" and boosterSettings.campaignID pointing to the parent.

The setup flow depends on whether the parent campaign has already been sent.

Flow 1: Parent is already sent

Create the booster, set sendingSettings, then call /send — exactly like a regular campaign.

  1. POST /api/campaigns with type: "booster", boosterSettings.campaignID, sendingSettings, and optionally content
  2. POST /api/campaigns/{boosterId}/send

For email boosters, content falls back to the parent's snapshot if not provided — you only need to supply what differs (e.g. a new subject line). For SMS boosters, content.sms is required.

Flow 2: Parent is still in draft

Create the booster while the parent is being prepared. Instead of sendingSettings, provide a delay — how long after the parent sends the booster should go out. When the parent is sent, the booster is automatically scheduled.

  1. POST /api/campaigns with type: "booster", boosterSettings.campaignID, boosterSettings.delay, and optionally content
  2. Send the parent campaign — the booster is scheduled automatically at parent.sentAt + delay

Note: Do not provide sendingSettings for a draft-parent booster — it will be rejected. The booster's schedule is system-managed until the parent is sent.

boosterSettings fields

FieldRequiredDescription
campaignIDYesID of the parent campaign to boost
delayYes (Flow 2 only)How long after the parent sends to send the booster. Object with amount (integer) and unit ("h" or "d"). Max 240 hours
sendToYesnonOpeners (did not open) or nonClickers (did not click)

Note: boosterSettings.campaignID and the booster's channel are immutable after creation.

Scheduling limits

  • Flow 1sendingSettings.scheduledAt must be within 10 days from now
  • Flow 2boosterSettings.delay must not exceed 240 hours (10 days)

Warning: For email boosters, the sender domain must be verified before sending. The send endpoint returns 409 with error code sender_domain_unverified otherwise.

Listing boosters

GET /api/campaigns?type=booster&parentCampaignID={parentID}

Uniqueness

Each parent campaign supports at most one active booster. Creating a duplicate returns 409 Conflict. To switch channel, delete the existing booster first then create a new one — content of the deleted booster is not preserved.

Note: Newly created boosters appear with status: "draft" in the API.

A/B Test Campaigns

An A/B test campaign splits the audience into a test group and a remainder. Two variants (A and B) are sent to the test group, and after a decision period the winning variant is sent to the rest.

A/B test campaigns are email-only. When type is abTest, content is defined per variant under abTest.variants.{a,b}.content.email — the top-level content field is omitted.

A/B test settings

FieldRequiredDescription
testSizePercentYesPercentage of audience for the test phase (10–100)
winningMetricYes (unless send-all mode)openRate or clickRate
decisionTimeYes (unless send-all mode)How long to wait before selecting the winner. Object with amount (integer) and unit ("h" or "d")

When testSizePercent is 100, all recipients receive a variant and no winner is sent separately ("send-all mode"). In that case winningMetric and decisionTime are not required.

Variant content

Each variant requires subject and templateID at creation. Other email fields (senderName, senderEmail, replyToEmail, preheader) are optional.

FieldRequiredDescription
subjectYesEmail subject line for this variant
templateIDYesEmail template ID — copied into the variant at creation time
senderNameNoSender display name override
senderEmailNoSender email — must belong to a verified domain
replyToEmailNoReply-to address
preheaderNoPreview text shown after the subject line

Note: templateID is set at creation and cannot be changed via PATCH. After creation, the variant's email design is editable using the contentID returned in the response via the Email Content API.

Winner selection

After the decision time elapses, the system automatically selects the winning variant based on winningMetric. Alternatively, you can manually select a winner at any time using POST /api/campaigns/{id}/ab-test/winner with the variant's id (returned in abTest.variants.a.id / abTest.variants.b.id).

The result is available in abTest.result:

FieldDescription
winnerVariantIDCampaign ID of the winning variant
isManuallySelectedWhether the winner was manually picked
selectedAtTimestamp of winner selection

Stopping and resuming

While an A/B test is in started status, you can halt automatic winner selection with POST /api/campaigns/{id}/ab-test/stop (moves to stopped status). Resume with POST /api/campaigns/{id}/ab-test/resume.

Warning: abTest uses full replacement semantics on update. When patching A/B test settings or variant content, provide the full abTest block — omitted fields will be reset.

Example: Create an email campaign

curl --request POST \
     --url https://api.omnisend.com/api/campaigns \
     --header 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
     --header 'Omnisend-Version: 2026-03-15' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "name": "Summer Sale Announcement",
  "type": "regular",
  "channel": "email",
  "language": "en_US",
  "content": {
    "email": {
      "subject": "Summer Sale — Up to 50% Off!",
      "senderName": "My Store",
      "senderEmail": "[email protected]",
      "preheader": "Shop our biggest sale of the season",
      "templateID": "000000000000000000000001"
    }
  },
  "audience": {
    "includedSegmentIDs": ["111111111111111111111111"],
    "excludedSegmentIDs": ["222222222222222222222222"]
  },
  "sendingSettings": {
    "strategy": "scheduled",
    "scheduledAt": "2026-06-15T10:00:00Z",
    "isTZOptimizationEnabled": true
  }
}'

Creates a scheduled email campaign targeting a specific segment, with timezone optimization enabled.

Example: Update campaign email content

curl --request PATCH \
     --url https://api.omnisend.com/api/campaigns/000000000000000000000001 \
     --header 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
     --header 'Omnisend-Version: 2026-03-15' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "content": {
    "email": {
      "subject": "Updated Subject Line"
    }
  }
}'

Email content fields are partially updated — only the fields you include will change.

Example: Create an email booster (sent parent)

curl --request POST \
     --url https://api.omnisend.com/api/campaigns \
     --header 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
     --header 'Omnisend-Version: 2026-03-15' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "name": "Summer Sale Booster",
  "type": "booster",
  "channel": "email",
  "language": "en_US",
  "content": {
    "email": {
      "subject": "Still on: Summer Sale — Up to 50% Off!"
    }
  },
  "boosterSettings": {
    "campaignID": "000000000000000000000001",
    "sendTo": "nonOpeners"
  },
  "sendingSettings": {
    "strategy": "scheduled",
    "scheduledAt": "2026-06-17T10:00:00Z"
  }
}'

Only subject is overridden — all other content fields fall back to the parent's snapshot. Call /send when ready.

Example: Create an email booster (draft parent)

curl --request POST \
     --url https://api.omnisend.com/api/campaigns \
     --header 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
     --header 'Omnisend-Version: 2026-03-15' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "name": "Summer Sale Booster",
  "type": "booster",
  "channel": "email",
  "language": "en_US",
  "boosterSettings": {
    "campaignID": "000000000000000000000001",
    "sendTo": "nonOpeners",
    "delay": {
      "amount": 48,
      "unit": "h"
    }
  }
}'

No sendingSettings — the booster is automatically scheduled 48 hours after the parent is sent. Content inherits from the parent.

Example: Create an A/B test campaign

curl --request POST \
     --url https://api.omnisend.com/api/campaigns \
     --header 'Authorization: Omnisend-API-Key YOUR-API-KEY' \
     --header 'Omnisend-Version: 2026-03-15' \
     --header 'accept: application/json' \
     --header 'content-type: application/json' \
     --data '{
  "name": "Subject Line Test",
  "type": "abTest",
  "channel": "email",
  "abTest": {
    "settings": {
      "testSizePercent": 30,
      "winningMetric": "openRate",
      "decisionTime": {
        "amount": 4,
        "unit": "h"
      }
    },
    "variants": {
      "a": {
        "content": {
          "email": {
            "subject": "Summer Sale — Up to 50% Off!",
            "templateID": "000000000000000000000001"
          }
        }
      },
      "b": {
        "content": {
          "email": {
            "subject": "Your exclusive 50% discount is here",
            "templateID": "000000000000000000000001"
          }
        }
      }
    }
  },
  "audience": {
    "includedSegmentIDs": ["111111111111111111111111"]
  },
  "sendingSettings": {
    "strategy": "scheduled",
    "scheduledAt": "2026-12-15T10:00:00Z"
  }
}'

Creates an A/B test with 30% of the audience receiving variants. After 4 hours, the variant with the higher open rate is sent to the remaining 70%.

UTM Tracking

Each campaign has UTM parameters (source, medium, campaign) appended to links for analytics attribution. Read or update them via the dedicated UTM sub-resource.

FieldDefaultMax length
sourceomnisend250
mediumCampaign channel (email, sms, or push)250
campaigncampaign: <name> (<id>)250
EndpointDescription
GET /api/campaigns/{id}/utmRead current UTM tags (or synthesized defaults)
PUT /api/campaigns/{id}/utmReplace UTM tags (campaign must be in draft)

For A/B test campaigns, UTM tags are set per variant — the response and request body use variants.a / variants.b instead of tags. This allows each variant to be tracked independently in analytics.

Sending an empty string for any field resets it to the default shown above.

For a complete walkthrough, see How to configure UTM tags for campaigns.

See Also