docs
  1. Advanced
  2. Pricing & Promotions
  3. Manage Prices

Manage Prices

General

Prices in SCAYLE can be concurrently applied to different countries, groups and campaigns as needed.

Prices are defined on a product variant level and contain all information about prices, taxes and validity — upcoming prices can also be defined for automatic future price updates. For a specific variant, there can be multiple prices active at the same time based on the following dimensions:

  • countryCode: The country in which the price is effective.
  • groupKey: Price groups can be used to apply different prices in different shops within the same country (e.g., B2C vs. B2B).
  • promotionKey: The price promotion key can be used to have multiple valid prices for the same country and price group within the same shop at the same time. The Storefront API can be used to retrieve a specific price by sending a request with a defined price promotion key.

The currency (currencyCode) is not part of these dimensions as it must match the respective country.

Price key

Every new price gets a generated key. This key might change due to certain conditions. For example, when a future price becomes an active price, the key is modified.

Merchant-Specific Prices

You can create prices for a specific merchant by providing its reference key in the merchantReferenceKey field.

Product Variant Price Entity

ParameterDetails
key

String READ-ONLY

Key assigned by SCAYLE.

price

Integer

Price of the variant.

oldPrice

Integer

Old price of the variant.

recommendedRetailPrice

Integer

Recommended retail price of the variant.

buyingPrice

Integer

Buying price of the variant.

tax

Double

A valid tax rate.

countryCode

String

ISO 3166 alpha 2 country code.

currencyCode

String

ISO 4217 currency code.

groupKey

String

Key of the group the price is assigned to.

promotionKey

String

Key of the promotion the price is assigned to.

unitPrice

ProductVariantUnitPrice

Describes the price for a specific unit.

validFrom

String

Controls when the price will be activated. If not present or null, the valid from is specified from now.

validTo

String

Controls when the price will be deactivated. If not present or null, the price is valid forever.

merchantReferenceKey

String

A merchant reference key the price belongs to.

Admin API

Create/Update a Price

Prices are defined on variant level and contain all information about prices, taxes and validity — upcoming prices can also be defined for automatic future price updates.

About this Method

This method can be used to create a new Product Variant Price. You can create prices which are valid from now or in the future. If there is an already existing price for the same validation time frame, it will get replaced.

If multiple prices of the same variant are to be created then use update-variant endpoint which supports sending multiple prices at once.

Method Signature

Details

  • Creating a new price, which is valid from the time of creation, will invalidate the current active price and become the new active one based on the dimensions explained on the prices overview page.
  • It is not possible to create a price for a composite product variant, when the automatic price calculation for composite variants is enabled.
  • Future prices are activated by a price activator cron job running every hour. Old prices are then deactivated.
  • merchantReferenceKey can be provided to create a merchant-specific price. Note that merchantReferenceKey must refer to one of the merchants provided on product creation.

If you send prices by specifying a merchantReferenceKey for which no product variant exists, you will receive the error message MERCHANT_REFERENCE_KEY_OUT_OF_RANGE.

Create Valid Price from Now

Create Valid Price for Future

Create Valid Expiring Price

Create Price with Unit Price

Create Merchant-Specific Price

Get a Collection of Prices

When you request variant prices, you can extend the query with several identifiers to get multiple active prices.

About this Method

This method can be used to get a collection of existing product variant prices.

The price collection contains currently active and future prices. Expired or invalid prices are not included.

Method Signature

Parameters

ParameterDetails
entities

ProductVariantPrice

A collection of product variant prices.

List of Prices

Delete a product variant price

You can easily delete prices by using the respective identifiers.

About this Method

This method can be used to delete a price.

Method Signature

Details

  • It is not possible to remove a price from a composite product variant, when the automatic price calculation for composite variants is enabled.
  • It is not allowed to delete a merchant price other than a future price.
  • It is not allowed to delete a custom price. When trying to remove a custom price, endpoint would respond with 400 Bad Request, PRODUCT_VARIANT_CUSTOM_PRICE_CANNOT_BE_DELETED error key.

Delete a Price

Price Rounding

A shop country price rounding represents a price rounding assigned to a shop country.

SCAYLE allows users to create and manage any number of price rounding configurations.

The primary purpose of this feature is to allow users to customize price rounding settings.

Price rounding precision

You can set the price rounding precision (the value by which the price is rounded up/down/ to the nearest integer). For simplicity, the precision values used in the following table are allowed:

  • 1.0
  • 5.0
  • 0.05
  • 0.95
  • 0.99

Example of precision value rounding

PrecisionRounding TypePriceRounded Price
1.0nearest1458.901459
1.0up1458.901459
1.0down1458.901458
5.0nearest1458.901460
5.0up1458.901460
5.0down1458.901455
0.05nearest1.021
0.05down1.021
0.05up1.021.05
0.99nearest14.8714.99
0.99down14.8713.99
0.99up14.8714.99
0.9nearest14.8714.9
0.9down14.8713.9
0.9up14.8714.9

The price rounding configurations apply at the shop country and currency level. For example, a configuration set for ACME Switzerland will specifically impact prices in Swiss Francs (CHF) for the corresponding shop and country.

By default, price rounding is disabled. To have it enabled, at least one price rounding configuration should be created.

Only the following prices are affected:

  • prices
  • old prices
  • promotion prices
  • campaign prices

Create a Shop Country Price Rounding

Method Signature

Example

Delete a Shop Country Price Rounding

Method Signature

Example

Get a Shop Country Price Rounding Collection

Method Signature

Example

Rounding Basket/Order prices

In case rounding also needs to be applied on the total of an basket/order, a different configuration shall be applied on shop level.

Order value precision

  • 1,0
  • 5,0

Rounding Type

  • nearest
  • up
  • down

Please note that the float precisions present on price rounding are not available for basket and order level

Rounding basket/order prices when promotions are applied

Whenever promotions or coupons are applied on the Basket, the configured rounding will be taken into consideration when calculating the final item price.

Example:

PrecisionRounding TypeDiscountOriginal PriceFinal rounded Price
1.0nearest10%1458.901313
1.0up10%1458.901314
1.0down10%1458.901312
5.0nearest10%1458.901315
5.0up10%1458.901315
5.0down10%1458.901305

Rounding order total

In case a configuration is also set on order level for rounding, the total value of the order will be rounded as per configuration. This will also ensure that, whenever vouchers or other costs are applied during Checkout, the total value or the order will follow the rule set on configuration level.

Storefront API

This section explains how the Storefront API resolves and returns prices at the time of the request.

Please keep in mind that Storefront API does not configure prices.
Price lists, country prices, campaigns, promotions, and sale categories are configured in the SCAYLE Panel or Admin API. For guidance on configuring prices, campaigns, promotions, and rounding, see above.


How Prices Are Returned

When Storefront API returns a price, it always uses a structured price object, such as:

Price Object Fields

FieldMeaning
withTaxFinal sellable price including VAT and all applied reductions. This is the price a customer pays.
withoutTaxSame price excluding VAT. Useful for B2B displays or tax breakdowns.
currencyCodeCurrency returned for the current shop country (e.g. EUR, USD).
tax.vat.amountAbsolute VAT amount included in withTax.
tax.vat.rateVAT percentage for the current shop/country.
recommendedRetailPriceReference/original price without reductions (often used to show a strike-through price).
appliedReductionsList of reductions that were applied on top of the current base price (campaigns, vouchers). Does not include price changes through pricePromotionKey.

This price object structure is reused across products, variants and basket pricing; only the context (per variant, per product, per basket item) differs.

General Pricing Behavior

Price Calculation

When Storefront API calculates a price, it evaluates the pricing layers in the following order:

Pricing LayerNameNotes
1Promotion price (pricePromotionKey)Only if a promotion price exists
2Campaign price (campaignKey)Only if a campaign price exists
3Merchant priceMarketplace setups
4Customer group priceE.g., B2B customer
5Country priceDerived from shopId
6Base priceRequirement for products to be returned in Storefront API.
  • If a pricing layer does not exist, the Storefront API falls back to the next one.

To receive variants without a base price in the Storefront API, you must configure products as sellable for free as described here. Otherwise, variants without a base price will be ignored.


Where Prices Appear in Storefront API

Products – List Products

  • Endpoint: GET /v1/products

Returned Price Fields

FieldMeaning
priceRange.minLowest final price among the product’s sellable variants
priceRange.maxHighest final price among the product’s sellable variants
variants[].price (optional, if variants are included)Final price for each returned variant
lowestPriorPrice (optional)Historical comparison value

Request example:

Context of the request:

  • shopId=10001 applies country-specific price, currency (EUR), and VAT rules.
  • campaignKey=BLACKWEEK triggers a campaign reduction.
  • No pricePromotionKey is passed, so the campaign applies directly to the base/country price.
  • The campaign discount appears in appliedReductions .
  • lowestPriorPrice is returned because the campaign price is lower than a previously valid price.

Response (excerpt):

Products – Get a Product

  • Endpoint: GET /v1/products/{productId}
FieldMeaning
variants[].priceFinal per-variant price
variants[].lowestPriorPrice (optional)Historical comparison
priceRange (optional)Same range semantics

Request example:

Context of the request:

  • shopId=10001 applies country-specific price, currency (EUR), and VAT rules.
  • campaignKey=BLACKWEEK triggers the campaign reduction (if configured for this product/variants).
  • No pricePromotionKey is passed; the campaign applies directly to the base/country price.
  • Campaign discounts appear in appliedReductions.
  • priceRange summarizes the product’s sellable variants for this request.

Response (excerpt):

Filters (Price Object)

  • Endpoint: GET /v1/filters (You may also receive filters embedded in other endpoints.)
FieldMeaning
price.minLowest price in the result set
price.maxHighest price in the result set

Difference of the price facet as opposed to per-product ranges:

Price SourceWhat it measures
priceRange in /v1/productsMin/max across all variants of one product
price facet in filtersMin/max price of the cheapest variant across products

Request example:

Context of the request:

  • categoryId=123 limits filters to products in this category.
  • shopId=10001 applies country-specific price, currency (EUR), and VAT rules.
  • with=values returns filter values, including the price facet with min / max.
  • campaignKey=BLACKWEEK applies campaign reductions where available, affecting the returned price boundaries.
  • Each product contributes one value: the price of its cheapest sellable variant in this request context.

Response (excerpt):

Variants – Get a Variant

  • Endpoint: GET /v1/variants/{variantId}
FieldMeaning
priceFinal price for this single variant
lowestPriorPrice (optional)Historical comparison

Request example:

Context of the request:

  • shopId=10001 applies country-specific price, currency (EUR), and VAT rules.
  • campaignKey=BLACKWEEK triggers the campaign reduction (if configured for this variant).
  • No pricePromotionKey is passed; the campaign applies directly to the base/country price.
  • The variant response contains its final price object for this single variant.

Response (excerpt):

Basket – Get a Basket

  • Endpoint: GET /v1/baskets/{basketId}
FieldMeaning
items[].price.unitFinal price for one unit
items[].price.totalUnit price × quantity
items[].price.unit.appliedReductionsCampaign, promotion, or other reductions
costFull basket totals

Request example:

Context of the request:

  • shopId=10001 applies country-specific price, currency (EUR), and VAT rules.
  • campaignKey=BLACKWEEK applies a campaign reduction on top (shows in appliedReductions).
  • Basket pricing is recalculated on every GET.
  • items[].price.unit = final unit price; items[].price.total = unit × quantity.
  • cost returns the basket totals.

Response (excerpt):

Basket – Add Or Update

  • Endpoints:
    • POST /v1/baskets/{basketId}/items
    • PUT /v1/baskets/{basketId}/promotions

Request example:

Context of the request:

  • pricePromotionKey=VIP-PPK-2025 sets the effective starting price (no reduction entry).
  • campaignKey=BLACKWEEK applies a relative discount on top of PPK, shown in appliedReductions.
  • The returned basket contains fully recalculated prices for all items and totals.

Response (excerpt):


campaignKey vs. pricePromotionKey

Assume a variant has the following pricing configuration:

  • Base price: €219.00
  • Promotion price (PPK): €199.00
  • Active campaign discount: 10%
Storefront API RequestFinal PriceExplanation
No keys€219.00Base price applies.
pricePromotionKey=24€199.00The promotion price replaces the base price. No entry appears in appliedReductions, because the price itself is replaced.

pricePromotionKey=24

campaignKey=BLACKWEEK

€199.00The promotion price replaces the base price. The promotion price overrides the campaign key and the campaign key is not considered. No entry appears in appliedReductions, because the price itself is replaced.

This shows that:

  • pricePromotionKey changes the effective price but does not mark a product as “on sale” and does not add an entry to appliedReductions.
  • campaignKey applies a reduction on top of the resolved price (base, country, merchant, customer group, or PPK) and does appear in appliedReductions (usually with category: "campaign" and the campaignKey as a label).

Price Range And Filter Calculation

CalculationDescriptionUsed For
Per-product priceRangeFor each product, the Storefront API resolves prices for all sellable variants and returns the min/max values.Product Listing Page - “from” prices, Price summaries on Product Detail Page
Filters price facetFor each product in the result set, the Storefront API takes the price of its cheapest sellable variant, then calculates global min/max across these values.Price sliders and global boundaries

To fully understand how priceRange and the filters price facet behave, it’s important to clarify which variants are included, how prices are resolved, and how aggregation differs between product-level ranges and global filters:

  • Sellable variants only: Variants without a valid resolved price (for example, missing base price) are ignored in both priceRange and filters.
  • Context-aware: Campaigns (campaignKey), price promotions (pricePromotionKey), customer group, merchant, and other filters (e.g., size, color) all influence which variants are considered sellable and what their final prices are.
  • Different aggregation levels:
    • priceRange aggregates within a single product.
    • The price facet aggregates across products in the current result set.

Both use the fallback logic of general pricing behavior.


Sale And NoSale Category Behavior

You have the option only to include products that are on sale in a category as described here (this does not include products included in campaigns or other promotions). The opposite, where you only include products that are not on sale, is also possible. Whether a category is a sale or a non-sale category can be identified through the reserved sale property in the Storefront API. They will be called sale and noSale categories from here on.

Request example:

Response (sale category):

A product will be returned as part of a sale category, if the following conditions are met:

ConditionIncluded in sale categories?
Product has permanent sale price✅ Yes
Campaign sale price exists for this variant✅ Yes
pricePromotionKey only❌ No
campaignKey passed, but no campaign price for this variant❌ No
SituationCategory Exposure
Product not on saleExclude sale, include noSale
Product on sale (permanent or campaign)Include sale, exclude noSale
PPK reduces price onlyExclude sale, include noSale

International Prices

Prices may differ from shop to shop. That may be due to local prices being applied, as well as the different VATs or currencies being applied to different shops.

BehaviorResult
Country price existsThe price corresponding to the country of the shopId will be returned.
Country price missingThe base price, independent of the shopId, will be returned.
VAT and currencyVAT and currency corresponding to the respective shopId will apply to the prices returned.

Edge Cases

These edge cases are important for interpreting price ranges, filters, and basket values.

SituationStorefront API BehaviorExplanation
Variant has no valid base priceVariant cannot be sold; ignored in product priceRange and filtersA base price is mandatory. Without it, the Storefront API cannot produce a final price.
All variants have base price but some have missing country/campaign/PPK pricesOnly variants with valid resolved prices are included in priceRange and basket responsesFalls back through resolution layers. If fallback fails, variant is treated as unsellable for this request.
Only some variants have campaign pricesDependent on variant.Campaign applies per variant, not per product.
Mixed merchant or customer group pricingpriceRange and filters reflect the resolved price per variant under current merchant/groupResults may differ between anonymous and logged-in customers, or between merchants