MoEngage Public Offerings API

The Public Offerings API from MoEngage — 3 operation(s) for public offerings.

Operations 4

GET /v5/offers List Offerings #
POST /v5/offers Create Offering #
PATCH /v5/offers/{offer_id} Update Offering #
GET /v5/offers/templates List Offer Templates #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/moengage-public-offerings-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Discovery needs no key. Ratings and market analysis are Pro.

Get an API key

Free tier, no email required.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

moengage-public-offerings-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Offer Decisioning Public API - v5 Public Offerings API
  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

        '
tags:
- name: Public Offerings
paths:
  /v5/offers:
    get:
      operationId: listPublicOfferings
      summary: List Offerings
      description: 'Fetch all offerings in the workspace. Returns a summary of each offering — ID, name,

        status, tags, and creation metadata.

        '
      x-mint:
        content: '#### Rate Limit

          The rate limit is 150 requests per minute, 500 requests per hour, and 1000 requests per day per consumer.

          '
      x-moe-mcp:
        expose:
          external: true
          internal: true
        tool_description: "List all offer campaigns in the workspace. Use this as the first step to discover\nexisting offerings and their IDs before calling update_offering or inspecting details.\n\nReturns a paginated summary — ID, name, status, tags, created_at, created_by.\nUse the fields parameter to request only the fields you need (reduces token usage).\n\nTypical agent flow:\n  1. Call list_offerings (optionally filter by status_in=active or name_contains)\n  2. Pick the offering ID (e.g. 6a4f69ee490f66322f968b87) from the results\n  3. Call update_offering with that ID to modify the offering\n\nPagination: pass next_cursor from the pagination object on the next call.\nKeep paginating until has_more is false.\n"
        param_overrides:
          status_in:
            description: 'Filter by lifecycle status. Use ''active'' to find offerings currently being

              served to users. Use ''scheduled'' for upcoming ones. Omit to return all statuses

              including drafts. Valid values: active, scheduled, expired, archived, draft.

              Example: status_in=active,scheduled

              '
          cursor:
            description: 'An opaque pagination token used to retrieve the next page of results.


              * **Initial Request:** Omit this parameter entirely on the first call to fetch the beginning of the list.

              * **Subsequent Pages:** Pass the exact string received from the `next_cursor` field of the immediate previous response.

              * **Handling:** Pass this token completely verbatim. Do not decode, alter, or modify the string in any way.

              '
          fields:
            description: 'Comma-separated list of fields to return. Omit for all six fields.

              Use to minimise token usage. Valid values: `id`, `name`, `status`, `tags`, `created_at`, `created_by`.

              Example: fields=id,name,status

              '
          limit:
            description: 'The number of offerings to return per paginated response.

              '
      tags:
      - Public Offerings
      security:
      - basicAuth: []
      parameters:
      - name: id
        in: query
        required: false
        schema:
          type: string
        description: 'Look up a single offering by its exact prefixed ID (e.g. offer_6a4f69ee490f66322f968b87). Use this when you already know the offering ID and want to confirm it exists before updating it.

          '
      - name: name_contains
        in: query
        required: false
        schema:
          type: string
          maxLength: 100
        description: 'Find offerings whose name contains specific text (case-insensitive). For example, pass "summer" to find all summer-related offerings.

          '
      - name: status_in
        in: query
        required: false
        schema:
          type: string
        description: 'Filter by lifecycle status. Valid values: active, scheduled, expired, archived, draft. Example: status_in=active,scheduled

          '
      - name: tags
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        style: form
        explode: true
        description: 'Filter to offerings that have ALL of the specified tags. Repeat the parameter for multiple tags: tags=summer-sale&tags=vip-users.

          '
      - name: created_date_gte
        in: query
        required: false
        schema:
          type: string
          format: date
        description: 'List offerings created on or after this date. Format: YYYY-MM-DD.

          '
      - name: created_date_lte
        in: query
        required: false
        schema:
          type: string
          format: date
        description: 'List offerings created on or before this date. Format: YYYY-MM-DD.

          '
      - name: created_by
        in: query
        required: false
        schema:
          type: array
          items:
            type: string
        style: form
        explode: true
        description: 'Filter offerings created by specific team members. Pass one or more email addresses. Example: created_by=john.doe@example.com,marketing-team@example.com

          '
      - name: fields
        in: query
        required: false
        schema:
          type: string
        description: 'Request only the fields you need. Example: fields=id,name,status returns only those three fields per item.

          '
      - name: cursor
        in: query
        required: false
        schema:
          type: string
        description: 'Pagination cursor returned as `next_cursor` in the previous response. Omit on the first request. When `next_cursor` is `null` in the response, you have reached the last page.

          '
      - name: limit
        in: query
        required: false
        schema:
          type: integer
          default: 20
          minimum: 1
          maximum: 100
        description: Items per page. Default 20, max 100.
      - 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.

          '
      responses:
        '200':
          description: Paginated list of offerings.
          headers:
            X-MOE-Request-Id:
              schema:
                type: string
              description: Trace ID echoed from the gateway.
            X-RateLimit-Limit:
              schema:
                type: integer
                example: 150
              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:
                type: object
                required:
                - response_id
                - type
                - data
                - pagination
                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).

                      '
                  type:
                    type: string
                    enum:
                    - offer
                  data:
                    type: array
                    description: List of offering summaries matching the applied filters.
                    items:
                      $ref: '#/components/schemas/OfferingListItem'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
              example:
                response_id: resp_d31d6d61-6f3b-40dc-a459-548f385a60cb
                type: offer
                data:
                - id: offer_6a4f69ee490f66322f968b87
                  name: Summer_Sale_Promo_2026
                  status: active
                  tags:
                  - tag_<object-id>
                  created_at: '2026-06-23T12:29:41.225270281Z'
                  created_by: marketing-team@example.com
                - id: offer_6a4f69ee490f66322f968b87
                  name: Homepage_Banner_AB_Test
                  status: scheduled
                  created_at: '2026-06-23T12:29:41.225270281Z'
                  created_by: growth-team@example.com
                pagination:
                  next_cursor: b2ZmZXJzOjZhM2E3YzM0NTE4NjdkNGRjZmIxNzQ5Mw==
                  limit: 20
                  has_more: true
                  total_count: 42
        '400':
          description: 'Invalid query parameter. Possible error codes in `error.details[].code`:

            - `OUT_OF_RANGE` — `limit` > 100, or `name_contains` > 100 chars.

            - `INVALID_CURSOR` — `cursor` is present but malformed (not valid base64, or corrupted segment/id).

            - `INVALID_ENUM_VALUE` — unrecognised value in `status_in`.

            - `INVALID_FIELDS_PARAM` — unrecognised field name in `fields`.

            - `INVALID_TYPE` — `created_date_gte` or `created_date_lte` not in YYYY-MM-DD format.

            '
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_FAILED
                  message: One or more query parameters are invalid.
                  doc_url: https://www.moengage.com/docs/api/offerings/offerings-overview
                  details:
                  - code: INVALID_ENUM_VALUE
                    target: status_in
                    message: '''invalid_status'' is not a valid status. Allowed values: active, scheduled, expired, archived, draft.'
                    doc_url: https://www.moengage.com/docs/api/offerings/offerings-overview
                response_id: resp_<trace-id>
        '401':
          $ref: '#/components/responses/GatewayAuthError'
        '403':
          $ref: '#/components/responses/GatewayAuthError'
        '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'
    post:
      operationId: createPublicOffering
      summary: Create Offering
      description: 'Create a new Offering in the workspace.

        '
      x-mint:
        content: '#### Rate Limit

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

          '
      x-moe-mcp:
        expose:
          external: true
          internal: true
        tool_description: "Create a new offering in the workspace.\n\nKey constraints:\n  - start_datetime MUST be in the future and use UTC \"Z\" suffix (e.g. \"2026-07-01T00:00:00Z\").\n    A past value returns 400 INVALID_SCHEDULING. Offset strings like \"+05:30\" are not accepted.\n  - tags must be pre-existing tag IDs — unknown IDs return 400 INVALID_TAG_ID.\n  - variation_meta CAN be updated via PATCH with status-based rules. See update_offering.\n  - name must be alphanumeric + underscores only (no spaces or hyphens). 5–100 chars.\n\nAlways supply a unique Idempotency-Key (UUID v4) header to prevent duplicate offerings\non retries. The same key within 24 hours returns the original 201 response.\n\nFor a simple single-variant offering with no A/B test:\n  - Set variation_meta.type = SMV, variantsPerLocale = [Variant_A], split = {Variant_A: 100}\n  - Put content in offer_content.locales[\"0\"].variations.Variant_A\n  - Locale key must be \"0\" for single-locale offerings (not \"default\" or \"en\")\n"
        param_overrides:
          variation_meta:
            description: "A/B test configuration. For a simple offering (no A/B test), use:\n  type: SMV, variantsPerLocale: [Variant_A], split: {Variant_A: 100}\nFor A/B test (SMV): split values must sum to exactly 100 inclusive of control group allocation(INVALID_SPLIT if not).\nFor AI optimization (DMV): provide equal initial splits; the server learns over time.\nStatus-based PATCH rules: SCHEDULED=free; ACTIVE+SMV=split% only; ACTIVE+DMV=control_group.percentage only.\n"
          offer_content:
            description: "Content payload. Use the locales[\"0\"] nested format for single-locale offerings:\n  {\"locales\": {\"0\": {\"variations\": {\"Variant_A\": {\"content_1\": {\"type\": \"json\", \"value\": \"...\"}}}}}}\nThe locale key \"0\" is required for single-locale — do not use \"default\" or \"en\".\nVariation keys in offer_content must exactly match variantsPerLocale and split keys (SPLIT_KEY_MISMATCH if not).\n"
          scheduling:
            description: 'Schedule window. Both start_datetime and expiry_datetime are required and **MUST** use

              UTC "Z" suffix (e.g. "2026-07-01T00:00:00Z"). Offset strings like "+05:30" return INVALID_TYPE.

              start_datetime must be in the future.

              '
          segment_info:
            description: 'Audience targeting. To target all users with no restrictions, send: {"filters": {}}

              For attribute-based targeting, use filter_type: "user_attributes" with data_type required.

              '
      tags:
      - Public Offerings
      security:
      - basicAuth: []
      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\nresponse may contain multiple `details` entries. Possible error codes:\n- `REQUIRED_FIELD_MISSING` — a required field is absent (e.g. missing `variation_meta`, `name`, `scheduling.start_datetime`). The `target` field identifies the missing field.\n- `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).\n- `OUT_OF_RANGE` — numeric field outside its allowed range (e.g. `priority` outside 1–100, `control_group.percentage` outside 1–99).\n- `INVALID_ENUM_VALUE` — enum field has an unrecognised value.\n- `INVALID_OFFER_NAME` — `name` contains characters other than alphanumeric characters and underscores. Spaces and hyphens are not allowed.\n- `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.\n- `INVALID_TIMEZONE` — `scheduling.timezone` is present but not a valid IANA timezone name (e.g. `Asia/Kolkata`, `America/New_York`, `UTC`).\n- `SPLIT_KEY_MISMATCH` — keys in `smv_distribution.split` do not match `variantsPerLocale`.\n- `INVALID_SPLIT` — values in `smv_distribution.split` do not sum to exactly 100. Adjust the percentages so the total equals 100.\n- `VARIANT_COUNT_MISMATCH` — count of variants in `offer_content` does not match `variantsPerLocale`.\n- `INVALID_TEMPLATE_ID` — `meta.templateId` refers to a template ID not registered in the workspace.\n- `MISSING_TEMPLATE_FIELD` — a required field (per the template's config) is missing or blank in the `value` map.\n  The `target` field will be `offer_content.locales.<locale>.variations.<variant>.content_1.value.<fieldKey>`.\n- `DUPLICATE_OFFER_NAME` — `name` matches an existing non-archived offering in this workspace. Offering names must be unique. Choose a different name.\n- `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.\n- `REVENUE_FIELDS_INCOMPLETE` — `conversion.primary.revenue_amount` or `conversion.primary.revenue_currency` is missing when `is_revenue_tracking` is true.\n- `INVALID_CURRENCY_CODE` — `conversion.primary.revenue_currency` is not a valid ISO 4217 code (e.g. use \"USD\", \"EUR\", \"INR\").\n- `MISSING_IDEMPOTENCY_KEY` — `Idempotency-Key` header is absent. Add the header with a UUID v4 value.\n- `INVALID_IDEMPOTENCY_KEY` — `Idempotency-Key` is present but not a valid UUID v4. Use a standard UUID v4 format (e.g. <uuid-v4>).\n"
          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:\n- **Gateway (APISIX)** — credentials missing or invalid. Returns `Content-Type: text/plain`\n  with body `{\"code\":\"ER001\",\"target\":\"Authentication Invalid\",\"message\":\"...\"}`.\n- **Service** — credentials passed the gateway but the injected `X-MOE-Tenant-ID` header\n  is missing (request bypassed gateway). Returns `Content-Type: application/json`.\n"
          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'
  /v5/offers/{offer_id}:
    patch:
      operationId: updatePublicOffering
      summary: Update Offering
      description: 'Modify an existing offering. Only the fields you include in the request body are

        changed.

        '
      x-mint:
        content: '#### Rate Limit

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

          '
      x-moe-mcp:
        expose:
          external: true
          internal: true
        tool_description: "Partially update an existing offering. Only the fields included in the request body\nare changed — all other fields retain their current values.\n\nUse list_offerings first to discover the offering ID if you don't already have it.\n\nCommon update patterns:\n  - Extend expiry: include only scheduling.expiry_datetime with a later date (Z suffix required)\n  - Rename: include only name (alphanumeric + underscores only; returns DUPLICATE_OFFER_NAME if taken)\n  - Update content: include only offer_content\n  - Replace tags: include tags as a full list of tag IDs (full replacement, not additive).\n    Tag IDs from list_offerings are returned with \"tag_\" prefix (e.g. \"tag_<object-id>\")\n    and can be passed directly — both \"tag_<id>\" and raw \"<id>\" formats are accepted.\n\nStatus-gated fields — return 400 IMMUTABLE_FIELD if violated:\n  - scheduling.start_datetime: locked once status becomes 'active'\n  - conversion: locked once status becomes 'active'\n  - variation_meta.type: locked once status is 'active'\n  - Adding/removing variants in variantsPerLocale: locked once 'active'\n  - ACTIVE + SMV: only

# --- truncated at 32 KB (89 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/moengage/refs/heads/main/openapi/moengage-public-offerings-api-openapi.yml