# Create handbill configuration

- Operation ID: `createHandbillConfiguration_POST`
- HTTP method: `POST`
- Path: `/v4/promotions/handbill`
- [Human-readable API reference](https://hub.synerise.com/api-reference/loyalty-and-engagement#tag/Handbills/operation/createHandbillConfiguration_POST)

## Self-contained OpenAPI method

The fenced document below contains this method's documentation and all of its local references. It is self-contained; no category or master specification fetch is required.

```yaml
openapi: 3.0.0
info:
  title: Synerise Public API
  version: 1.9.1
paths:
  /v4/promotions/handbill:
    post:
      tags:
        - Handbills
      summary: Create handbill configuration
      description: |
        Create a new handbill configuration for use in handbill-type promotions.

        ---

        **API consumers:** <a href="/api-reference/authorization?tag=Authorization&amp;operationId=profileLogin" target="_blank" rel="noopener">Workspace (Business Profile)</a>, <a href="/api-reference/authorization?tag=Authorization&amp;operationId=userLogin" target="_blank" rel="noopener">Synerise User</a>

        **API key permission required:** `PROMOTIONS_HANDBILL_CREATE`

        **User role permission required:** `campaigns_personalised_promotions: create`
      operationId: createHandbillConfiguration_POST
      security:
        - JWT: []
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - channel
                - status
                - name
                - description
                - controlGroup
                - variants
              properties:
                channel:
                  description: |-
                    Channel of the handbill.
                    * CHECK_IN means that the promotions are offered before a purchase.
                    * CHECK_OUT means that promotions are offered after a purchase, and can be used in a future transaction.
                    * MOBILE is used to deliver promotions to a mobile application.
                  type: string
                  enum:
                    - MOBILE
                    - CHECK_OUT
                    - CHECK_IN
                status:
                  type: string
                  description: Status of the handbill
                  enum:
                    - DRAFT
                    - ACTIVE
                    - INACTIVE
                name:
                  type: string
                  description: Name of the handbill configuration
                description:
                  type: string
                  maxLength: 65535
                  description: Description of the handbill configuration
                controlGroup:
                  nullable: true
                  description: Details of the control group. A control group is the part of profiles who are not offered any promotions so their activity can be compared with promotion-enabled profiles to check a promotion's effectiveness.
                  type: object
                  required:
                    - name
                    - percentage
                  properties:
                    name:
                      type: string
                      description: Name of the control group
                    percentage:
                      type: integer
                      minimum: 0
                      maximum: 100
                      description: The size of the group, in relation to the entire group to which the promotion applies. The control group and the groups for each variant must sum up to 100%.
                variants:
                  type: array
                  description: Variants of the handbill configuration. If you do not want to use variants, send an empty array.
                  maxItems: 10
                  items:
                    type: object
                    description: Handbill variant
                    required:
                      - name
                      - percentage
                      - ai
                      - limits
                      - activity
                    properties:
                      name:
                        type: string
                        description: Name of the variant
                      uuid:
                        type: string
                        format: uuid
                        description: UUID of the variant. Generated automatically. Do not send this field in create/update requests.
                      percentage:
                        type: integer
                        minimum: 0
                        maximum: 100
                        description: The size of the group, in relation to the entire group to which the promotion applies. The control group and the groups for each variant must sum up to 100%.
                      ai:
                        type: object
                        description: Additional configuration for the AI recommendations engine
                        required:
                          - controlVariant
                        properties:
                          controlVariant:
                            type: boolean
                            description: "When `true`, the promotions are assigned at random. When `false`, the promotions are assigned based on the AI recommendations settings: `varietyFactor`, `varietyGroupSize`,`redistributionFrequencyFactor`, `popularityBoosting`."
                          varietyFactor:
                            description: Adjust the variety of returned promotions. The higher the number, the more variety. The choice of promotions is calculated by the AI.
                            type: number
                            minimum: 0
                            maximum: 1
                            example: 0.5
                          varietyGroupSize:
                            description: Defines how many similar items may be recommended. This is calculated in according to `varietyFactor`.
                            type: integer
                            minimum: 1
                            example: 1
                          redistributionFrequencyFactor:
                            description: Allows adjusting the frequency of promotion redistribution. The default value of 1 allows the model to decide how often to redistribute promotions. A value lower than 1 decreases redistribution frequency, a value higher than 1 increases it.
                            type: number
                            minimum: 0.5
                            maximum: 1.5
                            example: 0.5
                          popularityBoosting:
                            description: Allows adjusting how important product popularity is for the promotions model. Higher values increase the importance.
                            type: number
                            minimum: 0
                            maximum: 1
                            example: 1
                      limits:
                        type: object
                        nullable: true
                        description: Daily redemption limits of this variant
                        properties:
                          limitPerDay:
                            type: integer
                            description: The maximum number of times each profile can redeem this handbill in a single day
                            example: 6
                            deprecated: true
                          limitExceptions:
                            type: array
                            description: Days of the week when the limits are different
                            nullable: true
                            items:
                              type: object
                              required:
                                - dayOfWeek
                                - limitPerDay
                              properties:
                                dayOfWeek:
                                  type: integer
                                  description: Day of the week when the exception applies. "1" is Monday.
                                  minimum: 1
                                  maximum: 7
                                  example: 5
                                limitPerDay:
                                  type: integer
                                  example: 8
                                  description: The maximum number of times each profile can redeem this promotion in the day defined for this exception.
                          limitsPerBasket:
                            type: array
                            description: The minimum basket limits that should be met
                            nullable: true
                            items:
                              type: object
                              required:
                                - basketSize
                                - basketValue
                                - condition
                              properties:
                                basketSize:
                                  type: integer
                                  description: Minimum basket size
                                  minimum: 0
                                  example: 12
                                basketValue:
                                  type: number
                                  description: Minimum basket value
                                  minimum: 0
                                  example: 30.5
                                condition:
                                  type: string
                                  description: Condition if minimum values should be conjunction or alternative
                                  enum:
                                    - AND
                                    - OR
                          limitExclusion:
                            type: array
                            description: Items that should not be taken into consideration while calculating basket value and size
                            nullable: true
                            items:
                              type: object
                              required:
                                - catalogId
                              properties:
                                catalogId:
                                  type: number
                                  description: Catalog that the products and/or filters belong to
                                  example: 22424
                                products:
                                  type: array
                                  description: Products that should be excluded
                                  nullable: true
                                  items:
                                    type: string
                                    description: Product reference
                                    example: UGG-BB-PUR-06
                                filters:
                                  type: array
                                  description: Filter ids of products that should be excluded
                                  nullable: true
                                  items:
                                    type: string
                                    description: Filter ids
                                    example: 7c1fbdf6-dd27-11ea-87d0-0242ac130003
                      activity:
                        type: object
                        nullable: true
                        description: Defines how long the handbill promotions remain assigned to the profile after the handbill is generated.
                        properties:
                          lastingType:
                            type: string
                            description: Type of handbill expiration.
                            default: RELATIVE
                            enum:
                              - RELATIVE
                              - CRON
                              - INTERVAL
                          lasting:
                            type: object
                            description: Defines a time period. Required if lastingType is `RELATIVE`.
                            required:
                              - value
                              - unit
                            properties:
                              unit:
                                description: The time unit
                                enum:
                                  - HOURS
                                  - DAYS
                              value:
                                type: integer
                                example: 24
                                description: The amount of time units
                          cronWeekdays:
                            type: array
                            description: 'Used when `"lastingType": "CRON"`. Array of week days when the handbill promotions expire'
                            minItems: 1
                            items:
                              type: integer
                              minimum: 0
                              maximum: 6
                              description: Day of the week in crontab notation (0 is Sunday, 6 is Saturday)
                            example:
                              - 0
                              - 1
                              - 6
                          cronTime:
                            type: string
                            description: 'Used when `"lastingType": "CRON"`. Clock time in UTC when the handbill promotions expire, in HH:MM format.'
                            pattern: ^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$
                            example: 12:34
                          lastingAt:
                            type: string
                            format: date-time
                            description: 'Used when `"lastingType": "RELATIVE"`. Time when the handbill expires.'
                          timeExclusions:
                            type: object
                            nullable: true
                            required:
                              - uuid
                            properties:
                              uuid:
                                type: string
                                format: uuid
                                example: 6a177f3e-748f-44d4-ac30-a457a5199685
                          interval:
                            type: object
                            nullable: true
                            description: 'Used when `"lastingType": "INTERVAL"`. Handbill promotions expire on an every-N-units grid anchored at `anchorDate`. The anchor fixes the cycle phase (weekday/day-of-month + time-of-day) and is preserved across content updates, so re-saving mid-cycle keeps counting from the same anchor. Boundaries are computed in UTC.'
                            required:
                              - every
                              - unit
                              - anchorDate
                            properties:
                              every:
                                type: integer
                                minimum: 1
                                maximum: 260
                                description: The cycle length as a number of units (e.g. every 2 weeks).
                                example: 2
                              unit:
                                description: The interval unit.
                                enum:
                                  - DAYS
                                  - WEEKS
                                  - MONTHS
                                example: WEEKS
                              anchorDate:
                                type: string
                                format: date-time
                                description: "Reference reset datetime defining the cycle phase. Any ISO-8601 datetime is accepted: a zone-less value (e.g. `2026-07-05T23:59:00`) is read as UTC, an explicit offset (e.g. `2026-07-05T23:59:00+02:00`) is normalized to the equivalent UTC instant. Boundaries keep that UTC wall-clock time."
                                example: 2026-07-05T23:59:00Z
                      printout:
                        type: object
                        description: Details for printing the coupon
                        nullable: true
                        required:
                          - template
                        properties:
                          template:
                            type: string
                            description: Template in [Pug format](https://pugjs.org/api/getting-started.html). The template can contain references to variables in the definition of the promotion, for example `promotion.name`, `promotion.tags[1]`. You can also use the [Moment.js library](https://momentjs.com/). The `#{}` elements allow you to insert JS code with the scope limited to `promotion`, `moment`, and `JSON`.
                            example: "|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!"
                          maxLineLength:
                            type: integer
                            description: Maximum number of characters to print on a line
                            example: 18
                          newLineDelimiter:
                            type: string
                            description: Line delimiter
                            example: ;
                      types:
                        type: array
                        nullable: true
                        description: Array of promotions types which will be taken as promotion candidates to assign. When set to null, only promotions with HANDBILL type will be considered as candidates.  For type HANDBILL, promotions are assigned with lasting date calculated by `activity` settings in variant, so all get promotions endpoints consider those dates when filtering by `lastingOnly` flag. For other types than HANDBILL, promotions lasting date is only respected in `/get-for-client/handbill/:handbillUuid` endpoint. Other get promotions endpoints don't filter those promotions by `lastingOnly` flag.
                        items:
                          type: string
                          description: Promotion type
                          enum:
                            - MEMBERS_ONLY
                            - HANDBILL
                            - CUSTOM
                            - GENERAL
                        example:
                          - MEMBERS_ONLY
                          - HANDBILL
                      excludeByAvailableProducts:
                        description: When `true`, promotions aren't generated for items which already belong to another assigned promotion.
                        type: boolean
                        example: true
                        default: true
                        nullable: false
                      slotFilters:
                        type: object
                        description: Slots to include in the coupon
                        nullable: true
                        required:
                          - order
                          - slots
                        properties:
                          order:
                            type: string
                            enum:
                              - GIVEN
                              - AI
                            description: |-
                              The type of slot ordering when they are returned, where:
                                  `GIVEN` - slots are returned in the order they were created
                                  `AI` - order of slots is changed by AI engine score
                          slots:
                            type: array
                            description: Slots in the coupon. You can use them, for example, to create a slot that will only show promotions for a certain brand, and another for all the other brands. This is done by applying filters that include certain promotions.
                            maxItems: 10
                            items:
                              type: object
                              required:
                                - filterId
                                - limit
                              properties:
                                filterId:
                                  description: UUID of a filter with promotions
                                  type: string
                                  format: uuid
                                limit:
                                  description: Number of promotions to be returned a in given slot
                                  type: number
                                  minimum: 1
                                  maximum: 50
                                  example: 5
                                distinctFilter:
                                  type: object
                                  nullable: true
                                  description: "Distinct filter that limits how many promotions from each value of a given field (e.g. brand, category) can appear in the returned set. Rules are applied per field; at most 3 rules allowed, each `field` value must be unique across rules. `elastic: true` relaxes the filter when there are not enough qualifying promotions (may under-fill less); `elastic: false` is strict (may under-fill the slot). A variant-level `distinctFilter` and slot-level `distinctFilter` values are mutually exclusive (XOR): if the variant has a non-null `distinctFilter`, all slot `distinctFilter` values must be null/absent, and `slotFilters` must be present. `levelRangeModifier` is only meaningful when `field` is `category` — it widens or narrows the category level range used for grouping."
                                  required:
                                    - filters
                                    - elastic
                                  properties:
                                    filters:
                                      type: array
                                      description: List of distinct-filter rules. Each rule targets one field. Field values must be unique across rules.
                                      minItems: 1
                                      maxItems: 3
                                      items:
                                        type: object
                                        required:
                                          - field
                                          - maxNumItems
                                        properties:
                                          field:
                                            type: string
                                            minLength: 1
                                            description: The promotion attribute to group by (e.g. `brand`, `category`).
                                            example: brand
                                          maxNumItems:
                                            type: integer
                                            minimum: 1
                                            description: Maximum number of promotions allowed from each distinct value of this field.
                                            example: 2
                                          levelRangeModifier:
                                            type: integer
                                            description: Only applicable when `field` is `category`. Adjusts the category level range used for grouping. Must not be present when `field` is not `category`.
                                            example: 1
                                    elastic:
                                      type: boolean
                                      description: When `true`, the filter is relaxed if not enough promotions qualify — the slot may be filled with additional promotions beyond the per-value limit. When `false`, the filter is strict — the slot may be under-filled if there are insufficient qualifying promotions.
                                      example: true
                                fallback:
                                  type: object
                                  nullable: true
                                  description: |-
                                    Opt-in per-slot fallback pool (default off) — the last, additive selection step (main filter → distinct filter → elastic relaxation → fallback pool). It runs in two situations:

                                    1. **Shortfall** — the normal path succeeded but returned fewer promotions than `limit`. Only the residual gap is drawn from the pool. Example: `limit: 5`, AI returns 4 promotions → 1 promotion is drawn from the pool; the 4 AI picks are kept.
                                    2. **Recovered error** — the normal path failed with a recoverable error (e.g. AI service unavailable). Slots with a pool are then filled entirely from their pools and supersede the whole-variant random fill; slots without a pool stay empty. Example: 2 slots, AI call fails — the slot with a pool returns `limit` promotions from the pool, the slot without one returns nothing.

                                    Draw semantics: candidates from the pool filter pass the standard eligibility checks (validity windows, displayable, target segment, behavioral filter, exclusion of already activated/redeemed promotions) and are drawn deterministically by `priority` asc, `id` asc. A promotion already chosen in this response (by any slot or handbill of the request) is never drawn again. Distinct-filter constraints and catalog-item deduplication are NOT applied to pool draws. An exhausted pool leaves the slot partially filled; a pool fetch/draw failure never fails the request. Control-group variants skip pools entirely. Pools are client-scoped — anonymous assignment (basket-based, no client) skips them.

                                    Pool-drawn items carry `extra.assignmentSource: fallback_pool` and `extra.slotFilterId` set to this pool's `filterId` in client responses.
                                  required:
                                    - filterId
                                  properties:
                                    filterId:
                                      description: UUID of the fallback filter with promotions to draw from
                                      type: string
                                      format: uuid
                                      example: 3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c
                      distinctFilter:
                        type: object
                        nullable: true
                        description: "Distinct filter that limits how many promotions from each value of a given field (e.g. brand, category) can appear in the returned set. Rules are applied per field; at most 3 rules allowed, each `field` value must be unique across rules. `elastic: true` relaxes the filter when there are not enough qualifying promotions (may under-fill less); `elastic: false` is strict (may under-fill the slot). A variant-level `distinctFilter` and slot-level `distinctFilter` values are mutually exclusive (XOR): if the variant has a non-null `distinctFilter`, all slot `distinctFilter` values must be null/absent, and `slotFilters` must be present. `levelRangeModifier` is only meaningful when `field` is `category` — it widens or narrows the category level range used for grouping."
                        required:
                          - filters
                          - elastic
                        properties:
                          filters:
                            type: array
                            description: List of distinct-filter rules. Each rule targets one field. Field values must be unique across rules.
                            minItems: 1
                            maxItems: 3
                            items:
                              type: object
                              required:
                                - field
                                - maxNumItems
                              properties:
                                field:
                                  type: string
                                  minLength: 1
                                  description: The promotion attribute to group by (e.g. `brand`, `category`).
                                  example: brand
                                maxNumItems:
                                  type: integer
                                  minimum: 1
                                  description: Maximum number of promotions allowed from each distinct value of this field.
                                  example: 2
                                levelRangeModifier:
                                  type: integer
                                  description: Only applicable when `field` is `category`. Adjusts the category level range used for grouping. Must not be present when `field` is not `category`.
                                  example: 1
                          elastic:
                            type: boolean
                            description: When `true`, the filter is relaxed if not enough promotions qualify — the slot may be filled with additional promotions beyond the per-value limit. When `false`, the filter is strict — the slot may be under-filled if there are insufficient qualifying promotions.
                            example: true
      responses:
        "201":
          description: Configuration created
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    description: Details of a single handbill configuration
                    properties:
                      uuid:
                        type: string
                        format: uuid
                        description: UUID of the variant. Generated automatically.
                      createdAt:
                        type: string
                        format: date-time
                        description: Time when the object was created
                      updatedAt:
                        type: string
                        format: date-time
                        description: Time when the object was last updated
                      channel:
                        description: |-
                          Channel of the handbill.
                          * CHECK_IN means that the promotions are offered before a purchase.
                          * CHECK_OUT means that promotions are offered after a purchase, and can be used in a future transaction.
                          * MOBILE is used to deliver promotions to a mobile application.
                        type: string
                        enum:
                          - MOBILE
                          - CHECK_OUT
                          - CHECK_IN
                      status:
                        type: string
                        description: Status of the handbill
                        enum:
                          - DRAFT
                          - ACTIVE
                          - INACTIVE
                      userId:
                        type: integer
                        nullable: true
                        description: ID of the user who created this object or the last user who updated it, if applicable
                      origin:
                        type: string
                        enum:
                          - USER
                          - PROFILE
                        description: Informs if this object was created/updated by a User or a Workspace.
                      name:
                        type: string
                        description: Name of the handbill configuration
                      description:
                        type: string
                        maxLength: 65535
                        description: Description of the handbill configuration
                      controlGroup:
                        nullable: true
                        description: Details of the control group. A control group is the part of profiles who are not offered any promotions so their activity can be compared with promotion-enabled profiles to check a promotion's effectiveness.
                        type: object
                        required:
                          - name
                          - percentage
                        properties:
                          name:
                            type: string
                            description: Name of the control group
                          percentage:
                            type: integer
                            minimum: 0
                            maximum: 100
                            description: The size of the group, in relation to the entire group to which the promotion applies. The control group and the groups for each variant must sum up to 100%.
                      variants:
                        type: array
                        description: Variants of the handbill configuration. If you do not want to use variants, send an empty array.
                        maxItems: 10
                        items:
                          type: object
                          description: Handbill variant
                          required:
                            - name
                            - percentage
                            - ai
                            - limits
                            - activity
                          properties:
                            name:
                              type: string
                              description: Name of the variant
                            uuid:
                              type: string
                              format: uuid
                              description: UUID of the variant. Generated automatically. Do not send this field in create/update requests.
                            percentage:
                              type: integer
                              minimum: 0
                              maximum: 100
                              description: The size of the group, in relation to the entire group to which the promotion applies. The control group and the groups for each variant must sum up to 100%.
                            ai:
                              type: object
                              description: Additional configuration for the AI recommendations engine
                              required:
                                - controlVariant
                              properties:
                                controlVariant:
                                  type: boolean
                                  description: "When `true`, the promotions are assigned at random. When `false`, the promotions are assigned based on the AI recommendations settings: `varietyFactor`, `varietyGroupSize`,`redistributionFrequencyFactor`, `popularityBoosting`."
                                varietyFactor:
                                  description: Adjust the variety of returned promotions. The higher the number, the more variety. The choice of promotions is calculated by the AI.
                                  type: number
                                  minimum: 0
                                  maximum: 1
                                  example: 0.5
                                varietyGroupSize:
                                  description: Defines how many similar items may be recommended. This is calculated in according to `varietyFactor`.
                                  type: integer
                                  minimum: 1
                                  example: 1
                                redistributionFrequencyFactor:
                                  description: Allows adjusting the frequency of promotion redistribution. The default value of 1 allows the model to decide how often to redistribute promotions. A value lower than 1 decreases redistribution frequency, a value higher than 1 increases it.
                                  type: number
                                  minimum: 0.5
                                  maximum: 1.5
                                  example: 0.5
                                popularityBoosting:
                                  description: Allows adjusting how important product popularity is for the promotions model. Higher values increase the importance.
                                  type: number
                                  minimum: 0
                                  maximum: 1
                                  example: 1
                            limits:
                              type: object
                              nullable: true
                              description: Daily redemption limits of this variant
                              properties:
                                limitPerDay:
                                  type: integer
                                  description: The maximum number of times each profile can redeem this handbill in a single day
                                  example: 6
                                  deprecated: true
                                limitExceptions:
                                  type: array
                                  description: Days of the week when the limits are different
                                  nullable: true
                                  items:
                                    type: object
                                    required:
                                      - dayOfWeek
                                      - limitPerDay
                                    properties:
                                      dayOfWeek:
                                        type: integer
                                        description: Day of the week when the exception applies. "1" is Monday.
                                        minimum: 1
                                        maximum: 7
                                        example: 5
                                      limitPerDay:
                                        type: integer
                                        example: 8
                                        description: The maximum number of times each profile can redeem this promotion in the day defined for this exception.
                                limitsPerBasket:
                                  type: array
                                  description: The minimum basket limits that should be met
                                  nullable: true
                                  items:
                                    type: object
                                    required:
                                      - basketSize
                                      - basketValue
                                      - condition
                                    properties:
                                      basketSize:
                                        type: integer
                                        description: Minimum basket size
                                        minimum: 0
                                        example: 12
                                      basketValue:
                                        type: number
                                        description: Minimum basket value
                                        minimum: 0
                                        example: 30.5
                                      condition:
                                        type: string
                                        description: Condition if minimum values should be conjunction or alternative
                                        enum:
                                          - AND
                                          - OR
                                limitExclusion:
                                  type: array
                                  description: Items that should not be taken into consideration while calculating basket value and size
                                  nullable: true
                                  items:
                                    type: object
                                    required:
                                      - catalogId
                                    properties:
                                      catalogId:
                                        type: number
                                        description: Catalog that the products and/or filters belong to
                                        example: 22424
                                      products:
                                        type: array
                                        description: Products that should be excluded
                                        nullable: true
                                        items:
                                          type: string
                                          description: Product reference
                                          example: UGG-BB-PUR-06
                                      filters:
                                        type: array
                                        description: Filter ids of products that should be excluded
                                        nullable: true
                                        items:
                                          type: string
                                          description: Filter ids
                                          example: 7c1fbdf6-dd27-11ea-87d0-0242ac130003
                            activity:
                              type: object
                              nullable: true
                              description: Defines how long the handbill promotions remain assigned to the profile after the handbill is generated.
                              properties:
                                lastingType:
                                  type: string
                                  description: Type of handbill expiration.
                                  default: RELATIVE
                                  enum:
                                    - RELATIVE
                                    - CRON
                                    - INTERVAL
                                lasting:
                                  type: object
                                  description: Defines a time period. Required if lastingType is `RELATIVE`.
                                  required:
                                    - value
                                    - unit
                                  properties:
                                    unit:
                                      description: The time unit
                                      enum:
                                        - HOURS
                                        - DAYS
                                    value:
                                      type: integer
                                      example: 24
                                      description: The amount of time units
                                cronWeekdays:
                                  type: array
                                  description: 'Used when `"lastingType": "CRON"`. Array of week days when the handbill promotions expire'
                                  minItems: 1
                                  items:
                                    type: integer
                                    minimum: 0
                                    maximum: 6
                                    description: Day of the week in crontab notation (0 is Sunday, 6 is Saturday)
                                  example:
                                    - 0
                                    - 1
                                    - 6
                                cronTime:
                                  type: string
                                  description: 'Used when `"lastingType": "CRON"`. Clock time in UTC when the handbill promotions expire, in HH:MM format.'
                                  pattern: ^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$
                                  example: 12:34
                                lastingAt:
                                  type: string
                                  format: date-time
                                  description: 'Used when `"lastingType": "RELATIVE"`. Time when the handbill expires.'
                                timeExclusions:
                                  type: object
                                  nullable: true
                                  required:
                                    - uuid
                                  properties:
                                    uuid:
                                      type: string
                                      format: uuid
                                      example: 6a177f3e-748f-44d4-ac30-a457a5199685
                                interval:
                                  type: object
                                  nullable: true
                                  description: 'Used when `"lastingType": "INTERVAL"`. Handbill promotions expire on an every-N-units grid anchored at `anchorDate`. The anchor fixes the cycle phase (weekday/day-of-month + time-of-day) and is preserved across content updates, so re-saving mid-cycle keeps counting from the same anchor. Boundaries are computed in UTC.'
                                  required:
                                    - every
                                    - unit
                                    - anchorDate
                                  properties:
                                    every:
                                      type: integer
                                      minimum: 1
                                      maximum: 260
                                      description: The cycle length as a number of units (e.g. every 2 weeks).
                                      example: 2
                                    unit:
                                      description: The interval unit.
                                      enum:
                                        - DAYS
                                        - WEEKS
                                        - MONTHS
                                      example: WEEKS
                                    anchorDate:
                                      type: string
                                      format: date-time
                                      description: "Reference reset datetime defining the cycle phase. Any ISO-8601 datetime is accepted: a zone-less value (e.g. `2026-07-05T23:59:00`) is read as UTC, an explicit offset (e.g. `2026-07-05T23:59:00+02:00`) is normalized to the equivalent UTC instant. Boundaries keep that UTC wall-clock time."
                                      example: 2026-07-05T23:59:00Z
                            printout:
                              type: object
                              description: Details for printing the coupon
                              nullable: true
                              required:
                                - template
                              properties:
                                template:
                                  type: string
                                  description: Template in [Pug format](https://pugjs.org/api/getting-started.html). The template can contain references to variables in the definition of the promotion, for example `promotion.name`, `promotion.tags[1]`. You can also use the [Moment.js library](https://momentjs.com/). The `#{}` elements allow you to insert JS code with the scope limited to `promotion`, `moment`, and `JSON`.
                                  example: "|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!"
                                maxLineLength:
                                  type: integer
                                  description: Maximum number of characters to print on a line
                                  example: 18
                                newLineDelimiter:
                                  type: string
                                  description: Line delimiter
                                  example: ;
                            types:
                              type: array
                              nullable: true
                              description: Array of promotions types which will be taken as promotion candidates to assign. When set to null, only promotions with HANDBILL type will be considered as candidates.  For type HANDBILL, promotions are assigned with lasting date calculated by `activity` settings in variant, so all get promotions endpoints consider those dates when filtering by `lastingOnly` flag. For other types than HANDBILL, promotions lasting date is only respected in `/get-for-client/handbill/:handbillUuid` endpoint. Other get promotions endpoints don't filter those promotions by `lastingOnly` flag.
                              items:
                                type: string
                                description: Promotion type
                                enum:
                                  - MEMBERS_ONLY
                                  - HANDBILL
                                  - CUSTOM
                                  - GENERAL
                              example:
                                - MEMBERS_ONLY
                                - HANDBILL
                            excludeByAvailableProducts:
                              description: When `true`, promotions aren't generated for items which already belong to another assigned promotion.
                              type: boolean
                              example: true
                              default: true
                              nullable: false
                            slotFilters:
                              type: object
                              description: Slots to include in the coupon
                              nullable: true
                              required:
                                - order
                                - slots
                              properties:
                                order:
                                  type: string
                                  enum:
                                    - GIVEN
                                    - AI
                                  description: |-
                                    The type of slot ordering when they are returned, where:
                                        `GIVEN` - slots are returned in the order they were created
                                        `AI` - order of slots is changed by AI engine score
                                slots:
                                  type: array
                                  description: Slots in the coupon. You can use them, for example, to create a slot that will only show promotions for a certain brand, and another for all the other brands. This is done by applying filters that include certain promotions.
                                  maxItems: 10
                                  items:
                                    type: object
                                    required:
                                      - filterId
                                      - limit
                                    properties:
                                      filterId:
                                        description: UUID of a filter with promotions
                                        type: string
                                        format: uuid
                                      limit:
                                        description: Number of promotions to be returned a in given slot
                                        type: number
                                        minimum: 1
                                        maximum: 50
                                        example: 5
                                      distinctFilter:
                                        type: object
                                        nullable: true
                                        description: "Distinct filter that limits how many promotions from each value of a given field (e.g. brand, category) can appear in the returned set. Rules are applied per field; at most 3 rules allowed, each `field` value must be unique across rules. `elastic: true` relaxes the filter when there are not enough qualifying promotions (may under-fill less); `elastic: false` is strict (may under-fill the slot). A variant-level `distinctFilter` and slot-level `distinctFilter` values are mutually exclusive (XOR): if the variant has a non-null `distinctFilter`, all slot `distinctFilter` values must be null/absent, and `slotFilters` must be present. `levelRangeModifier` is only meaningful when `field` is `category` — it widens or narrows the category level range used for grouping."
                                        required:
                                          - filters
                                          - elastic
                                        properties:
                                          filters:
                                            type: array
                                            description: List of distinct-filter rules. Each rule targets one field. Field values must be unique across rules.
                                            minItems: 1
                                            maxItems: 3
                                            items:
                                              type: object
                                              required:
                                                - field
                                                - maxNumItems
                                              properties:
                                                field:
                                                  type: string
                                                  minLength: 1
                                                  description: The promotion attribute to group by (e.g. `brand`, `category`).
                                                  example: brand
                                                maxNumItems:
                                                  type: integer
                                                  minimum: 1
                                                  description: Maximum number of promotions allowed from each distinct value of this field.
                                                  example: 2
                                                levelRangeModifier:
                                                  type: integer
                                                  description: Only applicable when `field` is `category`. Adjusts the category level range used for grouping. Must not be present when `field` is not `category`.
                                                  example: 1
                                          elastic:
                                            type: boolean
                                            description: When `true`, the filter is relaxed if not enough promotions qualify — the slot may be filled with additional promotions beyond the per-value limit. When `false`, the filter is strict — the slot may be under-filled if there are insufficient qualifying promotions.
                                            example: true
                                      fallback:
                                        type: object
                                        nullable: true
                                        description: |-
                                          Opt-in per-slot fallback pool (default off) — the last, additive selection step (main filter → distinct filter → elastic relaxation → fallback pool). It runs in two situations:

                                          1. **Shortfall** — the normal path succeeded but returned fewer promotions than `limit`. Only the residual gap is drawn from the pool. Example: `limit: 5`, AI returns 4 promotions → 1 promotion is drawn from the pool; the 4 AI picks are kept.
                                          2. **Recovered error** — the normal path failed with a recoverable error (e.g. AI service unavailable). Slots with a pool are then filled entirely from their pools and supersede the whole-variant random fill; slots without a pool stay empty. Example: 2 slots, AI call fails — the slot with a pool returns `limit` promotions from the pool, the slot without one returns nothing.

                                          Draw semantics: candidates from the pool filter pass the standard eligibility checks (validity windows, displayable, target segment, behavioral filter, exclusion of already activated/redeemed promotions) and are drawn deterministically by `priority` asc, `id` asc. A promotion already chosen in this response (by any slot or handbill of the request) is never drawn again. Distinct-filter constraints and catalog-item deduplication are NOT applied to pool draws. An exhausted pool leaves the slot partially filled; a pool fetch/draw failure never fails the request. Control-group variants skip pools entirely. Pools are client-scoped — anonymous assignment (basket-based, no client) skips them.

                                          Pool-drawn items carry `extra.assignmentSource: fallback_pool` and `extra.slotFilterId` set to this pool's `filterId` in client responses.
                                        required:
                                          - filterId
                                        properties:
                                          filterId:
                                            description: UUID of the fallback filter with promotions to draw from
                                            type: string
                                            format: uuid
                                            example: 3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c
                            distinctFilter:
                              type: object
                              nullable: true
                              description: "Distinct filter that limits how many promotions from each value of a given field (e.g. brand, category) can appear in the returned set. Rules are applied per field; at most 3 rules allowed, each `field` value must be unique across rules. `elastic: true` relaxes the filter when there are not enough qualifying promotions (may under-fill less); `elastic: false` is strict (may under-fill the slot). A variant-level `distinctFilter` and slot-level `distinctFilter` values are mutually exclusive (XOR): if the variant has a non-null `distinctFilter`, all slot `distinctFilter` values must be null/absent, and `slotFilters` must be present. `levelRangeModifier` is only meaningful when `field` is `category` — it widens or narrows the category level range used for grouping."
                              required:
                                - filters
                                - elastic
                              properties:
                                filters:
                                  type: array
                                  description: List of distinct-filter rules. Each rule targets one field. Field values must be unique across rules.
                                  minItems: 1
                                  maxItems: 3
                                  items:
                                    type: object
                                    required:
                                      - field
                                      - maxNumItems
                                    properties:
                                      field:
                                        type: string
                                        minLength: 1
                                        description: The promotion attribute to group by (e.g. `brand`, `category`).
                                        example: brand
                                      maxNumItems:
                                        type: integer
                                        minimum: 1
                                        description: Maximum number of promotions allowed from each distinct value of this field.
                                        example: 2
                                      levelRangeModifier:
                                        type: integer
                                        description: Only applicable when `field` is `category`. Adjusts the category level range used for grouping. Must not be present when `field` is not `category`.
                                        example: 1
                                elastic:
                                  type: boolean
                                  description: When `true`, the filter is relaxed if not enough promotions qualify — the slot may be filled with additional promotions beyond the per-value limit. When `false`, the filter is strict — the slot may be under-filled if there are insufficient qualifying promotions.
                                  example: true
                  message:
                    type: string
                    description: Status of the operation
        "400":
          description: JSON is null
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    enum:
                      - Invalid parameter
        "401":
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    description: HTTP code of the problem
                  error:
                    type: string
                    description: Summary of the error
                  message:
                    type: string
                    description: Error details
                  timestamp:
                    type: string
                    description: Time when the error occurred
        "403":
          description: Forbidden
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: integer
                    description: HTTP code of the problem
                  error:
                    type: string
                    description: Summary of the error
                  message:
                    type: string
                    description: Error details
                  timestamp:
                    type: string
                    description: Time when the error occurred
        "422":
          description: "Request payload failed schema validation, for example: missing required value, wrong data type"
          content:
            application/json:
              schema:
                type: object
                properties:
                  statusCode:
                    type: number
                    enum:
                      - 422
                  error:
                    type: string
                    enum:
                      - Unprocessable Entity
                  message:
                    type: string
                    enum:
                      - validation failed
      x-snr-doc-urls:
        - /api-reference/loyalty-and-engagement#tag/Handbills/operation/createHandbillConfiguration_POST
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |-
            curl --request POST \
              --url https://api.synerise.com/v4/promotions/handbill \
              --header 'Authorization: Bearer REPLACE_BEARER_TOKEN' \
              --header 'content-type: application/json' \
              --data '{"channel":"MOBILE","status":"DRAFT","name":"string","description":"string","controlGroup":{"name":"string","percentage":100},"variants":[{"name":"string","uuid":"095be615-a8ad-4c33-8e9c-c7612fbf6c9f","percentage":100,"ai":{"controlVariant":true,"varietyFactor":0.5,"varietyGroupSize":1,"redistributionFrequencyFactor":0.5,"popularityBoosting":1},"limits":{"limitPerDay":6,"limitExceptions":[{"dayOfWeek":5,"limitPerDay":8}],"limitsPerBasket":[{"basketSize":12,"basketValue":30.5,"condition":"AND"}],"limitExclusion":[{"catalogId":22424,"products":["UGG-BB-PUR-06"],"filters":["7c1fbdf6-dd27-11ea-87d0-0242ac130003"]}]},"activity":{"lastingType":"RELATIVE","lasting":{"unit":"HOURS","value":24},"cronWeekdays":[0,1,6],"cronTime":"12:34","lastingAt":"2019-08-24T14:15:22Z","timeExclusions":{"uuid":"6a177f3e-748f-44d4-ac30-a457a5199685"},"interval":{"every":2,"unit":"WEEKS","anchorDate":"2026-07-05T23:59:00Z"}},"printout":{"template":"|#{promotion.name};#{promotion.discountType == '\''EXACT_PRICE'\'' ? '\''Price'\'':'\''Discount'\''} #{promotion.discountValue} #{promotion.discountType == '\''PERCENT'\''? '\''%'\'' : '\''USD'\''};Valid for;#{moment.utc(coupon.createdAt).tz('\''Europe/Warsaw'\'').format('\''DD.MM.YYYY HH:mm'\'')} - #{moment.utc(coupon.lastingAt).tz('\''Europe/Warsaw'\'').format('\''DD.MM.YYYY HH:mm'\'')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!","maxLineLength":18,"newLineDelimiter":";"},"types":["MEMBERS_ONLY","HANDBILL"],"excludeByAvailableProducts":true,"slotFilters":{"order":"GIVEN","slots":[{"filterId":"aff0ee0f-f371-4b82-82c6-dc3b96f05c91","limit":5,"distinctFilter":{"filters":[{"field":"brand","maxNumItems":2,"levelRangeModifier":1}],"elastic":true},"fallback":{"filterId":"3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c"}}]},"distinctFilter":{"filters":[{"field":"brand","maxNumItems":2,"levelRangeModifier":1}],"elastic":true}}]}'
        - lang: Python
          label: Python
          source: |-
            import http.client

            conn = http.client.HTTPSConnection("api.synerise.com")

            payload = "{\"channel\":\"MOBILE\",\"status\":\"DRAFT\",\"name\":\"string\",\"description\":\"string\",\"controlGroup\":{\"name\":\"string\",\"percentage\":100},\"variants\":[{\"name\":\"string\",\"uuid\":\"095be615-a8ad-4c33-8e9c-c7612fbf6c9f\",\"percentage\":100,\"ai\":{\"controlVariant\":true,\"varietyFactor\":0.5,\"varietyGroupSize\":1,\"redistributionFrequencyFactor\":0.5,\"popularityBoosting\":1},\"limits\":{\"limitPerDay\":6,\"limitExceptions\":[{\"dayOfWeek\":5,\"limitPerDay\":8}],\"limitsPerBasket\":[{\"basketSize\":12,\"basketValue\":30.5,\"condition\":\"AND\"}],\"limitExclusion\":[{\"catalogId\":22424,\"products\":[\"UGG-BB-PUR-06\"],\"filters\":[\"7c1fbdf6-dd27-11ea-87d0-0242ac130003\"]}]},\"activity\":{\"lastingType\":\"RELATIVE\",\"lasting\":{\"unit\":\"HOURS\",\"value\":24},\"cronWeekdays\":[0,1,6],\"cronTime\":\"12:34\",\"lastingAt\":\"2019-08-24T14:15:22Z\",\"timeExclusions\":{\"uuid\":\"6a177f3e-748f-44d4-ac30-a457a5199685\"},\"interval\":{\"every\":2,\"unit\":\"WEEKS\",\"anchorDate\":\"2026-07-05T23:59:00Z\"}},\"printout\":{\"template\":\"|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!\",\"maxLineLength\":18,\"newLineDelimiter\":\";\"},\"types\":[\"MEMBERS_ONLY\",\"HANDBILL\"],\"excludeByAvailableProducts\":true,\"slotFilters\":{\"order\":\"GIVEN\",\"slots\":[{\"filterId\":\"aff0ee0f-f371-4b82-82c6-dc3b96f05c91\",\"limit\":5,\"distinctFilter\":{\"filters\":[{\"field\":\"brand\",\"maxNumItems\":2,\"levelRangeModifier\":1}],\"elastic\":true},\"fallback\":{\"filterId\":\"3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c\"}}]},\"distinctFilter\":{\"filters\":[{\"field\":\"brand\",\"maxNumItems\":2,\"levelRangeModifier\":1}],\"elastic\":true}}]}"

            headers = {
                'Authorization': "Bearer REPLACE_BEARER_TOKEN",
                'content-type': "application/json"
                }

            conn.request("POST", "/v4/promotions/handbill", payload, headers)

            res = conn.getresponse()
            data = res.read()

            print(data.decode("utf-8"))
        - lang: JavaScript
          label: JavaScript
          source: |-
            const data = JSON.stringify({
              "channel": "MOBILE",
              "status": "DRAFT",
              "name": "string",
              "description": "string",
              "controlGroup": {
                "name": "string",
                "percentage": 100
              },
              "variants": [
                {
                  "name": "string",
                  "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
                  "percentage": 100,
                  "ai": {
                    "controlVariant": true,
                    "varietyFactor": 0.5,
                    "varietyGroupSize": 1,
                    "redistributionFrequencyFactor": 0.5,
                    "popularityBoosting": 1
                  },
                  "limits": {
                    "limitPerDay": 6,
                    "limitExceptions": [
                      {
                        "dayOfWeek": 5,
                        "limitPerDay": 8
                      }
                    ],
                    "limitsPerBasket": [
                      {
                        "basketSize": 12,
                        "basketValue": 30.5,
                        "condition": "AND"
                      }
                    ],
                    "limitExclusion": [
                      {
                        "catalogId": 22424,
                        "products": [
                          "UGG-BB-PUR-06"
                        ],
                        "filters": [
                          "7c1fbdf6-dd27-11ea-87d0-0242ac130003"
                        ]
                      }
                    ]
                  },
                  "activity": {
                    "lastingType": "RELATIVE",
                    "lasting": {
                      "unit": "HOURS",
                      "value": 24
                    },
                    "cronWeekdays": [
                      0,
                      1,
                      6
                    ],
                    "cronTime": "12:34",
                    "lastingAt": "2019-08-24T14:15:22Z",
                    "timeExclusions": {
                      "uuid": "6a177f3e-748f-44d4-ac30-a457a5199685"
                    },
                    "interval": {
                      "every": 2,
                      "unit": "WEEKS",
                      "anchorDate": "2026-07-05T23:59:00Z"
                    }
                  },
                  "printout": {
                    "template": "|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!",
                    "maxLineLength": 18,
                    "newLineDelimiter": ";"
                  },
                  "types": [
                    "MEMBERS_ONLY",
                    "HANDBILL"
                  ],
                  "excludeByAvailableProducts": true,
                  "slotFilters": {
                    "order": "GIVEN",
                    "slots": [
                      {
                        "filterId": "aff0ee0f-f371-4b82-82c6-dc3b96f05c91",
                        "limit": 5,
                        "distinctFilter": {
                          "filters": [
                            {
                              "field": "brand",
                              "maxNumItems": 2,
                              "levelRangeModifier": 1
                            }
                          ],
                          "elastic": true
                        },
                        "fallback": {
                          "filterId": "3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c"
                        }
                      }
                    ]
                  },
                  "distinctFilter": {
                    "filters": [
                      {
                        "field": "brand",
                        "maxNumItems": 2,
                        "levelRangeModifier": 1
                      }
                    ],
                    "elastic": true
                  }
                }
              ]
            });

            const xhr = new XMLHttpRequest();
            xhr.withCredentials = true;

            xhr.addEventListener("readystatechange", function () {
              if (this.readyState === this.DONE) {
                console.log(this.responseText);
              }
            });

            xhr.open("POST", "https://api.synerise.com/v4/promotions/handbill");
            xhr.setRequestHeader("Authorization", "Bearer REPLACE_BEARER_TOKEN");
            xhr.setRequestHeader("content-type", "application/json");

            xhr.send(data);
        - lang: Node.js
          label: Node.js
          source: |-
            const http = require("https");

            const options = {
              "method": "POST",
              "hostname": "api.synerise.com",
              "port": null,
              "path": "/v4/promotions/handbill",
              "headers": {
                "Authorization": "Bearer REPLACE_BEARER_TOKEN",
                "content-type": "application/json"
              }
            };

            const req = http.request(options, function (res) {
              const chunks = [];

              res.on("data", function (chunk) {
                chunks.push(chunk);
              });

              res.on("end", function () {
                const body = Buffer.concat(chunks);
                console.log(body.toString());
              });
            });

            req.write(JSON.stringify({
              channel: 'MOBILE',
              status: 'DRAFT',
              name: 'string',
              description: 'string',
              controlGroup: {name: 'string', percentage: 100},
              variants: [
                {
                  name: 'string',
                  uuid: '095be615-a8ad-4c33-8e9c-c7612fbf6c9f',
                  percentage: 100,
                  ai: {
                    controlVariant: true,
                    varietyFactor: 0.5,
                    varietyGroupSize: 1,
                    redistributionFrequencyFactor: 0.5,
                    popularityBoosting: 1
                  },
                  limits: {
                    limitPerDay: 6,
                    limitExceptions: [{dayOfWeek: 5, limitPerDay: 8}],
                    limitsPerBasket: [{basketSize: 12, basketValue: 30.5, condition: 'AND'}],
                    limitExclusion: [
                      {
                        catalogId: 22424,
                        products: ['UGG-BB-PUR-06'],
                        filters: ['7c1fbdf6-dd27-11ea-87d0-0242ac130003']
                      }
                    ]
                  },
                  activity: {
                    lastingType: 'RELATIVE',
                    lasting: {unit: 'HOURS', value: 24},
                    cronWeekdays: [0, 1, 6],
                    cronTime: '12:34',
                    lastingAt: '2019-08-24T14:15:22Z',
                    timeExclusions: {uuid: '6a177f3e-748f-44d4-ac30-a457a5199685'},
                    interval: {every: 2, unit: 'WEEKS', anchorDate: '2026-07-05T23:59:00Z'}
                  },
                  printout: {
                    template: '|#{promotion.name};#{promotion.discountType == \'EXACT_PRICE\' ? \'Price\':\'Discount\'} #{promotion.discountValue} #{promotion.discountType == \'PERCENT\'? \'%\' : \'USD\'};Valid for;#{moment.utc(coupon.createdAt).tz(\'Europe/Warsaw\').format(\'DD.MM.YYYY HH:mm\')} - #{moment.utc(coupon.lastingAt).tz(\'Europe/Warsaw\').format(\'DD.MM.YYYY HH:mm\')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!',
                    maxLineLength: 18,
                    newLineDelimiter: ';'
                  },
                  types: ['MEMBERS_ONLY', 'HANDBILL'],
                  excludeByAvailableProducts: true,
                  slotFilters: {
                    order: 'GIVEN',
                    slots: [
                      {
                        filterId: 'aff0ee0f-f371-4b82-82c6-dc3b96f05c91',
                        limit: 5,
                        distinctFilter: {
                          filters: [{field: 'brand', maxNumItems: 2, levelRangeModifier: 1}],
                          elastic: true
                        },
                        fallback: {filterId: '3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c'}
                      }
                    ]
                  },
                  distinctFilter: {
                    filters: [{field: 'brand', maxNumItems: 2, levelRangeModifier: 1}],
                    elastic: true
                  }
                }
              ]
            }));
            req.end();
        - lang: PHP
          label: PHP
          source: |-
            <?php

            $request = new HttpRequest();
            $request->setUrl('https://api.synerise.com/v4/promotions/handbill');
            $request->setMethod(HTTP_METH_POST);

            $request->setHeaders([
              'Authorization' => 'Bearer REPLACE_BEARER_TOKEN',
              'content-type' => 'application/json'
            ]);

            $request->setBody('{"channel":"MOBILE","status":"DRAFT","name":"string","description":"string","controlGroup":{"name":"string","percentage":100},"variants":[{"name":"string","uuid":"095be615-a8ad-4c33-8e9c-c7612fbf6c9f","percentage":100,"ai":{"controlVariant":true,"varietyFactor":0.5,"varietyGroupSize":1,"redistributionFrequencyFactor":0.5,"popularityBoosting":1},"limits":{"limitPerDay":6,"limitExceptions":[{"dayOfWeek":5,"limitPerDay":8}],"limitsPerBasket":[{"basketSize":12,"basketValue":30.5,"condition":"AND"}],"limitExclusion":[{"catalogId":22424,"products":["UGG-BB-PUR-06"],"filters":["7c1fbdf6-dd27-11ea-87d0-0242ac130003"]}]},"activity":{"lastingType":"RELATIVE","lasting":{"unit":"HOURS","value":24},"cronWeekdays":[0,1,6],"cronTime":"12:34","lastingAt":"2019-08-24T14:15:22Z","timeExclusions":{"uuid":"6a177f3e-748f-44d4-ac30-a457a5199685"},"interval":{"every":2,"unit":"WEEKS","anchorDate":"2026-07-05T23:59:00Z"}},"printout":{"template":"|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!","maxLineLength":18,"newLineDelimiter":";"},"types":["MEMBERS_ONLY","HANDBILL"],"excludeByAvailableProducts":true,"slotFilters":{"order":"GIVEN","slots":[{"filterId":"aff0ee0f-f371-4b82-82c6-dc3b96f05c91","limit":5,"distinctFilter":{"filters":[{"field":"brand","maxNumItems":2,"levelRangeModifier":1}],"elastic":true},"fallback":{"filterId":"3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c"}}]},"distinctFilter":{"filters":[{"field":"brand","maxNumItems":2,"levelRangeModifier":1}],"elastic":true}}]}');

            try {
              $response = $request->send();

              echo $response->getBody();
            } catch (HttpException $ex) {
              echo $ex;
            }
        - lang: Java
          label: Java
          source: |-
            HttpResponse<String> response = Unirest.post("https://api.synerise.com/v4/promotions/handbill")
              .header("Authorization", "Bearer REPLACE_BEARER_TOKEN")
              .header("content-type", "application/json")
              .body("{\"channel\":\"MOBILE\",\"status\":\"DRAFT\",\"name\":\"string\",\"description\":\"string\",\"controlGroup\":{\"name\":\"string\",\"percentage\":100},\"variants\":[{\"name\":\"string\",\"uuid\":\"095be615-a8ad-4c33-8e9c-c7612fbf6c9f\",\"percentage\":100,\"ai\":{\"controlVariant\":true,\"varietyFactor\":0.5,\"varietyGroupSize\":1,\"redistributionFrequencyFactor\":0.5,\"popularityBoosting\":1},\"limits\":{\"limitPerDay\":6,\"limitExceptions\":[{\"dayOfWeek\":5,\"limitPerDay\":8}],\"limitsPerBasket\":[{\"basketSize\":12,\"basketValue\":30.5,\"condition\":\"AND\"}],\"limitExclusion\":[{\"catalogId\":22424,\"products\":[\"UGG-BB-PUR-06\"],\"filters\":[\"7c1fbdf6-dd27-11ea-87d0-0242ac130003\"]}]},\"activity\":{\"lastingType\":\"RELATIVE\",\"lasting\":{\"unit\":\"HOURS\",\"value\":24},\"cronWeekdays\":[0,1,6],\"cronTime\":\"12:34\",\"lastingAt\":\"2019-08-24T14:15:22Z\",\"timeExclusions\":{\"uuid\":\"6a177f3e-748f-44d4-ac30-a457a5199685\"},\"interval\":{\"every\":2,\"unit\":\"WEEKS\",\"anchorDate\":\"2026-07-05T23:59:00Z\"}},\"printout\":{\"template\":\"|#{promotion.name};#{promotion.discountType == 'EXACT_PRICE' ? 'Price':'Discount'} #{promotion.discountValue} #{promotion.discountType == 'PERCENT'? '%' : 'USD'};Valid for;#{moment.utc(coupon.createdAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')} - #{moment.utc(coupon.lastingAt).tz('Europe/Warsaw').format('DD.MM.YYYY HH:mm')};#{promotion.description};Discount for #{coupon.redeemLimit} items.;Single-use coupon. Get extra coupons with the app!\",\"maxLineLength\":18,\"newLineDelimiter\":\";\"},\"types\":[\"MEMBERS_ONLY\",\"HANDBILL\"],\"excludeByAvailableProducts\":true,\"slotFilters\":{\"order\":\"GIVEN\",\"slots\":[{\"filterId\":\"aff0ee0f-f371-4b82-82c6-dc3b96f05c91\",\"limit\":5,\"distinctFilter\":{\"filters\":[{\"field\":\"brand\",\"maxNumItems\":2,\"levelRangeModifier\":1}],\"elastic\":true},\"fallback\":{\"filterId\":\"3f2c9a4e-8b1d-4e5f-9c6a-7d8e9f0a1b2c\"}}]},\"distinctFilter\":{\"filters\":[{\"field\":\"brand\",\"maxNumItems\":2,\"levelRangeModifier\":1}],\"elastic\":true}}]}")
              .asString();
servers:
  - description: Microsoft Azure EU
    url: https://api.synerise.com
  - description: Microsoft Azure USA
    url: https://api.azu.synerise.com
  - description: Google Cloud Platform
    url: https://api.geb.synerise.com
tags:
  - name: Handbills
components:
  securitySchemes:
    JWT:
      type: http
      scheme: bearer
      description: |-
        JWT Bearer token. The header looks like this: `Bearer {JWT}`

        Remember to include the space between 'Bearer' and the token.

        Generate a token via the **Authorization** endpoints.
```
