> ## Documentation Index
> Fetch the complete documentation index at: https://moengage.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Offering

> Create a new Offering in the workspace.


#### Rate Limit

The rate limit is 100 requests per minute, 300 requests per hour, and 600 requests per day per consumer.


## OpenAPI

````yaml /api/offerings/offerings.yaml post /v5/offers
openapi: 3.0.0
info:
  title: Offer Decisioning Public API - v5
  version: 5.0.0
  description: >
    The Offerings API lets you create, update, and list offerings for Offer
    Decisioning, and

    list the personalization templates available for offering content. For
    lifecycle, rate limits,

    idempotency, and error details, see the [Offerings
    Overview](/api/offerings/offerings-overview).
servers:
  - url: https://api-{dc}.moengage.com
    variables:
      dc:
        default: '01'
        description: >
          MoEngage data center identifier. Replace with your assigned DC number.
          Full example: https://api-01.moengage.com
security: []
paths:
  /v5/offers:
    post:
      tags:
        - Public Offerings
      summary: Create Offering
      description: |
        Create a new Offering in the workspace.
      operationId: createPublicOffering
      parameters:
        - name: Idempotency-Key
          in: header
          required: true
          schema:
            type: string
            format: uuid
          description: >
            UUID v4 idempotency token. Submitting the same key within 24 hours
            returns the original `201 response` without re-creating the
            Offering. A different body hash on the same key returns `409
            IDEMPOTENCY_CONFLICT`. A concurrent in-progress request with the
            same key returns `409 DUPLICATE_IDEMPOTENCY_KEY`.
        - name: X-MOE-Request-Id
          in: header
          required: false
          schema:
            type: string
            format: uuid
          description: >
            Client-supplied trace ID (UUID v4). Echoed back in the
            X-MOE-Request-Id response header. Use this to correlate client
            requests with server-side logs.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/ClientOfferCreateRequest'
            examples:
              jsonSingleVariantNoCapping:
                summary: 'JSON: 1 variant, no control group, no capping'
                value:
                  name: Summer_Sale
                  description: Summer sale discount offers
                  priority: 50
                  delivery: scheduled
                  created_by: john.doe@example.com
                  scheduling:
                    start_datetime: '2026-07-16T00:00:00Z'
                    expiry_datetime: '2026-07-16T23:59:00Z'
                    timezone: Asia/Kolkata
                  segment_info:
                    filters:
                      included_filters:
                        filter_operator: and
                        filters:
                          - filter_type: custom_segments
                            name: level_0_for_automation
                            id: 6a572827fad010a3318a1bc1
                  offer_content:
                    content_1:
                      type: json
                      value: '{"discount":"10%"}'
                  variation_meta:
                    type: SMV
                    variantsPerLocale:
                      - Variant_A
                    control_group:
                      is_enabled: false
                      percentage: 0
                    smv_distribution:
                      split:
                        Variant_A: 100
                  capping_rules: {}
                  is_global_control_enabled: false
                  imp_track_hours: 36
              jsonMultiVariantWithCapping:
                summary: >-
                  JSON: 2 variants, control group enabled, overall + user-level
                  capping (scheduled delivery)
                value:
                  name: Summer_Sale
                  description: Summer sale discount offers
                  priority: 50
                  delivery: scheduled
                  created_by: john.doe@example.com
                  scheduling:
                    start_datetime: '2026-07-16T00:00:00Z'
                    expiry_datetime: '2026-07-16T23:59:00Z'
                    timezone: Asia/Kolkata
                  segment_info:
                    filters:
                      included_filters:
                        filter_operator: and
                        filters:
                          - filter_type: custom_segments
                            name: level_0_for_automation
                            id: 6a572827fad010a3318a1bc1
                  offer_content:
                    locales:
                      '0':
                        variations:
                          Variant_A:
                            content_1:
                              type: json
                              value: '{"discount":"10%"}'
                          Variant_B:
                            content_1:
                              type: json
                              value: '{"discount":"20%"}'
                  variation_meta:
                    type: SMV
                    variantsPerLocale:
                      - Variant_A
                      - Variant_B
                    control_group:
                      is_enabled: true
                      percentage: 10
                    smv_distribution:
                      split:
                        Variant_A: 50
                        Variant_B: 50
                  capping_rules:
                    overall:
                      enabled: true
                      limit_value: 1
                      limit_schedule: DAILY
                    user_level:
                      enabled: true
                      limit_value: 15
                      limit_schedule: MONTHLY
                  is_global_control_enabled: true
                  imp_track_hours: 36
              templateDmvWithCapping:
                summary: >-
                  Template: 2 variants (DMV), control group enabled,
                  user_attributes segment, capping (scheduled delivery)
                value:
                  name: Summer_Sale
                  description: Summer sale discount offers
                  priority: 50
                  delivery: scheduled
                  created_by: john.doe@example.com
                  scheduling:
                    start_datetime: '2026-07-16T11:00:00Z'
                    expiry_datetime: '2026-07-16T23:59:00Z'
                    timezone: Asia/Kolkata
                  segment_info:
                    filters:
                      included_filters:
                        filter_operator: and
                        filters:
                          - filter_type: user_attributes
                            data_type: string
                            name: Name
                            value:
                              - David
                            case_sensitive: false
                            operator: in
                            negate: false
                          - filter_type: user_attributes
                            data_type: string
                            name: last_purchase_category
                            value:
                              - Electronics
                            case_sensitive: false
                            operator: in
                            negate: false
                      excluded_filters:
                        filter_operator: and
                        filters:
                          - filter_type: user_attributes
                            data_type: string
                            name: city
                            value:
                              - Detroit
                            case_sensitive: false
                            operator: in
                            negate: false
                  offer_content:
                    locales:
                      '0':
                        variations:
                          Variant_A:
                            content_1:
                              type: template
                              value:
                                id: card_notification_01
                                title: Welcome to Your Dashboard
                                description: >-
                                  This is a generic description field supporting
                                  standard text notification content.
                                ctaUrl: https://example.com/destination-pathv2
                                darkModeImageUrl: >-
                                  https://example.com/assets/dark-mode-featurev2.png
                                lightModeImageUrl: >-
                                  https://example.com/assets/light-mode-featurev2.png
                                darkModeBackgroundImageUrl: https://example.com/assets/dark-mode-bgv2.png
                                ariaLabel: >-
                                  Alternative text description for screen
                                  readers
                              meta:
                                templateId: feature_hero_slide
                          Variant_B:
                            content_1:
                              type: template
                              value:
                                id: card_notification_01
                                title: Welcome to Your Dashboard
                                description: >-
                                  This is a generic description field supporting
                                  standard text notification content.
                                ctaUrl: https://example.com/destination-path
                                darkModeImageUrl: >-
                                  https://example.com/assets/dark-mode-feature.png
                                lightModeImageUrl: >-
                                  https://example.com/assets/light-mode-feature.png
                                darkModeBackgroundImageUrl: https://example.com/assets/dark-mode-bg.png
                                ariaLabel: >-
                                  Alternative text description for screen
                                  readers
                              meta:
                                templateId: feature_hero_slide
                  variation_meta:
                    type: DMV
                    variantsPerLocale:
                      - Variant_A
                      - Variant_B
                    control_group:
                      is_enabled: true
                      percentage: 5
                  capping_rules:
                    overall:
                      enabled: true
                      limit_value: 1
                      limit_schedule: DAILY
                    user_level:
                      enabled: true
                      limit_value: 1
                      limit_schedule: WEEKLY
                  is_global_control_enabled: true
                  imp_track_hours: 36
      responses:
        '201':
          description: Offering created successfully.
          headers:
            X-MOE-Request-Id:
              schema:
                type: string
              description: Echoed trace ID (from request header or server-generated).
            X-RateLimit-Limit:
              schema:
                type: integer
                example: 100
              description: Maximum requests allowed in the current window.
            X-RateLimit-Remaining:
              schema:
                type: integer
              description: >-
                Requests remaining in the current window before rate limiting
                applies.
            X-RateLimit-Reset:
              schema:
                type: integer
              description: UTC epoch second when the current rate-limit window resets.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/PublicOfferCreateResponse'
        '400':
          description: >
            Validation errors. All errors are collected before returning, so a
            single 400

            response may contain multiple `details` entries. Possible error
            codes:

            - `REQUIRED_FIELD_MISSING` — a required field is absent (e.g.
            missing `variation_meta`, `name`, `scheduling.start_datetime`). The
            `target` field identifies the missing field.

            - `INVALID_TYPE` — a field has the wrong type or format (e.g.
            `content_1.value` is not a JSON object when `type` is `template`; or
            `scheduling.start_datetime` is not a valid ISO 8601 datetime with
            UTC "Z" suffix).

            - `OUT_OF_RANGE` — numeric field outside its allowed range (e.g.
            `priority` outside 1–100, `control_group.percentage` outside 1–99).

            - `INVALID_ENUM_VALUE` — enum field has an unrecognised value.

            - `INVALID_OFFER_NAME` — `name` contains characters other than
            alphanumeric characters and underscores. Spaces and hyphens are not
            allowed.

            - `INVALID_SCHEDULING` — `expiry_datetime` is not after
            `start_datetime`; `start_datetime` is in the past; or
            `expiry_datetime` is less than 10 minutes in the future.

            - `INVALID_TIMEZONE` — `scheduling.timezone` is present but not a
            valid IANA timezone name (e.g. `Asia/Kolkata`, `America/New_York`,
            `UTC`).

            - `SPLIT_KEY_MISMATCH` — keys in `smv_distribution.split` do not
            match `variantsPerLocale`.

            - `INVALID_SPLIT` — values in `smv_distribution.split` do not sum to
            exactly 100. Adjust the percentages so the total equals 100.

            - `VARIANT_COUNT_MISMATCH` — count of variants in `offer_content`
            does not match `variantsPerLocale`.

            - `INVALID_TEMPLATE_ID` — `meta.templateId` refers to a template ID
            not registered in the workspace.

            - `MISSING_TEMPLATE_FIELD` — a required field (per the template's
            config) is missing or blank in the `value` map.
              The `target` field will be `offer_content.locales.<locale>.variations.<variant>.content_1.value.<fieldKey>`.
            - `DUPLICATE_OFFER_NAME` — `name` matches an existing non-archived
            offering in this workspace. Offering names must be unique. Choose a
            different name.

            - `INVALID_TAG_ID` — one or more tag IDs in `tags` do not exist in
            this workspace. Create the tags first via the dashboard before
            referencing them here.

            - `REVENUE_FIELDS_INCOMPLETE` — `conversion.primary.revenue_amount`
            or `conversion.primary.revenue_currency` is missing when
            `is_revenue_tracking` is true.

            - `INVALID_CURRENCY_CODE` — `conversion.primary.revenue_currency` is
            not a valid ISO 4217 code (e.g. use "USD", "EUR", "INR").

            - `MISSING_IDEMPOTENCY_KEY` — `Idempotency-Key` header is absent.
            Add the header with a UUID v4 value.

            - `INVALID_IDEMPOTENCY_KEY` — `Idempotency-Key` is present but not a
            valid UUID v4. Use a standard UUID v4 format (e.g. <uuid-v4>).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_FAILED
                  message: Request validation failed.
                  doc_url: >-
                    https://www.moengage.com/docs/api/offerings/offerings-overview
                  details:
                    - code: REQUIRED_FIELD_MISSING
                      target: variation_meta
                      message: variation_meta is required.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                    - code: INVALID_SCHEDULING
                      target: scheduling
                      message: expiry_datetime must be after start_datetime.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                    - code: INVALID_TEMPLATE_ID
                      target: >-
                        offer_content.locales.0.variations.Variant_A.content_1.meta.templateId
                      message: >-
                        Template 'app_large' is not registered in this
                        workspace.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                    - code: MISSING_TEMPLATE_FIELD
                      target: >-
                        offer_content.locales.0.variations.Variant_A.content_1.value.cta_url
                      message: >-
                        Field 'cta_url' is required by the template but is
                        missing or blank.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                response_id: resp_<trace-id>
        '401':
          description: >
            Authentication failure. Two sources produce 401 on this endpoint:

            - **Gateway (APISIX)** — credentials missing or invalid. Returns
            `Content-Type: text/plain`
              with body `{"code":"ER001","target":"Authentication Invalid","message":"..."}`.
            - **Service** — credentials passed the gateway but the injected
            `X-MOE-Tenant-ID` header
              is missing (request bypassed gateway). Returns `Content-Type: application/json`.
          content:
            text/plain:
              schema:
                type: string
                description: >-
                  Gateway (APISIX) authentication failure. Body is
                  JSON-formatted but sent as text/plain.
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          $ref: '#/components/responses/GatewayAuthError'
        '409':
          description: >
            Idempotency conflict. Two distinct error codes are possible:


            **DUPLICATE_IDEMPOTENCY_KEY** — a request with the same
            Idempotency-Key is already

            in-flight (concurrent duplicate). Wait for the first request to
            complete before retrying.


            **IDEMPOTENCY_CONFLICT** — the Idempotency-Key was already used
            within the 24-hour

            window but the request body hash differs from the original request.
            Use a new

            Idempotency-Key to submit a different payload.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: >
            The rate limit for this endpoint has been exceeded. Retry after the
            window

            indicated in the `Retry-After` response header (in seconds).
          headers:
            Retry-After:
              schema:
                type: integer
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - basicAuth: []
components:
  schemas:
    ClientOfferCreateRequest:
      description: >
        Request body for creating an Offering via `POST /v5/offers`.


        Required fields: `name`, `priority`, `delivery`, `created_by`,
        `scheduling`,

        `segment_info`, `offer_content`, `variation_meta`.
      type: object
      required:
        - name
        - priority
        - delivery
        - created_by
        - scheduling
        - segment_info
        - offer_content
        - variation_meta
      properties:
        name:
          type: string
          description: >
            Unique display name for this offering within the workspace. Names
            are case-sensitive and must be unique.  Allowed characters:
            alphanumeric characters and underscores (_).
          minLength: 5
          maxLength: 100
          example: Summer_Sale_Promo_2026
        description:
          type: string
          description: >
            Optional free-text description of the offering's purpose, targeting
            rationale, or expected user experience. Visible in the MoEngage UI
            offering list.
          maxLength: 500
          example: 20% discount for returning users who have not purchased in 30 days
        priority:
          type: integer
          description: >
            Static priority score for offer ranking. Lower number means lower
            priority (1 is lowest priority, 100 is highest). This score is used
            when the Decision Policy ranking strategy is set to Offering
            Priority.
          minimum: 1
          maximum: 100
        delivery:
          type: string
          description: >
            Controls when the offering is eligible for delivery. `scheduled` —
            the offering is served within its scheduling window.
          enum:
            - scheduled
        created_by:
          type: string
          format: email
          description: |
            Email address of the user creating this offering.
          example: marketing-team@example.com
        tags:
          type: array
          description: >
            Tags that provide context about the Offering's nature or theme. Each
            tag ID must already exist in the workspace — the service returns
            `400 INVALID_TAG_ID` for any unknown tag ID.
          items:
            type: string
          maxItems: 10
          example:
            - activation
            - summer_sale
        scheduling:
          $ref: '#/components/schemas/OfferSchedulingCreate'
        segment_info:
          $ref: '#/components/schemas/OfferSegmentInfo'
        offer_content:
          $ref: '#/components/schemas/OfferContent'
        variation_meta:
          $ref: '#/components/schemas/OfferVariationMeta'
        capping_rules:
          $ref: '#/components/schemas/OfferCappingRules'
        is_global_control_enabled:
          type: boolean
          description: |
            Whether the global control group is enabled.
          default: false
        imp_track_hours:
          type: integer
          description: |
            The attribution window in hours.
          minimum: 1
          maximum: 240
          example: 36
        offering_attribute_configuration:
          type: array
          description: >
            Custom attributes assigned to this offering. These attributes are
            used in Decision Policy using the Custom formula ranking strategy.
          items:
            $ref: '#/components/schemas/OfferAttributeConfigurationRequest'
          maxItems: 5
        conversion:
          $ref: '#/components/schemas/ConversionDto'
          description: >
            Conversion goal configuration for measuring offering effectiveness.
            This can be set at creation time or later via PATCH while the
            offering is still in "scheduled" status. Once the offering goes
            "active", the conversion configuration is locked to preserve
            Thompson Sampling statistical integrity.
    PublicOfferCreateResponse:
      description: Response returned by `POST /v5/offers` on successful creation.
      type: object
      properties:
        response_id:
          type: string
          description: >
            Format: `resp_<X-MOE-Request-Id>` header value (auto-generated UUID
            if the `X-MOE-Request-Id` header was not part of the request body).
          example: resp_c5f83262-3127-4e23-bc1b-9efd4c929e12
        type:
          type: string
          enum:
            - offer
          description: Resource type discriminator. Always `offer`.
        data:
          type: object
          description: Created offering summary.
          properties:
            id:
              type: string
              description: >
                Offering ID assigned by the server. Format:
                `offer_<OfferingId>`. Use this value as the `{offer_id}` path
                parameter in subsequent PATCH requests.
              example: offer_6a4f69ee490f66322f968b87
            status:
              type: string
              enum:
                - active
                - scheduled
              description: |
                Lifecycle status of the newly created offering
              example: scheduled
            created_at:
              type: string
              format: date-time
              description: ISO 8601 UTC timestamp when the offering was persisted.
              example: '2026-07-09T09:29:18.526812352Z'
      example:
        response_id: resp_c5f83262-3127-4e23-bc1b-9efd4c929e12
        type: offer
        data:
          id: offer_6a4f69ee490f66322f968b87
          status: scheduled
          created_at: '2026-07-09T09:29:18.526812352Z'
    ErrorResponse:
      type: object
      required:
        - response_id
      properties:
        error:
          type: object
          required:
            - code
            - message
            - doc_url
          properties:
            code:
              type: string
              description: Machine-readable ALL_CAPS_SNAKE_CASE error code.
              example: VALIDATION_FAILED
            message:
              type: string
              description: >-
                Human-readable explanation. Specific enough for AI agents to act
                on.
            target:
              type: string
              description: >-
                The field or resource that caused the error (e.g.
                "scheduling.expiry_datetime").
            details:
              type: array
              description: >
                Per-field error entries for VALIDATION_FAILED responses. All
                field violations are collected and returned in a single response
                — never truncated.
              items:
                type: object
                properties:
                  code:
                    type: string
                    description: Field-level error code.
                  target:
                    type: string
                    description: Dot-notation path to the failing field.
                  message:
                    type: string
                    description: Human-readable description of the field-level violation.
            doc_url:
              type: string
              description: Link to documentation for this error code.
              example: https://www.moengage.com/docs/api/offerings/offerings-overview
        response_id:
          type: string
          description: >
            Trace identifier — same format as success responses ("resp_" +
            X-MOE-Request-Id). Always present even on error responses for log
            correlation.
    OfferSchedulingCreate:
      description: >
        Scheduling window that determines when an offering is eligible for
        delivery.

        Both `start_datetime` and `expiry_datetime` are required when creating
        an offering.
      type: object
      required:
        - start_datetime
        - expiry_datetime
      properties:
        start_datetime:
          type: string
          format: date-time
          description: >
            ISO 8601 UTC datetime when the offering becomes eligible for
            delivery. MUST use the UTC "Z" suffix format.
          example: '2026-06-15T09:00:00Z'
        expiry_datetime:
          type: string
          format: date-time
          description: >
            ISO 8601 UTC datetime when the offering expires and stops being
            served. MUST use the UTC "Z" suffix format.
          example: '2026-09-30T23:59:59Z'
        timezone:
          type: string
          description: >
            IANA timezone name. When omitted, the default timezone set for the
            workspace will be considered.
          example: Asia/Kolkata, America/New_York, UTC
    OfferSegmentInfo:
      description: >
        Segment targeting configuration that controls which users are eligible
        to

        receive this offering.


        `included_filters`: criteria a user MUST match to be eligible.

        `excluded_filters`: criteria that DISQUALIFY a user even if they match
        the

        included filters.


        To target `all users`, send an empty filters object:

        { "filters": {} }
      type: object
      properties:
        filters:
          type: object
          description: >
            Container for inclusion and exclusion filter blocks. Pass an empty
            object to target all users with no segmentation restriction.
          properties:
            included_filters:
              type: object
              description: >
                The filtering criteria used for including users. For detailed
                payload and supported fields, refer to [Create Filter
                Segment](https://www.moengage.com/docs/api/filter-segments/create-filter-segment).
              properties:
                filters:
                  type: array
                  description: >
                    Array of individual filter criteria. Each item is a filter
                    object whose structure varies by filter_type. Common
                    filter_type values: `actions`, `user_attributes`,
                    `custom_segments`.
                  items:
                    type: object
                    description: >-
                      A single UIS filter criterion. Structure varies by
                      filter_type.
                filter_operator:
                  type: string
                  description: |
                    The logical operator to combine filters.
                  enum:
                    - and
                    - or
            excluded_filters:
              type: object
              description: |
                The filtering criteria used for excluding users.
              properties:
                filters:
                  type: array
                  items:
                    type: object
                filter_operator:
                  type: string
                  enum:
                    - and
                    - or
    OfferContent:
      description: >
        The core content payload delivered to the end-user. This object supports
        two mutually exclusive structures depending on whether your offering
        uses content variations or experimentation.


        **Mutually Exclusive:** Do not provide both `content_1` and `locales` in
        the same request payload. Doing so will result in a validation error.


        ### 1. Flat Format (No Content Variations)


        Use this structure for simple offerings that do not require A/B testing
        or localization.


        * **Payload Structure:** Send a single `content_1` object at the root
        level.

        * **Behavior:** The exact same content block is served universally to
        all eligible users.


        ### 2. Nested Format (Multiple Content Variations)


        Use this structure when `variation_meta.type` is configured as either
        **SMV** (Static Multi-Variant) or **DMV** (Dynamic Multi-Variant).


        * **Payload Structure:** Send a structured `locales` map object.

        * **Single-Locale Targeting:** For single-locale offerings, you **must**
        use `"0"` as the literal locale key string.

        * **Variations Mapping:** Inside each locale, the nested `variations`
        map keys must exactly match the variation IDs defined in
        `variation_meta.variantsPerLocale` and `smv_distribution.split`.
      type: object
      properties:
        content_1:
          $ref: '#/components/schemas/ContentBlock'
          description: |
            Primary content block for single variation offerings.
        locales:
          type: object
          description: |
            Use "0" as the locale key
          additionalProperties:
            type: object
            description: Content container for a single locale.
            required:
              - variations
            properties:
              variations:
                type: object
                description: >
                  Each key is a variation of the content payload. The key name
                  **must** match a key in
                  `variation_meta.smv_distribution.split`. 
                additionalProperties:
                  type: object
                  properties:
                    content_1:
                      $ref: '#/components/schemas/ContentBlock'
      example:
        content_1:
          type: json
          value: >-
            {"headline":"Save 20% today","cta_text":"Claim
            offer","image_url":"https://cdn.example.com/banner.png","cta_url":"https://example.com/offer/summer"}
    OfferVariationMeta:
      description: >
        Configuration for A/B testing content variations.


        * `SMV`: Fixed percentage splits across up to 5 variations.

        * `DMV`: The system automatically learns which variant performs best
        over time and shifts traffic toward the winner.

        * `Offer Control Group`: A configurable percentage of eligible users to
        be held out as a pure control group.


        #### Lifecycle & Mutation Rules


        `variation_meta` can be edited later via `PATCH /v5/offers/{offer_id}`,
        subject to status-based rules. Field mutability depends on both the
        offering status and the variation type. Attempting to modify a locked
        field returns a `400 IMMUTABLE_FIELD` error.


        | Offering Status | Variation Type | Editable Fields | Locked Fields |

        | :--- | :--- | :--- | :--- |

        | **`scheduled`** | Any | Entire object (`type`, `variantsPerLocale`,
        `smv_distribution`, `control_group`) | None |

        | **`active`** | **SMV** | `smv_distribution.split` percentages,
        `control_group.percentage` | `type`, Variant key names |

        | **`active`** | **DMV** | `control_group.percentage` | `type`,
        `variantsPerLocale`, `smv_distribution` |

        | **`expired`** | Any | None | All fields are locked |
      type: object
      required:
        - type
      properties:
        type:
          type: string
          description: >
            Variation strategy type. `SMV` — fixed percentage split. `DMV` -
            adaptive traffic allocation.
          enum:
            - SMV
            - DMV
        variantsPerLocale:
          type: array
          description: >
            Ordered list of variations. This list **must** contain exactly the
            same keys defined in smv_distribution.split and **must** match the
            variation keys used in `offer_content.locales[0].variations`.
          items:
            type: string
          example:
            - Variant_A
            - Variant_B
        smv_distribution:
          type: object
          description: >
            Variation percentage allocation. Required when type is `SMV`;
            optional for `DMV`.
          properties:
            split:
              type: object
              description: |
                Map of variations to integer percentage allocation.
              additionalProperties:
                type: integer
                minimum: 1
                maximum: 100
              example:
                Variation_1: 70
                Variation_2: 30
        control_group:
          type: object
          description: >
            When enabled, a percentage of eligible users are held out as a pure
            control and do not receive the offering. This operates independently
            of the workspace-level GCG.
          properties:
            is_enabled:
              type: boolean
              description: Whether the offering-level control group holdout is active.
              example: false
            percentage:
              type: integer
              description: |
                Percentage of eligible users to hold out. 
              minimum: 1
              maximum: 99
              example: 10
      example:
        type: SMV
        variantsPerLocale:
          - Variant_A
          - Variant_B
        smv_distribution:
          split:
            Variant_A: 70
            Variant_B: 30
        control_group:
          is_enabled: true
          percentage: 10
    OfferCappingRules:
      description: >
        Frequency capping configuration that limits how often this offering is
        delivered.

        Two independent capping rules can be configured and enabled
        simultaneously.


        `overall`: Limits the TOTAL number of times the offering is delivered
        across

        **ALL users in the target segment** within the capping schedule period.


        `user_level`: Limits the number of times any SINGLE user can receive the

        offering within the capping schedule period.
      type: object
      properties:
        overall:
          $ref: '#/components/schemas/OfferCappingRule'
          description: Total delivery cap across all users within the target segment.
        user_level:
          $ref: '#/components/schemas/OfferCappingRule'
          description: Per-user delivery cap for individual users.
      example:
        overall:
          enabled: true
          limit_value: 10000
          limit_schedule: DAILY
        user_level:
          enabled: true
          limit_value: 3
          limit_schedule: WEEKLY
    OfferAttributeConfigurationRequest:
      description: >
        Assignment of a custom offering attribute and its value(s) to this
        offering.
      type: object
      required:
        - offering_attribute_id
        - selected_values
      properties:
        offering_attribute_id:
          type: string
          description: |
            ID of the Offering Attribute. 
        offering_attribute_name:
          type: string
          description: |
            Display name of the referenced Offering Attribute.
          example: Product Category
        type:
          type: string
          description: |
            Attribute type of the referenced Offering Attribute.
          enum:
            - FIXED
            - DYNAMIC
          example: FIXED
        selected_values:
          type: array
          description: >
            Selected option value(s) for this attribute. At least one value is
            required. For `DYNAMIC` attributes, at most one value is allowed per
            assignment. For `FIXED` attributes, multiple values are allowed up
            to the attribute definition's `max_inputs_allowed` limit.
          items:
            type: object
            required:
              - value
            properties:
              id:
                type: string
                description: >
                  ID of the option(s) defined as part of the Offering Attribute
                  definition.
                nullable: true
              value:
                type: string
                description: >
                  Option value string. It must match an existing option name in
                  the Offering Attribute definition.
                example: Electronics
              score:
                type: integer
                description: >
                  Priority score for this option to be used in a Decision Policy
                  using the Custom Formula ranking strategy. Set to `null` for
                  `DYNAMIC` attributes. Set to a value between 1-100 for `FIXED`
                  attributes.
                minimum: 1
                maximum: 100
                nullable: true
                example: 85
          minItems: 1
    ConversionDto:
      description: >
        List of conversion goals to track.


        **Status constraint:** `conversion` can only be set or updated while the
        offering status is `scheduled`. Attempting to update it on an `active`
        or `expired` offering returns a `400 IMMUTABLE_FIELD` error.
      type: object
      properties:
        primary:
          $ref: '#/components/schemas/ConversionGoal'
          description: |
            Primary conversion goal.
        secondary:
          type: array
          description: |
            Additional conversion goals tracked alongside the primary goal.
          items:
            $ref: '#/components/schemas/ConversionGoal'
    ContentBlock:
      description: >
        This field indicates the type of the offering content payload.


        `json` — Serialised JSON string containing the offering content 

        payload.


        `content_block` — The ID of a content block stored in the

        MoEngage Content Block library.


        `template` — value is a JSON object of the personalized template's field
        values, and

        meta.templateId carries the template id (from GET /v1/offers/templates).
      type: object
      required:
        - type
        - value
      properties:
        type:
          type: string
          description: >
            Format of the content payload. Determines how `value` is
            interpreted. `json` — serialised JSON string. `content_block` —
            Content Block library reference ID. `template` — object of template
            field key-value pairs.
          enum:
            - json
            - content_block
            - template
        value:
          description: >
            Content payload. Interpretation depends on `type`:


            - **`json`** — value must be a **serialised JSON string** (not an
            inline JSON object).
              The entire payload is encoded as a string. Example: `"{\"discount\": \"10%\"}"`.
              Passing a raw JSON object instead of a string returns `400 INVALID_TYPE`.
            - **`content_block`** — value is the reference ID string of a
            Content Block from the
              MoEngage Content Block library.
            - **`template`** — value is a JSON **object** (not a string) whose
            keys are the field
              names defined by the template schema. Retrieve available templates and required fields
              from `GET /v5/offers/templates`. Omitting a required template field returns
              `400 MISSING_TEMPLATE_FIELD`.
          oneOf:
            - type: string
              description: >-
                For `json` and `content_block` types. For `json`, must be a
                serialised JSON string — not an inline object.
            - type: object
              description: >-
                For `template` type — a map of template field names to their
                values.
              additionalProperties: true
        meta:
          type: object
          description: >
            Key-value metadata attached to this content block.

            **Required for template type**: when `type` is `template`, you
            **must** include `templateId` in this object, set to the template's
            `id` value returned by GET /v1/offers/templates.
          additionalProperties: true
          example:
            templateId: app_small
    OfferCappingRule:
      description: A single frequency capping rule (either overall or per-user).
      type: object
      required:
        - enabled
      properties:
        enabled:
          type: boolean
          description: >-
            Whether this capping rule is enforced. When false, all other fields
            are ignored.
          example: true
        limit_value:
          type: integer
          description: >
            Maximum number of deliveries allowed within one limit_schedule
            period. Required when enabled is true. Must be at least 1. For
            overall capping, this is the total across all users. For user_level
            capping, this is per individual user.
          minimum: 1
          example: 3
        limit_schedule:
          type: string
          description: |
            Time window for the capping counter.
          enum:
            - DAILY
            - WEEKLY
            - MONTHLY
          example: WEEKLY
    ConversionGoal:
      description: A single conversion goal that tracks a specific user action.
      type: object
      required:
        - goal_name
        - action
      properties:
        goal_name:
          type: string
          description: |
            Display name for this conversion goal.
          example: Add to Cart
        action:
          type: string
          description: |
            MoEngage event name associated with the conversion goal.
          example: add_to_cart
        filter_type:
          type: string
          description: >
            How the conversion event is matched. "ACTIONS" matches by event name
            and optional attribute-level filters.
          example: ACTIONS
        attributes:
          $ref: '#/components/schemas/ConversionAttributesDto'
          description: >
            Optional attribute-level filters to narrow which occurrences of the
            action count as a conversion (e.g. only purchase events where
            category = "Electronics").
        is_revenue_tracking:
          type: boolean
          description: >
            When true, the conversion also records the monetary value from the
            event. Requires the `revenue_amount` and `revenue_currency` fields
            to be set.
          default: false
        revenue_amount:
          type: string
          description: >
            Name of the event attribute containing the transaction revenue
            value. Should be used only when `is_revenue_tracking` is true. The
            attribute must be a numeric field on the tracked event.
          example: order_value
        revenue_currency:
          type: string
          description: >
            ISO 4217 three-letter currency code for revenue tracking (e.g.
            "USD", "EUR", "GBP", "INR"). Should be used only when
            `is_revenue_tracking` is true.
          example: USD
    ConversionAttributesDto:
      type: object
      description: >
        Attribute-level filters applied to the conversion event. Allows
        narrowing the conversion signal to a specific subset of occurrences of
        the tracked action (e.g. only purchases where category equals
        "Electronics").
      properties:
        filters:
          type: array
          description: >
            Array of attribute filter objects. Each object targets a specific
            event attribute. Follows the same filter structure as
            `segment_info.filters.included_filters.filters`.
          items:
            type: object
            description: >-
              A single attribute filter criterion. Structure varies by
              filter_type.
          properties:
            included_filters:
              type: object
              description: >
                Inclusion criteria for the conversion attribute filter. Contains
                a "filters" array of UIS filter objects and a "filter_operator"
                (AND or OR).
              properties:
                filters:
                  type: array
                  items:
                    type: object
                    description: >-
                      A single UIS filter criterion. Structure varies by
                      filter_type.
                filter_operator:
                  type: string
                  enum:
                    - and
                    - or
                  example: and
            excluded_filters:
              type: object
              description: Exclusion criteria, same structure as included_filters.
              properties:
                filters:
                  type: array
                  items:
                    type: object
                filter_operator:
                  type: string
                  enum:
                    - and
                    - or
  responses:
    GatewayAuthError:
      description: >
        Authentication or authorisation failure from the API gateway layer.

        This response is generated by the gateway before the request reaches the
        service.

        The body is JSON-formatted but API gateway sends it with `Content-Type:
        text/plain`.

        Two gateway error codes are possible:

        - `ER001` — credentials missing or invalid (401).

        - `ER007` — credentials valid but insufficient scope for this route
        (403).
      content:
        text/plain:
          schema:
            type: string
            example: >-
              {"code":"ER001","target":"Authentication Invalid","message":"Auth
              validation failed."}
    ServiceUnavailable:
      description: >
        Gateway temporarily unable to route the request. Returned when the

        upstream service is unreachable or the HTTP request cannot be proxied
        (e.g. malformed

        headers with control characters). Treat as a transient error and retry
        with exponential back-off.
      content:
        text/html:
          schema:
            type: string
            example: >-
              <html><body><h1>503 Service Temporarily
              Unavailable</h1></body></html>
  securitySchemes:
    basicAuth:
      type: http
      scheme: basic
      description: >
        Authentication is done via Basic Auth. This requires a base64-encoded
        string of your credentials in the format 'username:password'.


        - **Username**: Use your MoEngage Workspace ID (also known as the App
        ID). Find it in the dashboard at **Settings** > **Account** > **APIs** >
        **Workspace ID (earlier app id)**.

        - **Password**: On your MoEngage workspace, navigate to **Settings** >
        **Account** > **API keys**. Use the Key listed within the
        **Personalize** tile.


        For more information on authentication and getting your credentials,
        refer to [Getting  your
        credentials](https://www.moengage.com/docs/api/introduction#getting-your-credentials).

        Send the value in the `Authorization` header as `Basic` followed by
        Base64-encoding of `appkey:apisecret` (workspace ID and API key).

````