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

# List Offer Templates

> Fetch the personalization templates available in the workspace.




## OpenAPI

````yaml /api/offerings/offerings.yaml get /v5/offers/templates
openapi: 3.0.0
info:
  title: Offer Decisioning Public API - v5
  version: 5.0.0
  description: >
    `/v5/*` routes serve Public (S2S) and MCP agent consumers only.


    ## Consumer Types



    | Consumer | Gateway | Auth |

    |---|---|---|

    | **Public (S2S)** | APISIX | Basic Auth (`Authorization: Basic
    base64(appId:apiKey)`) |

    | **MCP agents** | SGK | OIDC JWT via MCP Server |


    The gateway (APISIX or SGK) validates credentials and injects trusted
    headers before

    the request reaches this service. The service reads `X-MOE-Consumer-Type`,

    `X-MOE-Tenant-ID`, and `X-MOE-Scopes` — it never re-validates credentials.


    ## Scope Enforcement


    Endpoint-level scope enforcement is performed by the gateway (§4.4 API
    Guidelines).

    A request that reaches this service has already passed the scope check for
    the

    route + method. `X-MOE-Scopes` is available for data-level authorization
    only

    (field filtering, row scoping).


    ## Idempotency


    POST and PATCH operations require an `Idempotency-Key` header (UUID v4
    format).

    The key is validated for presence and format before the handler runs.
    Submitting

    the same key within 24 hours returns the original response without
    re-executing

    the operation. See §7.2 API Guidelines.


    ## Tracing


    Every response includes a `response_id` field. This value is `resp_`
    prefixed to

    the `X-MOE-Request-Id` trace ID supplied by the gateway (or auto-generated
    if not

    supplied). Use `response_id` / `X-MOE-Request-Id` to correlate requests
    across

    logs, client-side retries, and support tickets.


    ## Rate Limits


    | Endpoint | Method | Public (APISIX) | MCP (SGK) |

    |---|---|---|---|

    | `/v5/offers` | GET | 150/min, 500/hour, 1000/day | 150/min, 500/hour,
    1000/day |

    | `/v5/offers/templates` | GET | 150/min, 500/hour, 1000/day | 150/min,
    500/hour, 1000/day |

    | `/v5/offers` | POST | 100/min, 300/hour, 600/day | 100/min, 300/hour,
    600/day |

    | `/v5/offers/{offer_id}` | PATCH | 100/min, 300/hour, 600/day | 100/min,
    300/hour, 600/day |


    Limits are keyed by `tenant_id + client_id` for Public and `tenant_id +
    agent_id` for MCP.

    Rate limit headers (`X-RateLimit-Limit`, `X-RateLimit-Remaining`,
    `X-RateLimit-Reset`)

    are injected by the gateway (APISIX or SGK) — not by this service — on every
    response.


    ## MCP Agent Notes


    **Authentication**: MCP agents must use `bearerAuth` (JWT via SGK), not
    `basicAuth`.

    `basicAuth` is for S2S public consumers only. The MCP server handles token
    injection

    automatically — do not manually set the `Authorization` header.


    **Tenant context**: `X-MOE-Tenant-ID` is injected by SGK from the
    authenticated session.

    Do NOT include this header explicitly — the gateway always provides it.


    **Tag discovery**: Tags must pre-exist before you attach them to an
    offering. Create and

    manage tags in the MoEngage dashboard — unknown tag IDs return 400
    INVALID_TAG_ID.


    **Template discovery**: Before creating `template`-type content, list
    templates from

    `GET /v1/offers/templates` (v1 internal endpoint) to get valid `templateId`
    values.


    ## Security Headers


    Every response from `/v5/*` endpoints includes the following headers set by
    the

    service's `SecurityHeadersFilter`:


    | Header | Value |

    |---|---|

    | `Cache-Control` | `no-store` |

    | `Content-Security-Policy` | `frame-ancestors 'none'` |

    | `Strict-Transport-Security` | `max-age=31536000; includeSubDomains` |

    | `X-Content-Type-Options` | `nosniff` |

    | `X-Frame-Options` | `DENY` |

    | `Referrer-Policy` | `no-referrer` |

    | `X-MOE-Request-Id` | Echoed trace ID from the gateway header |
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/templates:
    get:
      tags:
        - Public Offerings
      summary: List Offer Templates
      description: |
        Fetch the personalization templates available in the workspace.
      operationId: listPublicOfferTemplates
      parameters:
        - name: cursor
          in: query
          required: false
          schema:
            type: string
          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.
        - name: limit
          in: query
          required: false
          schema:
            type: integer
            default: 20
            minimum: 1
            maximum: 100
          description: Number of templates per page. Default 20, maximum 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 and in server logs. If omitted, the
            server generates a trace ID automatically.
      responses:
        '200':
          description: Paginated list of offer templates.
          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. Limits per
                consumer (Public and MCP): 150/min, 500/hour, 1000/day.
            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: >
                      Stable trace identifier for this response. Format: "resp_"
                      + X-MOE-Request-Id. Identical on retries that carry the
                      same X-MOE-Request-Id header, enabling client-side
                      deduplication and cross-log correlation.
                  type:
                    type: string
                    enum:
                      - template
                  data:
                    type: array
                    description: List of templates matching the applied pagination.
                    items:
                      $ref: '#/components/schemas/OfferTemplateListItem'
                  pagination:
                    $ref: '#/components/schemas/CursorPagination'
              example:
                response_id: resp_<trace-id>
                type: template
                data:
                  - id: app_small
                    value: app_small
                    label: App small
                    template_type: []
                pagination:
                  next_cursor: null
                  limit: 20
                  has_more: false
                  total_count: 1
        '400':
          description: >
            Invalid query parameter. Possible error codes in
            `error.details[].code`:

            - `OUT_OF_RANGE` — `limit` > 100.

            - `INVALID_CURSOR` — `cursor` is present but malformed (not valid
            base64, or corrupted segment/id).
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              example:
                error:
                  code: VALIDATION_FAILED
                  message: One or more fields failed validation.
                  doc_url: >-
                    https://www.moengage.com/docs/api/offerings/offerings-overview
                  details:
                    - code: OUT_OF_RANGE
                      target: limit
                      message: limit must be between 1 and 100.
                response_id: resp_<trace-id>
        '401':
          $ref: '#/components/responses/GatewayAuthError'
        '403':
          $ref: '#/components/responses/GatewayAuthError'
        '429':
          description: >
            Rate limit exceeded. Limits per consumer (Public and MCP): 150
            requests/min,

            500 requests/hour, 1000 requests/day. Wait for the number of seconds
            in

            Retry-After before retrying.
          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:
    OfferTemplateListItem:
      description: >
        Summary representation of a personalization template returned in GET
        /v5/offers/templates list responses.
      type: object
      properties:
        id:
          type: string
          description: >
            Caller-assigned natural key for the template (not a prefixed
            ObjectId — §9.3 deviation, intentional). Copy this value verbatim
            into
            offer_content.locales["0"].variations.*.content_1.meta.templateId
            when creating template-type content.
          example: app_small
        value:
          type: string
          description: Identical to id. Present for form-select UI compatibility.
          example: app_small
        label:
          type: string
          description: Human-readable display name of the template.
          example: App small
        template_type:
          type: array
          description: Tags describing where this template can be used. Empty if unset.
          items:
            type: string
          example: []
      example:
        id: app_small
        value: app_small
        label: App small
        template_type: []
    CursorPagination:
      description: Pagination metadata included in list responses.
      type: object
      required:
        - limit
        - has_more
        - total_count
      properties:
        next_cursor:
          type: string
          nullable: true
          description: >
            Opaque cursor pointing to the start of the next page. Pass this
            value as the cursor query parameter on the next request. null when
            there are no more pages.
          example: <base64-encoded-cursor>
        limit:
          type: integer
          description: >-
            Number of items returned per page, matching the limit query
            parameter.
          example: 20
        has_more:
          type: boolean
          description: >
            Whether additional pages exist. When true, pass next_cursor on the
            next request. When false, the current page is the last page.
          example: false
        total_count:
          type: integer
          format: int64
          description: >
            Total number of items matching the applied filters — offerings and
            drafts for the offers list, templates for the templates list.
          example: 42
    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.
  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).

````