Skip to main content
The MoEngage Offerings API allows you to manage offerings. You can create time-bound promotions and personalized content, update scheduling or targeting on existing offerings, list offerings for reporting or orchestration workflows, and list the personalization templates available for offering content.
If this API is not enabled for your account, contact your MoEngage Customer Success Manager (CSM) or the Support team to request enablement.

Offering lifecycle

An offering moves through different states automatically based on its scheduling window. There is no separate publish step — the offering goes live as soon as it is created, if the scheduling window is current.
StateMeaning
scheduledIndicates that the start_datetime is in the future. The offering is not yet eligible for decisioning.
activeIndicates that the current time is between start_datetime and expiry_datetime. The offering is eligible for decisioning.
expiredIndicates that the expiry_datetime has passed. The offering is no longer served and cannot be updated via the API.
archivedIndicates that the offering is manually archived from the dashboard. The offering is excluded from decisioning and cannot be updated via the API.
draftIndicates that the offering is not yet published. Offerings created via the API are never in draft state.

Endpoints

The Offerings API is a collection of the following endpoints:
  • List Offerings: Returns a paginated list of offerings, with filtering by ID, name, status, tags, date range, and creator.
  • Create Offering: Creates an offering in your workspace, including content, scheduling, segmentation, and variation configuration.
  • Update Offering: Partially updates an existing offering. Only the fields in the request body are changed.
  • List Templates: Returns a paginated list of the personalization templates available in your workspace. Use a template id as meta.templateId in offering content.
There is no endpoint to fetch a single offering by ID.

Idempotency

The Create and Update endpoints require an Idempotency-Key header (UUID v4). Reusing the same key within 24 hours returns the original response without re-running the operation, so retries on network failures are safe. Two conflict cases return 409:
  • DUPLICATE_IDEMPOTENCY_KEY - a request with the same key is already in progress. Wait for it to complete before retrying.
  • IDEMPOTENCY_CONFLICT - the key was already used within 24 hours with a different request body. Use a new UUID v4 key to submit the changed payload.
Use the same key only when retrying an identical request after a network failure or timeout. Use a new key for every logically distinct operation, including any request where the payload has changed.

FAQs

Getting Started

Yes. Make sure the Offer Decisioning feature is enabled for your workspace — if it isn’t, all API calls return 403 FORBIDDEN. Contact your MoEngage CSM or the Support team to request enablement. Before calling the Create Offering API, ensure the following workspace resources already exist:
  • Tags — create and manage them in the MoEngage dashboard under Settings → Advanced Settings → Tags. The tag IDs you pass in the tags array must already exist.
  • Offering attributes — configured under Offer Decisioning → Attributes in the dashboard. Pass their IDs in offering_attribute_configuration.
  • Personalization templates — list available templates using GET /v5/offers/templates and use the returned id as meta.templateId in your content.
In the MoEngage dashboard, go to Settings → Account → APIs. Your Workspace ID (App ID) is listed there. Your API key is in the Personalize tile on the same page. Use the Workspace ID as the Basic Auth username and the API key as the password.

Offering Lifecycle

An offering is always in one of five states: scheduled, active, expired, archived, or draft. See the Offering lifecycle section above for the full state table.
Currently, there is no dedicated GET /v5/offers/{offer_id} endpoint. To retrieve a specific offering, call List Offerings with the id query parameter set to the offering’s ID (including the offer_ prefix). This returns a single-item list for that offering.

Create Offering

The required top-level fields are: request_id, name, priority, delivery, created_by, scheduling (with both start_datetime and expiry_datetime), segment_info, offer_content, and variation_meta. All other fields — tags, capping_rules, conversion, imp_track_hours, offering_attribute_configuration — are optional and can be omitted.
It depends on the offering’s status and variation type:
  • While the offering is scheduled, the entire variation_meta object is editable.
  • Once the offering is active, the type and the variantsPerLocale key set are locked. For SMV, you can still update the smv_distribution split percentages and control_group.percentage. For DMV, only control_group.percentage is editable.
Editing a locked field returns IMMUTABLE_FIELD. The variation types are SMV (static allocation you control), DMV (dynamic allocation MoEngage optimizes), and CONTROL_ONLY.
You include all fields in a single Create request — there is no incremental or draft-building flow. The offering’s initial status is set from the scheduling dates: scheduled when start_datetime is in the future, active when the current time is within the scheduling window, or expired when start_datetime is already in the past.
Priority is an integer from 1 to 100 used by Decision Policies to rank eligible offerings for a user. Higher values rank the offering higher relative to others with lower priority. The exact ranking behavior also depends on any scoring formulas configured in the associated Decision Policy and any offering_attribute_configuration scores.
Offering names must be 5–100 characters and contain only letters, numbers, and underscores. Spaces, hyphens, and special characters are not allowed. Names must be unique within the workspace. Example of a valid name: Summer_Sale_Promo_2026.

Update Offering

You can update name, description, priority, tags, scheduling (within state-based rules below), segment_info, offer_content, capping_rules, is_global_control_enabled, imp_track_hours, offering_attribute_configuration, and conversion. You can also update variation_meta, but only within the status-based and type-based rules described below.
Fieldscheduledactive
scheduling.start_datetime✅ Editable❌ Locked
scheduling.expiry_datetime✅ Editable✅ Editable
conversion✅ Editable❌ Locked
offer_content✅ Editable✅ Editable
name, tags, priority, segment_info✅ Editable✅ Editable
variation_meta.type, variantsPerLocale✅ Editable❌ Locked
variation_meta.smv_distribution (SMV)✅ Editable✅ Editable
variation_meta.smv_distribution (DMV)✅ Editable❌ Locked
variation_meta.control_group.percentage✅ Editable✅ Editable
No. The Update endpoint is a PATCH — only the fields you include in the request body are changed. Omitted fields retain their current values. However, tags and offering_attribute_configuration are replaced entirely when included, not merged. To add a single tag, send the current tag list plus the new one. To remove all tags, send an empty array.
No. The API returns 403 with EXPIRED_OFFERING or ARCHIVED_OFFERING. Only offerings in active and scheduled states can be updated.
The offer_id (including the offer_ prefix) is returned in the data.id field of the Create Offering response. You can also retrieve it by calling List Offerings and filtering by name or status.

Idempotency

Use the same key only when retrying a request that failed due to a network error or timeout — where you are not sure whether the server processed the original request. Reusing the same key within 24 hours returns the original response without re-running the operation. Use a new key for every logically distinct operation, and for any retry where the request body has changed from the previous attempt.
The API returns 409 IDEMPOTENCY_CONFLICT. The original operation is not replayed and the new payload is not processed. Generate a new UUID v4 key and resubmit.
UUID v4 (for example, 550e8400-e29b-41d4-a716-446655440000). For automated workflows, generate a fresh UUID v4 per distinct operation. Do not derive the key from the request payload — if the payload is identical to a previous request, an intentional replay would return the cached response.