> ## 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.

# Update Offering

> Modify an existing offering. Only the fields you include in the request body are
changed.


#### 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 patch /v5/offers/{offer_id}
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/{offer_id}:
    patch:
      tags:
        - Public Offerings
      summary: Update Offering
      description: >
        Modify an existing offering. Only the fields you include in the request
        body are

        changed.
      operationId: updatePublicOffering
      parameters:
        - name: offer_id
          in: path
          required: true
          schema:
            type: string
          description: >-
            The unique ID of the offering to be updated. You can fetch the
            offering ID using the [List Offerings
            API](/api/public-offerings/list-offerings) by filtering with name.
        - 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 `200 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/ClientOfferPatchRequest'
            examples:
              extendExpiry:
                summary: Extend expiry date only
                value:
                  updated_by: marketing-team@example.com
                  scheduling:
                    expiry_datetime: '2026-12-31T23:59:59Z'
              updateNameAndTags:
                summary: Rename offering and replace tags
                value:
                  updated_by: marketing-team@example.com
                  name: Summer_Sale_Promo_2026_V2
                  tags:
                    - summer-sale
                    - vip-users
              updateContent:
                summary: Update offer content (single variant, locale "0")
                value:
                  updated_by: marketing-team@example.com
                  offer_content:
                    locales:
                      '0':
                        variations:
                          Variant_A:
                            content_1:
                              type: json
                              value: >-
                                {"headline":"Flash Sale - 30%
                                Off!","cta_text":"Claim
                                Now","cta_url":"https://example.com/flash"}
      responses:
        '200':
          description: Offering updated successfully.
          headers:
            X-MOE-Request-Id:
              schema:
                type: string
              description: Echoed trace ID.
            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/PublicOfferPatchResponse'
        '400':
          description: >
            Validation errors. All errors collected before returning. Possible
            error codes:

            - `REQUIRED_FIELD_MISSING` — a required field is absent
            (`updated_by`). The `target` field identifies the missing field.

            - `INVALID_TYPE` — wrong type or format (e.g.
            `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 (e.g.
            unrecognised `variation_meta.type`).

            - `INVALID_OFFER_NAME` — `name` contains characters other than
            alphanumeric characters and underscores.

            - `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.

            - `IMMUTABLE_FIELD` — attempt to change a status-locked field:
              • `scheduling.start_datetime` when offering is ACTIVE or EXPIRED.
              • `conversion` when offering is not in `scheduled` status.
              • `variation_meta.type` when offering is ACTIVE.
              • Adding or removing keys in `variation_meta.variantsPerLocale` when offering is ACTIVE — only split percentages (SMV) or `control_group.percentage` (DMV) can change on an ACTIVE offering.
            - `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.

            - `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.

            - `INVALID_TAG_ID` — one or more tag IDs in `tags` do not exist in
            this workspace.

            - `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.

            - `MISSING_IDEMPOTENCY_KEY` — `Idempotency-Key` header is absent.

            - `INVALID_IDEMPOTENCY_KEY` — `Idempotency-Key` is present but not a
            valid 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: IMMUTABLE_FIELD
                      target: variation_meta.type
                      message: >-
                        variation_meta.type cannot be changed on an active
                        offering.
                      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':
          description: >
            Forbidden. Two distinct sources produce 403 on this endpoint:

            - **Gateway (APISIX)** — insufficient scope for this route. Returns
            `Content-Type: text/plain`
              with body `{"code":"ER007","target":"Authentication Invalid","message":"..."}`.
            - **Service** — offering is in a terminal lifecycle state. Returns
            `Content-Type: application/json`.
              Error codes: `EXPIRED_OFFERING` (past expiry_datetime) or `ARCHIVED_OFFERING` (manually archived).
          content:
            text/plain:
              schema:
                type: string
                description: >-
                  Gateway (APISIX) scope failure. Body is JSON-formatted but
                  sent as text/plain.
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: Offering not found (OFFER_NOT_FOUND).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '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'
              examples:
                duplicateInFlight:
                  summary: Concurrent duplicate (in-flight)
                  value:
                    error:
                      code: DUPLICATE_IDEMPOTENCY_KEY
                      message: >-
                        A request with this Idempotency-Key is already being
                        processed.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                      target: Idempotency-Key
                    response_id: resp_<trace-id>
                bodyMismatch:
                  summary: Same key, different body
                  value:
                    error:
                      code: IDEMPOTENCY_CONFLICT
                      message: >-
                        The Idempotency-Key was already used with a different
                        request body. Use a new key.
                      doc_url: >-
                        https://www.moengage.com/docs/api/offerings/offerings-overview
                      target: Idempotency-Key
                    response_id: resp_<trace-id>
        '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
              description: Seconds to wait before retrying.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          $ref: '#/components/responses/ServiceUnavailable'
      security:
        - basicAuth: []
components:
  schemas:
    ClientOfferPatchRequest:
      description: >
        Request body for partially updating an existing offering via the public
        API (`PATCH /v5/offers/{offer_id}`). Only the fields explicitly provided
        in the request body will be modified.


        Some fields are status-gated based on the offering's current lifecycle
        phase — see the field-level descriptions for `variation_meta`,
        `conversion`, and `scheduling` for the exact rules. Modifying a locked
        field returns a `400 IMMUTABLE_FIELD` error.
      type: object
      required:
        - updated_by
      properties:
        updated_by:
          type: string
          format: email
          description: |
            Email address of the team member making this update.
          example: marketing-team@example.com
        name:
          type: string
          description: >
            Updated display name for the offering. Must remain unique within the
            workspace. **Allowed characters:** alphanumeric characters and
            underscores (_) only.
          minLength: 5
          maxLength: 100
        description:
          type: string
          description: Updated free-text description of the offering's purpose.
          maxLength: 500
        priority:
          type: integer
          description: Updated static priority score.
          minimum: 1
          maximum: 100
        tags:
          type: array
          description: >
            **Full replacement, not additive** — the entire existing tag list is
            overwritten with this value. To add a single tag, send the complete
            current tag list plus the new tag. To remove all tags, send an empty
            array.
          items:
            type: string
            maxLength: 50
          maxItems: 10
        scheduling:
          $ref: '#/components/schemas/OfferSchedulingPatch'
        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: >
            Toggle GCG holdout exclusion. When true, GCG members are excluded
            from receiving this offering. When false, all eligible users can
            receive it.
        imp_track_hours:
          type: integer
          description: Updated impression de-duplication window in hours (1 to 240).
          minimum: 1
          maximum: 240
        offering_attribute_configuration:
          type: array
          description: >
            Replacement custom attribute configuration. This is a FULL
            REPLACEMENT — the entire existing attribute list is overwritten. At
            most 5 attributes.
          items:
            $ref: '#/components/schemas/OfferAttributeConfigurationRequest'
          maxItems: 5
        conversion:
          $ref: '#/components/schemas/ConversionDto'
    PublicOfferPatchResponse:
      description: Response returned by `PATCH /v5/offers/{offer_id}` on successful update.
      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
        data:
          type: object
          description: Updated offering summary.
          properties:
            id:
              type: string
              description: Offering ID
              example: offer_6a4f69ee490f66322f968b87
            status:
              type: string
              enum:
                - active
                - scheduled
              description: Current lifecycle status after the update.
              example: active
            updated_at:
              type: string
              format: date-time
              description: ISO 8601 UTC timestamp of the update.
              example: '2026-07-09T09:29:18.526812352Z'
      example:
        response_id: resp_c5f83262-3127-4e23-bb1b-9efd4c929e12
        type: offer
        data:
          id: offer_6a4f69ee490f66322f968b87
          status: active
          updated_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.
    OfferSchedulingPatch:
      description: >
        Partial scheduling update for `PATCH` operations. All fields are
        optional.

        `start_datetime` can only be changed when offering status is
        `scheduled`. 

        `expiry_datetime` can be updated only when offering status is `active`
        or `scheduled`.
      type: object
      properties:
        start_datetime:
          type: string
          format: date-time
          description: |
            Updated `start datetime`. MUST use UTC "Z" suffix.
          example: '2026-06-20T09:00:00Z'
        expiry_datetime:
          type: string
          format: date-time
          description: |
            Updated `expiry datetime`. MUST use UTC "Z" suffix.
          example: '2026-10-31T23:59:59Z'
        timezone:
          type: string
          description: |
            Updated IANA timezone name.
          example: Asia/Kolkata
    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:
    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).

````