Product Discounts

Product discounts are used to change certain product prices.

A product price can be discounted in two ways:

  • with a relative or an absolute product discount, which will be automatically applied to all prices in a product that match a discount predicate.
    A relative discount reduces the matching price by a fraction (for example 10 % off). An absolute discount reduces the matching price by a fixed amount (for example 10€ off). If more than one product discount matches a price, the discount sort order determines which one will be applied.
  • with an external product discount, which can then be used to explicitly set a discounted value on a particular product price.

The discounted price is stored in the discounted field of the Product Price.

Note that when a discount is created, updated or removed it can take up to 15 minutes to update all the prices with the discounts.

The maximum number of ProductDiscounts that can be active at the same time is 200.

Representations

ProductDiscount

  • id - String
    The unique ID of the product discount
  • version - Number
    The current version of the product discount.
  • createdAt - DateTime
  • lastModifiedAt - DateTime
  • name - LocalizedString
  • description - LocalizedString - Optional
  • value - ProductDiscountValue
  • predicate - String
    A valid ProductDiscount Predicate.
  • sortOrder - String
    The string contains a number between 0 and 1. A discount with greater sortOrder is prioritized higher than a discount with lower sortOrder. A sortOrder must be unambiguous.
  • isActive - Boolean
    Only active discount will be applied to product prices.
  • validFrom - DateTime - Optional
    The time from which the discount should be effective. Please take Eventual Consistency into account for calculated product discount values.
  • validUntil - DateTime - Optional
    The time from which the discount should be ineffective. Please take Eventual Consistency into account for calculated undiscounted values.
  • references - Array of Reference
    The platform will generate this array from the predicate. It contains the references of all the resources that are addressed in the predicate.

ProductDiscountDraft

  • name - LocalizedString
  • description - LocalizedString - Optional
  • value - ProductDiscountValue
  • predicate - String
    A valid ProductDiscount Predicate.
  • sortOrder - String
    The string must contain a decimal number between 0 and 1. A discount with greater sortOrder is prioritized higher than a discount with lower sortOrder.
  • isActive - Boolean
    If set to true the discount will be applied to product prices.
  • validFrom - DateTime - Optional
    The time from which the discount should be effective. Please take Eventual Consistency into account for calculated product discount values.
  • validUntil - DateTime - Optional
    The time from which the discount should be effective. Please take Eventual Consistency into account for calculated undiscounted values.

ProductDiscountValue

Defines discount type with the corresponding value. The type can be relative, absolute or external.

Relative

  • type - relative
  • permyriad - Number
    Per ten thousand. The fraction the price is reduced. 1000 will result in a 10% price reduction.

Absolute

  • type - absolute
  • money - Array of Money
    The array contains money values in different currencies. An absolute ProductDiscount will only match a price if this array contains a value with the same currency. If it contains 10€ and 15$, for example, the matching € price will be decreased by 10€ and the matching $ price will be decreased by 15$.

External

  • type - external

The external discount is used by the setDiscountedPrice update action and enables the client to explicitly set a discounted value for a particular price.

Get ProductDiscount by ID

Endpoint: /{projectKey}/product-discounts/{id}
Method: GET
OAuth2 Scopes: view_products:{projectKey}
Response Representation: ProductDiscount

Query ProductDiscounts

Endpoint: /{projectKey}/product-discounts
Method: GET
OAuth2 Scopes: view_products:{projectKey}
Response Representation: PagedQueryResult with the results array of ProductDiscount
Query Parameters:

Create a ProductDiscount

Endpoint: /{projectKey}/product-discounts
Method: POST
OAuth2 Scopes: manage_products:{projectKey}
Request Representation: ProductDiscountDraft
Response Representation: ProductDiscount

Update ProductDiscount

Endpoint: /{projectKey}/product-discounts/{id}
Method: POST
OAuth2 Scopes: manage_products:{projectKey}
Response Representation: ProductDiscount
Fields:

  • version - Number - Required
    The expected version of the ProductDiscount on which the changes should be applied. If the expected version does not match the actual version, a 409 Conflict will be returned.
  • actions - Array of UpdateAction - Required
    The list of update actions to be performed on the ProductDiscount.

Update Actions
Please find below the individual update actions provided on this endpoint.


Change Value

Change Predicate

Change Is Active

  • action - String - "changeIsActive"
  • isActive - Boolean

Set Valid From

  • action - String - "setValidFrom"
  • validFrom - DateTime - Optional
    The time from which the discount should be effective. Please take Eventual Consistency into account for calculated product discount values.

Set Valid Until

  • action - String - "setValidUntil"
  • validUntil - DateTime - Optional
    The time from which the discount should be ineffective. Please take Eventual Consistency into account for calculated undiscounted values.

Set Valid From and Until

  • action - String - "setValidFromAndUntil"
  • validFrom - DateTime - Optional
  • validUntil - DateTime - Optional
    The timeframe for which the discount should be effective. Please take Eventual Consistency into account for calculated undiscounted values.

Change Name

Set Description

  • action - String - "setDescription"
  • description - LocalizedString - Optional

Change Sort Order

  • action - String - "changeSortOrder"
  • sortOrder - String
    The string must contain a number between 0 and 1. A discount with greater sortOrder is prioritized higher than a discount with lower sortOrder.

Delete ProductDiscount

Endpoint: /{projectKey}/product-discounts/{id}
Method: DELETE
OAuth2 Scopes: manage_products:{projectKey} Query Parameters:

  • version - Number - Required

ProductDiscount Predicate

The predicate offers a flexible way to define which product prices should be reduced.

Predicate Identifiers

The following field identifiers can be used in a predicate. They reference a field in a Product or a field in the Product Price.

  • product.id - UUID
  • product.key - String
  • productType.id - UUID
  • variantId - Number
  • sku - String
  • categories.id - Array of UUID
  • categoriesWithAncestors.id - Array of UUID
    Identifies categories of a product and all the ancestors of those categories. It is used to match all categories that are in a subtree of a specific category.
  • price - Money
  • amount - Number - The amount in the specified currency.
  • centAmount - Number - The amount in cents (the subunit) of the specified currency.
  • currency- String - Currency code
  • country - String - Country code
  • customerGroup.id - UUID
  • customerGroup.key - String
  • channel.id - UUID
  • attributes.<attr-name>
    Matches a product attribute by its name. Only boolean, text, number, datetime, date, time, enum and lenum attribute types are supported. The set of these types is supported also. In case of enum and lenum type attributes only the key can be used in predicates. If a field name contains a dash (-) or starts with a digit, it needs to be escaped with backticks (`), e.g., attributes.`average-count`.

Predicate Operators

The operators combine field identifiers with concrete values to construct predicates.
The operators use the infix notation with the general notation field-identifier operator value.

Example: sku = "AB-123" where

  • the field identifier is sku,
  • the operator is = and
  • the value is "AB-123".

Collection values are separated with , and enclosed in parentheses.

Example: categories.id = ("f6a19a23-14e3-40d0-aee2-3e612fcb1bc7", "abcd9a23-14e3-40d0-aee2-3e612fcbefgh")

Following table lists all operators that can be used on fields or on other predicates to build higher order predicates.

purpose operator usable on
compare field values =, !=, >, >=, <, <= simple fields
check if field is present on resource is defined any field
check if field is missing on resource is not defined any field
check if field is present but has no value is empty collection fields
check if field is present and has a value is not empty collection fields
check if field contains specified value contains collection fields with simple value
check if field contains at least one of the specified values contains any collection fields with collection value
check if field contains all of the specified values contains all collection fields with collection value
logical disjunction or predicates
logical conjunction and predicates
logical negation not predicates

Parentheses are used to nest logical operators and combine predicate parts into more complex predicates.

Predicate Examples

// match a specific variant in the specific product
product.id = "f6a19a23-14e3-40d0-aee2-3e612fcb1bc7" and variant.id = 1

//match a product that is in the given category
categories.id contains "f6a19a23-14e3-40d0-aee2-3e612fcb1bc7"

//match a product that is in all of the the given categories
categories.id contains all ("f6a19a23-14e3-40d0-aee2-3e612fcb1bc7", "abcd9a23-14e3-40d0-aee2-3e612fcbefgh")

//match a product that is in one of the the given categories
categories.id contains any ("f6a19a23-14e3-40d0-aee2-3e612fcb1bc7", "abcd9a23-14e3-40d0-aee2-3e612fcbefgh")

//match a product that is in the two given categories and in no others
categories.id = ("f6a19a23-14e3-40d0-aee2-3e612fcb1bc7", "abcd9a23-14e3-40d0-aee2-3e612fcbefgh")

//match a product that is not in a given category
categories.id != ("f6a19a23-14e3-40d0-aee2-3e612fcb1bc7")

//match the prices above 12€ for any countries except France that do not have a customer group set
centAmount > 1200 and currency = "EUR" and country != "FR" and customerGroup.id is not defined

//match all product variants that have size "L" and have the color white and black   
//size is an EnumType attribute for which the key is specified in the predicate,
//color is a SetType of Enums for which the keys are listed in the predicate.
attributes.size = "L" and attributes.colors contains all ("black", "white")

//match all product variants with the given sku, the boolean attribute available set to true and the number attribute weight less than 100
sku = "AB-12" and attributes.available = true and attributes.weight < 100

//match all products that are in the given category or in a category that is a descendant of the given category
categoriesWithAncestors.id contains "abcd9a23-14e3-40d0-aee2-3e612fcbefgh"

Get Matching ProductDiscount

This endpoint can be used to simulate which product discounts would be applied if a specified product variant had a specified price. Given product and variant ids and a price, this endpoint will return the product discount that would have been applied to that price.

Endpoint: /{projectKey}/product-discounts/matching
Method: POST
OAuth2 Scopes: view_products:{projectKey}
Response Representation: ProductDiscount

Fields:

  • productId - UUID
    ID of the product
  • variantId - Integer
    ID of the variant
  • staged - Boolean
    Whether to use the staged version of this variant or the published one
  • price - Price - Required

Specific Error Codes: