# Duplicate existing promotion

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

## 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/promotion/duplicate:
    post:
      tags:
        - Promotions
      summary: Duplicate existing promotion
      description: |
        You can duplicate an existing promotion.

        ---

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

        **API key permission required:** `PROMOTIONS_DUPLICATE_PROMOTIONS_CREATE`

        **User role permission required:** `campaigns_promotions: create`
      operationId: duplicatePromotion
      requestBody:
        required: true
        description: Provide only one of the parameters.
        content:
          application/json:
            schema:
              type: object
              properties:
                uuid:
                  type: string
                  description: Promotion UUID
                code:
                  type: string
                  description: Promotion code
      responses:
        "200":
          description: Promotion duplicated
          content:
            application/json:
              schema:
                type: object
                description: Details of the promotion
                properties:
                  uuid:
                    type: string
                    description: Unique UUIDv4.
                  code:
                    type: string
                    maxLength: 64
                    description: Unique code
                  status:
                    type: string
                    description: Profile-oriented status of the promotion.
                    enum:
                      - DRAFT
                      - PUBLISH
                      - HIDDEN
                    default: DRAFT
                  type:
                    type: string
                    description: Promotion type
                    enum:
                      - MEMBERS_ONLY
                      - HANDBILL
                      - CUSTOM
                      - GENERAL
                    default: GENERAL
                  redeemLimitPerClient:
                    type: integer
                    description: Limit how many times a Profile can redeem this promotion.
                    default: 0
                    minimum: 0
                    maximum: 32767
                    nullable: true
                  redeemQuantityPerActivation:
                    type: integer
                    nullable: true
                    description: How many times per activation a multibuy promotion can be redeemed
                    minimum: 0
                    maximum: 8388607
                  redeemLimitGlobal:
                    type: integer
                    deprecated: true
                    format: int32
                    description: Limit the total of redemptions by all Profiles
                    default: 0
                    minimum: 0
                    maximum: 2147483647
                    nullable: true
                  activationLimitGlobalType:
                    type: string
                    nullable: true
                    default: LIFETIME
                    description: |-
                      Promotion activation limit type
                      * `LIFETIME` – No additional configuration required. The limit applies to the entire lifespan of the promotion. * `RELATIVE` – Requires specifying a relative time window (number of minutes from the current time).
                    enum:
                      - RELATIVE
                      - LIFETIME
                  activationLimitGlobalLimit:
                    type: integer
                    format: int32
                    description: Limit the total of activations by all Profiles within given time unit.
                    minimum: 1
                    maximum: 2147483647
                    nullable: true
                  activationLimitGlobalCounter:
                    type: integer
                    format: int32
                    description: Counter of the total of activations by all Profiles within given time unit.
                    nullable: true
                  activationLimitGlobalRelativeMinutes:
                    type: integer
                    format: int32
                    nullable: true
                    default: null
                    minimum: 1
                    maximum: 527040
                    description: Used only when `type` is `RELATIVE`. Defines how many minutes back from the current time the limit applies.
                  activationLimitGlobalReached:
                    type: boolean
                    nullable: true
                    default: null
                    description: Indicator to inform that limit is reached.
                  redeemType:
                    type: string
                    description: Promotion redemption type
                    enum:
                      - FULL
                      - PARTIAL
                  discountType:
                    type: string
                    description: The type of discount
                    enum:
                      - PERCENT
                      - POINTS
                      - AMOUNT
                      - NONE
                      - MULTIBUY
                      - 2_FOR_1
                      - EXACT_PRICE
                      - DIGITAL_CASHBACK
                    default: NONE
                  details:
                    type: object
                    description: Promotion details
                    nullable: true
                    properties:
                      discountType:
                        type: object
                        description: Details that apply for specific discount type.
                        required:
                          - name
                          - outerScope
                          - requiredItemsCount
                          - discountedItemsCount
                        properties:
                          name:
                            type: string
                            enum:
                              - BOGO
                            default: BOGO
                          outerScope:
                            type: boolean
                            description: |
                              This defines whether a defined promotion trigger for discount is based on different item scope.
                              When set to
                                * `false` it means items are from the same scope,
                                * `true` it means items are from outer scope and `requiredItems` should be defined.
                            default: false
                            example: true
                          requiredItemsCount:
                            description: Number of items that should be purchased to meet the promotion condition.
                            type: integer
                            format: int32
                            example: 2
                          requiredItems:
                            type: object
                            description: Catalog items definition details
                            required:
                              - catalog
                              - catalogItemType
                            nullable: true
                            properties:
                              catalog:
                                type: string
                                description: ID of the item catalog that the promotion applies to
                                nullable: true
                                example: "221"
                              catalogItemType:
                                type: string
                                enum:
                                  - ALL
                                  - SELECTED
                                  - FILTERED
                                  - QUERY
                                description: |
                                  
                                  - If set to "ALL", define the catalog in the `catalog` field and set `catalogIndexItems` to null.

                                  - If set to "SELECTED", define the catalog in the `catalog` field and provide a list of catalog items in `catalogIndexItems`.

                                  - If set to "FILTERED", define the catalog in the `catalog` field and provide a list of catalog filter ids in `catalogFilterIds`.

                                  - If set to "QUERY", define the catalog in the `catalog` field and provide an inline RSQL expression in `catalogFilterQuery`.
                                default: ALL
                                example: FILTERED
                              catalogIndexItems:
                                type: array
                                items:
                                  type: string
                                description: |
                                  
                                  'An array of items from the catalog to be included in the promotion if `catalogItemType` is set to `SELECTED`.


                                  If `catalogItemType` is set to `ALL`, set `catalogIndexItems` to null.'
                                nullable: true
                                example: []
                              catalogFilterIds:
                                type: array
                                items:
                                  type: string
                                description: |
                                  
                                  'An array of catalog filter IDs to be executed to fetch catalog items if `catalogItemType` is set to `FILTERED`.


                                  If `catalogItemType` is set to `ALL`, set `catalogFilterIds` to null.'
                                nullable: true
                                example:
                                  - f978b20f-7156-40ed-99c2-3af62b76af12
                              catalogFilterQuery:
                                type: string
                                maxLength: 1024
                                description: |
                                  
                                  An RSQL expression that the Catalogs API resolves to matching catalog items when `catalogItemType` is set to `QUERY`.

                                  This field is required when `catalogItemType` is set to `QUERY`. A catalog must also be defined. Otherwise, set this field to null.

                                  **Structure**

                                  An expression consists of one or more rules joined by:

                                  - `;` — AND

                                  - `,` — OR

                                  RSQL expressions are case-insensitive.

                                  **Attribute predicates**

                                  | Operator | Type | Meaning | Example |
                                  | --- | --- | --- | --- |
                                  | `==` | string / number / boolean | Equals | `category==shampoo` |
                                  | `!=` | string / number | Does not equal | `brand!=Nivea` |
                                  | `=in=(a,b,…)` | string | Value is in the set | `sku=in=(SKU1,SKU2)` |
                                  | `=out=(a,b,…)` | string | Value is not in the set | `brand=out=(Nivea,Dove)` |
                                  | `=contains=` | string | Value contains the specified string | `brand=contains=nike` |
                                  | `=startsWith=` | string | Value starts with the specified string | `brand=startsWith=nik` |
                                  | `=endsWith=` | string | Value ends with the specified string | `brand=endsWith=ike` |
                                  | `>` / `=gt=` | number | Greater than | `price>2` |
                                  | `>=` / `=gte=` | number | Greater than or equal to | `price>=2` |
                                  | `<` / `=lt=` | number | Less than | `price<2` |
                                  | `<=` / `=lte=` | number | Less than or equal to | `price<=2` |

                                  **Important:** Attributes used in the expression must be indexed in the catalog. Read more about [indexing catalogs](https://hub.synerise.com/docs/assets/catalogs/creating-catalogs#indexing-catalogs).
                                nullable: true
                                example: color==green;price=lt=100
                          discountedItemsCount:
                            description: Number of items to apply the discount to.
                            type: integer
                            format: int32
                            example: 1
                      cashbackSettings:
                        type: object
                        description: Settings for cashback mechanism
                        nullable: true
                        required:
                          - exchangeRate
                        properties:
                          exchangeRate:
                            type: number
                            minimum: 0.0001
                            description: Defines how much currency corresponds to one point. For example, if the currency is PLN and exchangeRate is 2, then 1 point equals 2 PLN.
                          limits:
                            type: object
                            nullable: true
                            description: Defines the limits on cashback usage
                            properties:
                              minPoints:
                                type: integer
                                nullable: true
                                minimum: 1
                                description: The minimum number of points required to spend for cashback. If null - there is no limit defined.
                                example: 10
                              maxPoints:
                                type: integer
                                nullable: true
                                minimum: 1
                                description: The maximum number of points allowed to spend for cashback. If null - there is no limit defined.
                                example: 1000
                              maxTransactionAmount:
                                type: number
                                nullable: true
                                minimum: 0.01
                                description: Maximum amount in local currency to redeem in a transaction. If null - there is no limit defined.
                                example: 20
                              maxTransactionPercentage:
                                type: number
                                nullable: true
                                description: Defines how much (in percent) of the total transaction amount can be treated as cashback. If null - there is no limit defined.
                                example: 50
                                minimum: 0.01
                                maximum: 100
                  discountValue:
                    type: number
                    description: How much discount to apply
                    default: 0
                    minimum: 0
                    maximum: 100
                  discountMode:
                    type: string
                    description: Promotion discount mode
                    enum:
                      - STATIC
                      - STEP
                    default: STATIC
                  discountModeDetails:
                    type: object
                    properties:
                      steps:
                        type: array
                        nullable: false
                        minItems: 1
                        maxItems: 5
                        items:
                          required:
                            - discountValue
                            - usageThreshold
                          type: object
                          properties:
                            discountValue:
                              description: Discount value in given step
                              type: number
                            usageThreshold:
                              description: Threshold after current step would apply
                              type: number
                      discountUsageTrigger:
                        type: string
                        enum:
                          - TRANSACTION
                          - REDEEM
                        nullable: false
                        description: Describe after what action new steps would be applied
                    nullable: true
                    description: 'Applies only when `"discountMode": "STEP"`.'
                  preDiscountValue:
                    type: number
                    minimum: 0
                    nullable: true
                    default: 0
                    description: In single-item promotions, this is the price of the item before the discount. This is in regular units of currency. For example, if the currency is USD and `preDiscountValue` is set to 1.2, the price before discount is 1 dollar and 20 cents.
                  requireRedeemedPoints:
                    type: number
                    nullable: true
                    format: int32
                    description: How many loyalty points are needed to activate the promotion
                  headerName:
                    type: string
                    maxLength: 255
                    description: Name displayed in Synerise Web UI
                  headerDescription:
                    type: string
                    maxLength: 255
                    description: Description displayed in Synerise Web UI
                    nullable: true
                  name:
                    type: string
                    maxLength: 255
                    description: Promotion name displayed to viewers
                  headline:
                    type: string
                    nullable: true
                    description: Promotion headline displayed to viewers
                  description:
                    type: string
                    maxLength: 2048
                    nullable: true
                    description: Details of the promotion displayed to viewers
                  images:
                    type: array
                    nullable: true
                    items:
                      required:
                        - url
                        - type
                      type: object
                      properties:
                        url:
                          description: Image or thumbnail source. Must be an absolute HTTP/HTTPS URL.
                          type: string
                          format: uri
                          example: https://www.snrcdn.net/upload/f2afa4d4d7af216196047d1f7f0613f22a50a8c8/default/origin/1537188683527-el-ipadpro.png
                        type:
                          type: string
                          enum:
                            - image
                            - thumbnail
                    description: Images and thumbnails for the promotion
                  tags:
                    description: |
                      An array of tags.

                      **IMPORTANT:** To be able to use a tag for promotions, you must first assign the tag to a directory with `"type":"promotion"`. If the directory type does not exist, create it using [this endpoint](https://developers.synerise.com/AssetManagement/AssetManagement.html#operation/createDirectoryType). Then create a directory of that type and assign tags to it.
                    type: array
                    items:
                      type: object
                      properties:
                        hash:
                          type: string
                          description: Hash ID of the tag
                          example: 6f54671d-157f-4c4e-a577-11fac3111293
                    nullable: true
                  createdAt:
                    type: string
                    format: date-time
                    description: Time when the object was created
                  startAt:
                    type: string
                    nullable: true
                    format: date-time
                    description: Time when the promotion becomes available. Defaults to current time.
                  expireAt:
                    type: string
                    nullable: true
                    format: date-time
                    description: Time when the promotion ends for all profiles. Defaults to current time. Has to be greater than startAt
                  displayFrom:
                    type: string
                    nullable: true
                    description: Time when the promotion becomes displayable. Defaults to null.
                  displayTo:
                    type: string
                    nullable: true
                    description: Time when the promotion stops being displayed for users. Defaults to null. Has to be greater than displayFrom.
                  lastingTime:
                    type: integer
                    format: int32
                    nullable: true
                    description: Duration of the promotion in seconds. This countdown starts when the profile activates a promotion and is individual for each profile.
                    default: 0
                  params:
                    type: object
                    description: A JSON object with any custom parameters of type string, object, array.
                    nullable: true
                    additionalProperties: true
                  itemScope:
                    type: string
                    description: |-
                      The scope of of the promotion.
                      * LINE_ITEM is a promotion used for certain items in the basket
                      * BASKET is a promotion that applies to the entire basket
                    enum:
                      - LINE_ITEM
                      - BASKET
                    default: LINE_ITEM
                  minBasketValue:
                    type: number
                    nullable: true
                    default: null
                    minimum: 0
                    description: |
                      Minimal basket value required to trigger the application of the promotion. This is the basket value after calculating other promotions that apply to the items in the basket. 

                      `minBasketValue` must be lower than `maxBasketValue`.
                  maxBasketValue:
                    type: number
                    nullable: true
                    default: null
                    minimum: 0
                    description: |
                      
                      The maximum basket value to apply the promotion to. Any amount above the maximum is not discounted. This is the basket value after calculating other promotions that apply to the items in the basket.

                      `maxBasketValue` must be greater than `minBasketValue`

                      **Example:**<br/>
                      The maximum basket value is set to 500 USD. The discount is 10%. A basket's total is 700 USD. The discount is 50 USD.
                  catalog:
                    type: string
                    description: ID of the item catalog that the promotion applies to
                    nullable: true
                    example: "221"
                  catalogItemType:
                    type: string
                    enum:
                      - ALL
                      - SELECTED
                      - FILTERED
                      - QUERY
                    description: |
                      
                      - If set to "ALL", define the catalog in the `catalog` field and set `catalogIndexItems` to null.

                      - If set to "SELECTED", define the catalog in the `catalog` field and provide a list of catalog items in `catalogIndexItems`.

                      - If set to "FILTERED", define the catalog in the `catalog` field and provide a list of catalog filter ids in `catalogFilterIds`.

                      - If set to "QUERY", define the catalog in the `catalog` field and provide an inline RSQL expression in `catalogFilterQuery`.
                    default: ALL
                    example: FILTERED
                  catalogIndexItems:
                    type: array
                    items:
                      type: string
                    description: |
                      
                      'An array of items from the catalog to be included in the promotion if `catalogItemType` is set to `SELECTED`.


                      If `catalogItemType` is set to `ALL`, set `catalogIndexItems` to null.'
                    nullable: true
                    example: []
                  catalogFilterIds:
                    type: array
                    items:
                      type: string
                    description: |
                      
                      'An array of catalog filter IDs to be executed to fetch catalog items if `catalogItemType` is set to `FILTERED`.


                      If `catalogItemType` is set to `ALL`, set `catalogFilterIds` to null.'
                    nullable: true
                    example:
                      - f978b20f-7156-40ed-99c2-3af62b76af12
                  catalogFilterQuery:
                    type: string
                    maxLength: 1024
                    description: |
                      
                      An RSQL expression that the Catalogs API resolves to matching catalog items when `catalogItemType` is set to `QUERY`.

                      This field is required when `catalogItemType` is set to `QUERY`. A catalog must also be defined. Otherwise, set this field to null.

                      **Structure**

                      An expression consists of one or more rules joined by:

                      - `;` — AND

                      - `,` — OR

                      RSQL expressions are case-insensitive.

                      **Attribute predicates**

                      | Operator | Type | Meaning | Example |
                      | --- | --- | --- | --- |
                      | `==` | string / number / boolean | Equals | `category==shampoo` |
                      | `!=` | string / number | Does not equal | `brand!=Nivea` |
                      | `=in=(a,b,…)` | string | Value is in the set | `sku=in=(SKU1,SKU2)` |
                      | `=out=(a,b,…)` | string | Value is not in the set | `brand=out=(Nivea,Dove)` |
                      | `=contains=` | string | Value contains the specified string | `brand=contains=nike` |
                      | `=startsWith=` | string | Value starts with the specified string | `brand=startsWith=nik` |
                      | `=endsWith=` | string | Value ends with the specified string | `brand=endsWith=ike` |
                      | `>` / `=gt=` | number | Greater than | `price>2` |
                      | `>=` / `=gte=` | number | Greater than or equal to | `price>=2` |
                      | `<` / `=lt=` | number | Less than | `price<2` |
                      | `<=` / `=lte=` | number | Less than or equal to | `price<=2` |

                      **Important:** Attributes used in the expression must be indexed in the catalog. Read more about [indexing catalogs](https://hub.synerise.com/docs/assets/catalogs/creating-catalogs#indexing-catalogs).
                    nullable: true
                    example: color==green;price=lt=100
                  storeCatalog:
                    type: string
                    description: ID of the store catalog that the promotion applies to
                    nullable: true
                    minLength: 1
                    maxLength: 255
                  storeItemType:
                    type: string
                    enum:
                      - ALL
                      - SELECTED
                    description: Defines if the promotion is available for the entire store catalog or only certain stores (listed in `storeIds`).
                    default: ALL
                  storeIds:
                    type: array
                    items:
                      type: string
                    description: An array of stores from the store catalog where the promotion is available if `storeItemType` is set to `SELECTED`
                    nullable: true
                  targetType:
                    type: string
                    description: If this field is set to "SEGMENT", you must provide a list of segments in `targetSegment`.
                    default: ALL
                    enum:
                      - ALL
                      - SEGMENT
                  targetSegment:
                    type: array
                    nullable: true
                    description: This field applies only when `targetType` is set to "SEGMENT".
                    items:
                      type: string
                      description: ID of the segmentation of profiles that can redeem this promotion
                  price:
                    description: In single-item promotions, this is the price of the item in the smallest unit of currency. For example, if the currency is USD and `price` is 120, the price is 1 dollar and 20 cents.
                    type: integer
                    default: 0
                    minimum: 0
                    maximum: 2147483647
                  priority:
                    description: Defines the promotion's priority, used both for display order and to order candidate promotions when they are selected during handbill and checkout assignment. Values are ordered ascending, so a lower number means a higher priority and `1` is the highest. When the per-slot read limit or the AI request cap truncates the candidate list, the higher-priority (lower-numbered) promotions are the ones kept. Promotions that share the same priority have no further guaranteed ordering between them, so when a truncation boundary falls inside a group of equal priority it is not defined which of them are kept — assign distinct priorities to the promotions that must always win.
                    type: integer
                    minimum: 1
                    maximum: 500
                    default: 250
                  metric:
                    nullable: true
                    type: string
                    maxLength: 64
                    description: Currently unused
                  importHash:
                    type: string
                    format: uuid
                    nullable: true
                    description: Hash of the import
        "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
        "404":
          description: Promotion not found
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                    description: Short summary of the response
              example:
                message: Promotion not found
        "500":
          description: Internal Server Error
      x-snr-doc-urls:
        - /api-reference/loyalty-and-engagement#tag/Promotions/operation/duplicatePromotion
      x-codeSamples:
        - lang: cURL
          label: cURL
          source: |-
            curl --request POST \
              --url https://api.synerise.com/v4/promotions/promotion/duplicate \
              --header 'content-type: application/json' \
              --data '{"uuid":"string","code":"string"}'
        - lang: Python
          label: Python
          source: |-
            import http.client

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

            payload = "{\"uuid\":\"string\",\"code\":\"string\"}"

            headers = { 'content-type': "application/json" }

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

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

            print(data.decode("utf-8"))
        - lang: JavaScript
          label: JavaScript
          source: |-
            const data = JSON.stringify({
              "uuid": "string",
              "code": "string"
            });

            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/promotion/duplicate");
            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/promotion/duplicate",
              "headers": {
                "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({uuid: 'string', code: 'string'}));
            req.end();
        - lang: PHP
          label: PHP
          source: |-
            <?php

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

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

            $request->setBody('{"uuid":"string","code":"string"}');

            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/promotion/duplicate")
              .header("content-type", "application/json")
              .body("{\"uuid\":\"string\",\"code\":\"string\"}")
              .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: Promotions
```
