Skip to main content
The Campaigns API (V5) lets you build campaigns incrementally rather than submitting a complete payload in a single request. Create a campaign in draft state, then add content, audience segments, trigger conditions, and scheduling across subsequent calls. Once the campaign is ready, validate its configuration, send test messages, and publish it. Include an Idempotency-Key (UUID v4) on all POST and PATCH requests to ensure safe retries. The X-MOE-Tenant-ID header (your Workspace ID) is optional — when omitted, the workspace is resolved from the Basic Auth credentials in the Authorization header.

Supported channels and delivery types

Channel support varies by operation:
OperationSupported channels
Create Campaign, Update Campaign, Validate CampaignEMAIL, PUSH (Android, iOS, Web)
Get Campaign, Search Campaigns, Get Campaign MetaEMAIL, PUSH, SMS, WHATSAPP, FACEBOOK, GOOGLE ADS, CONNECTORS
Test CampaignEMAIL, PUSH
Personalized PreviewEMAIL, PUSH, SMS
SMS campaign creation and update are not supported in V5. Use the MoEngage dashboard or the V1 API to create and manage SMS campaigns. Existing SMS campaigns can be retrieved, searched, and previewed via V5.
Supported delivery types:
  • ONE_TIME
  • PERIODIC
  • EVENT_TRIGGERED
  • BUSINESS_EVENT_TRIGGERED
  • DEVICE_TRIGGERED (Push only)
  • LOCATION_TRIGGERED (Push only)
  • BROADCAST_LIVE_ACTIVITY (Push iOS only)

Campaign lifecycle

1

Create

Start a draft with only the required fields: channel, campaign_delivery_type, and created_by. Add content, audience, and scheduling incrementally across subsequent update calls.
2

Update

Patch individual components as you refine the setup. Each submitted component is validated in full before the draft is updated.
3

Validate (optional)

Check whether the draft would pass publish-time validation without committing any changes. This step is optional but recommended before testing or publishing.
4

Test

Send a test message to specific users before going live. V5 supports two modes: inline mode, where you supply channel and campaign_content directly in the request without saving a draft, and draft mode, where you pass a draft_id to load content from a saved draft. Draft mode is new in V5.
5

Publish

Transition the draft to ACTIVE by sending { "status": "PUBLISH" } in a PATCH /v5/campaigns/{campaign_id} request. There is no separate publish endpoint. Publishing is a status transition sent through the Update Campaign endpoint.
6

Manage

Pause, resume, or stop a live campaign. Search your workspace and retrieve lightweight metadata across all campaigns.
If you are migrating from V1, here is what is new in V5:
  • Draft state: Campaigns now start as drafts, giving you full control over when to go live. Publish explicitly using PATCH /v5/campaigns/{campaign_id} with { "status": "PUBLISH" }.
  • Validate endpoint: V5 adds a dedicated validate step to check your campaign before publishing. There is no equivalent in V1.
  • Updated authentication header: The MOE-APPKEY header is replaced by X-MOE-Tenant-ID for passing your Workspace ID.

Campaign versioning

Campaign Versioning is opt-in per workspace. When it is turned on, publishing changes to a campaign that is already live creates a new campaign document with an incremented version_number. The campaign_id returned in API responses is the canonical identifier: it stays the same across versions so you can correlate drafts, search results, and analytics. Each version still has its own raw id (24-character ObjectId). For UI-focused behavior and version history in the dashboard, see Campaign versioning.

Endpoints

The Campaigns API consists of the following endpoints to manage your campaign lifecycle:
  • Create Campaign: Initializes a new Push or Email campaign in a DRAFT state using minimal required fields.
  • Get Campaign: Retrieves a single campaign in its full deparsed form, displaying its current state and configuration.
  • Update Campaign: Updates specific components of an existing draft or triggers the formal PUBLISH action to launch the campaign.
  • Validate Campaign: Safely runs a full publish-time validation check without modifying the draft or changing its state.
  • Update Campaign Status: Applies lifecycle transitions (STOP, PAUSE, RESUME) to campaigns that have already been published.
  • Search Campaigns: Searches for campaigns using granular filters, with the ability to explicitly include or exclude campaigns in draft state.
  • Get Campaign Meta: Fetches lightweight metadata, including daily cached reachability estimates for scheduled campaigns.
  • Test Campaign: Sends a test push or email to up to 10 users. Supports inline mode (pass channel and campaign_content directly) and draft mode (pass draft_id to load content from a saved draft). Draft mode is new in V5.
  • Personalized Preview: Returns a resolved preview of personalized campaign content for a specific user without sending a message.
Get Child Campaigns and Update Global Control Group are not yet available in V5. Continue to use the V1 Campaigns API for these operations.

FAQs

Create Campaign

Three fields are required at creation time: channel (PUSH or EMAIL), campaign_delivery_type, and created_by (the email of the user creating the campaign). All other components, including content, audience, scheduling, and delivery controls, are optional and can be added later using the Update Campaign endpoint.
Both approaches are supported. You can submit a minimal request with only the required fields and patch in the remaining components later, or you can include all sections in a single Create request. Any components included at creation time must meet the DRAFT_CREATE validation standards.
The request_id is an idempotency key scoped to campaign creation. For Push campaigns, the same request_id cannot be reused for one hour after a successful creation. For Email campaigns, the window is one day. If a creation attempt fails, you can retry immediately using the same request_id.
  • Push: ONE_TIME, PERIODIC, EVENT_TRIGGERED, BUSINESS_EVENT_TRIGGERED, DEVICE_TRIGGERED, LOCATION_TRIGGERED, BROADCAST_LIVE_ACTIVITY
  • Email: ONE_TIME, PERIODIC, EVENT_TRIGGERED, BUSINESS_EVENT_TRIGGERED
The API enforces two sets of limits:
  • Request rate: 5 per second, 25 per minute, 100 per hour.
  • Campaign creation: 5 successful per minute, 25 per hour, 100 per day.
Once 100 campaigns are successfully created within a day, subsequent requests are rejected regardless of the total number of API calls made.
MoEngage supports template expressions in content fields such as title, message, subject, and html_content. Use the following syntax to reference a user attribute at delivery time:
{{UserAttribute['First Name']}}
MoEngage also supports personalization using event attributes, content blocks, and the Content API. Refer to the MoEngage personalization documentation for the full syntax and configuration details for each source.
Campaigns created via the API are visible in the MoEngage dashboard under Campaigns, alongside campaigns created through the UI. Campaigns in DRAFT status can be updated via subsequent API calls.
No. custom_template_id and html_content are mutually exclusive in the Email campaign content payload. Submitting both fields in the same request returns a validation error. Use custom_template_id to reference a saved template from the MoEngage Email Template library, or use html_content to supply raw HTML directly.
Pass the segment reference inside segmentation_details.included_filters using filter_type: custom_segments. You can find the segment ID and name in the MoEngage dashboard under Segments.
{
  "segmentation_details": {
    "included_filters": {
      "filter_operator": "and",
      "filters": [
        {
          "filter_type": "custom_segments",
          "name": "{{segment_name}}",
          "id": "{{segment_id}}"
        }
      ]
    }
  }
}
To exclude a segment, use the same structure under excluded_filters. You can combine multiple filter types, such as user attributes, actions, and custom segments, in the same filters array using the filter_operator (and / or).

Get Campaign

Use the campaign_id path parameter, which is the 24-character ObjectId returned when you create or search for a campaign. Pass it in the GET /v5/campaigns/{campaign_id} request.
When campaign versioning is enabled, campaign_id is the stable canonical identifier that stays the same across all versions of a campaign. The id field is the raw ObjectId unique to each individual version document. Use campaign_id to correlate drafts, published campaigns, and analytics across versions.
The response reflects the campaign’s current lifecycle state, which can be DRAFT, SCHEDULED, ACTIVE, SENDING, PAUSED, SENT, STOPPED, or ARCHIVED.

Update Campaign

No. Component updates and the publish action are mutually exclusive. To update components, send the fields you want to change without a status key. To publish, send only { "status": "PUBLISH" }. Combining both in a single request returns a 400 Bad Request error.
  • Active: You cannot edit trigger_condition, segmentation_details, conversion_goal_details, the scheduling type, or the scheduling start date.
  • Scheduled: All fields can be edited except the scheduling type.
  • Stopped / Archived: No fields can be updated.
Updated content for Event-triggered campaigns is cached and can take up to 30 minutes to propagate to users.
No. Send only the components you want to update. However, if you are updating a field within a nested object, you must send the complete parent object. For example, to update the title of a push notification, include the full campaign_content object in the request body.
Component-level updates require the campaigns:create_manage scope. Publishing a campaign (sending { "status": "PUBLISH" }) requires the campaigns:create_manage_publish scope.
No. Publishing is a status transition sent through the Update Campaign endpoint. Send { "status": "PUBLISH" } as the request body in a PATCH /v5/campaigns/{campaign_id} request. The Update Campaign Status endpoint (POST /v5/campaigns/{campaign_id}/status) is a different endpoint that handles post-publish transitions, STOP, PAUSE, and RESUME, and does not accept PUBLISH.
No. The segmentation_details field cannot be updated for campaigns in ACTIVE state. To change the audience, stop the campaign and create a new one. See Which fields cannot be edited once a campaign is Active? for the full list of non-editable fields by campaign state.
It depends on the delivery type:
  • Event-triggered campaigns: Updated content is cached and can take up to 30 minutes to propagate to users after a successful update.
  • Periodic campaigns: The updated configuration applies from the next scheduled run.
  • One-time campaigns: Changes apply to any messages that have not yet been dispatched at the time of the update.
The campaign_id is returned in the data.id field of the Create Campaign response. You can also retrieve it using GET /v5/campaigns/{campaign_id} or by using the Search Campaigns endpoint to look up campaigns by name, status, channel, or delivery type.
Yes. The template_type field is part of campaign_content, which can be updated for campaigns in ACTIVE state. If you change the template type, include all required fields for the new template in the same request, as each template type has different required fields.
Yes. The platforms field in basic_details is not restricted for ACTIVE campaigns. Adding a platform extends delivery to that platform for future sends; removing a platform stops delivery to it.

Validate Campaign

No. The validate endpoint performs a read-only publish-time validation check (DRAFT_PUBLISH) without modifying the campaign or changing its status.
The endpoint always returns HTTP 200. Whether the campaign is valid or not is indicated in the response body through the valid field (true or false) and an errors array that lists any validation failures.
No. Unlike other POST and PATCH endpoints, the validate endpoint does not require an Idempotency-Key header.

Update Campaign Status

The endpoint supports three actions. Each action applies only to specific delivery types and requires the campaign to be in a valid source state:
ActionSupported delivery typesValid source states
STOPONE_TIMEACTIVE, SCHEDULED, PAUSED, SENDING
PAUSEPERIODIC, EVENT_TRIGGEREDACTIVE, SCHEDULED, SENDING
RESUMEPERIODIC, EVENT_TRIGGEREDPAUSED
No. This endpoint only applies lifecycle transitions to campaigns that are already published. To publish a campaign, use PATCH /v5/campaigns/{campaign_id} with the body { "status": "PUBLISH" }.
STOP is not valid for Periodic or Event-triggered campaigns. Use PAUSE to temporarily halt a running Periodic or Event-triggered campaign and RESUME to restart it. Attempting to STOP a Periodic campaign returns a 422 Unprocessable Entity error.
Yes. STOP is valid for One-time campaigns in SCHEDULED, ACTIVE, PAUSED, and SENDING states. If the campaign is in SENDING state, the action halts any remaining sends. Messages already dispatched before the stop is processed are still delivered.
  • Push: Periodic, Event-triggered, Device-triggered, and Location-triggered campaigns.
  • Email: Periodic and Event-triggered campaigns.
  • Both channels: Stopping a Scheduled One-time campaign.

Search Campaigns

No. Campaigns in DRAFT state are excluded from results unless you explicitly include DRAFT in the campaign_fields.status array. This preserves backward compatibility with existing integrations that do not expect draft rows in results.
The maximum is 15 campaigns per page. Use the limit and page parameters to paginate through results.
Check the flow_name and flow_id fields in the response. If these fields are present, the campaign is a node within a flow.
When campaign versioning is enabled, each published revision appears as a separate document in search results, all sharing the same campaign_id. You can filter by version_number in the campaign_fields object to narrow results to a specific version.
Include "SMS" in the campaign_fields.channels array. Matching results return channel: SMS and include SMS-specific fields, connector (connector type and name) and sender_name, in each campaign object. Note that SMS campaign creation and update are not supported in V5; this endpoint retrieves existing SMS campaigns only.
Set include_child_campaigns: true in the request body. Flow-node campaigns are excluded from results by default. When this flag is enabled, flow-node campaigns appear in the results with flow_id and flow_name populated. Periodic child campaigns also appear with a parent_id field when this flag is set.
Set include_archive_campaigns: true in the request body. Archived campaigns are excluded by default, regardless of whether ARCHIVED is listed in campaign_fields.status. You must set this flag to true to include them.
There is no sender_name filter in the search request. To find SMS campaigns from a specific sender, pass "SMS" in campaign_fields.channels to retrieve all SMS campaigns, then filter by the sender_name field returned in each result on the client side.

Get Campaign Meta

No. Reachability estimates are available only for scheduled campaigns: One-time, Business Event-triggered, and Event-triggered campaigns. The field is not populated for other campaign types.
No. Reachability is calculated once per day and cached for 24 hours. Multiple calls within the same day return the same cached value. The estimate may vary over time due to app installations, uninstalls, or changes in subscription status.
The endpoint supports Email, Push, SMS, WhatsApp, Facebook, Google Ads, and Connector-based campaigns.
If a campaign has been reviewed and rejected, the rejection_comment field appears in the meta response while the campaign remains in DRAFT status.

Test Campaign

Yes. Use inline mode by including channel and campaign_content directly in the test request. The content is not stored on the server. For Email inline tests, also include the connector object. To test using a saved campaign, use draft mode and pass the draft_id instead.
You can send a test to a maximum of 10 users at a time using the identifier_values array.
Yes. In draft mode, the server sends one test per platform, locale, and variation by default. To narrow the send, specify test_campaign_meta.platform (ANDROID, IOS, or WEB), locale_name, or variation in the request.
Yes. Use EMAIL as the identifier type and provide the recipient’s email address. The test will be sent, but the content will not be personalized with user profile data since there is no matching user record in MoEngage.

Push Campaigns

Use the MoEngage Templates API to list Push templates available in your workspace. The response includes a template_id for each template. Pass this value as custom_template_id in the campaign_content payload when creating or updating a Push campaign.
Required fields vary by template_type. Set the template_type in the basic_details object of your campaign content payload. The supported values for Android are BASIC, STYLIZED_BASIC, SIMPLE_IMAGE_CAROUSEL, IMAGE_BANNER_WITH_TEXT, TIMER, TIMER_WITH_PROGRESS_BAR, and Custom. For iOS, the supported values are BASIC, STYLIZED_BASIC, SIMPLE_IMAGE_CAROUSEL, and Custom.For the Custom template type, custom_template_id is required. For all other types, refer to the campaign_content schema in the Create Campaign reference for the full list of required and optional fields per template type.

SMS Campaigns

No. SMS campaign creation and update are not supported in V5. You can retrieve existing SMS campaigns using Get Campaign and Search Campaigns, and preview SMS content using Personalized Preview. To create and manage SMS campaigns, use the MoEngage dashboard or the V1 API.
The sender_name field in the campaign response carries the sender name configured for the campaign. This field is only populated for SMS campaigns. There is no sender_name filter in the Search Campaigns request. To find campaigns for a specific sender, retrieve all SMS campaigns and filter by sender_name on the client side.
The connector object in the campaign response contains the connector_type and connector_name for the campaign. For SMS campaigns, these fields identify the SMS delivery provider configured in your workspace.

Personalized Preview

The endpoint supports PUSH, EMAIL, and SMS. Pass the target channel in the channel field of the request body.
No. The endpoint is read-only. It resolves all personalization expressions against the specified user’s profile and returns the fully rendered content, but no message is delivered.
The endpoint resolves all standard MoEngage personalization sources: user attributes, event attributes, custom templates, content blocks, content APIs, and product sets. All Jinja expressions in the content are evaluated against the specified user’s profile.
Pass the triggering event’s attribute key-value pairs in the event_attributes object. The endpoint injects these values at resolution time to simulate how the content would render for a specific event. For example:
{
  "event_attributes": {
    "product_name": "Running Shoes",
    "product_price": "4999"
  }
}
In the content, reference these values using {{ event.product_name }}.
Pass custom_template_id in the campaign_content object, the same way you would in a Create Campaign request. The endpoint fetches and resolves the template, then returns the fully rendered output for the specified user.
No. The Personalized Preview endpoint only accepts inline content passed in campaign_content. It does not load content from a saved draft. To send a test message from a saved draft, use the Test Campaign endpoint with draft_id.