Updating Prices

Overview

Use the Prices API to set or update the price of any article in the Zalando Catalog.

Prices must be specified for each product_simple or EAN. Prices are set separately for each sales channel in which the article is available for sale (such as zalando.de or zalando.co.uk).

You may optionally set a promotional price to alert customers that an article is on sale.

You may optionally provide schedules (with specific start and end times) for each article.

After price updates are accepted by the price API, they pass through a validation system that detects faulty/suspicious price updates and reports them as OK, WARNING or ERROR codes via the Price Reporting API.

The Prices API is write-only. To get the current price of an article, use the article Status Report feature of the zDirect UI. To get all price attempts, schedules and validation results, use the Price Reporting API.

The Prices API is write-only. To get the price of an article, use the article Status Report feature of the zDirect UI.

Price API specification

Non-Euro Currency

For all sales channels that use a currency other than the euro (EUR), you must convert all prices to the target currency yourself and submit the converted value as the price. The zDirect Platform does not perform any currency conversion.

Update the Price of an Article

There are two steps to updating article prices:

  1. Create a price update JSON to specify the updates you wish to make, and
  2. Submit the JSON file to zDirect with the Prices API.

If the price update is submitted for an EAN which already exists in the Zalando Catalog, the price update is immediately propagated to the fashion store. If the EAN is not in the Zalando Catalog, the price update will be stored in our database and passed on to the Zalando Fashion Store once the article is associated with a Zalando SKU (waiting room concept). To check the status of an EAN, use the Products API as described in Checking if an Article Exists in the Zalando Catalog.

Create a Price Update JSON

Prices may be set per article or in batch updates. A single price update JSON may include up to 1,000 EANs for a single Merchant ID.

This is the basic structure of the prices update JSON:

{
  "product_prices": [
    {
      "ean": "$EAN_1",
      "sales_channel_id": "$SALES_CHANNEL",
      "regular_price": {
        "amount": $AMOUNT,
        "currency": "$CURRENCY_CODE"
      }
    },
    {
      "ean": "$EAN_2",
      "sales_channel_id": "$SALES_CHANNEL",
      "regular_price": {
        "amount": $AMOUNT_1,
        "currency": "$CURRENCY_CODE"
      },
      "promotional_price": {
        "amount": $AMOUNT_2,
        "currency": "$CURRENCY_CODE"
      },
      "scheduled_prices": [
        {
          "regular_price": {
            "amount": $AMOUNT_3,
            "currency": "$CURRENCY_CODE"
          },
          "promotional_price": {
            "amount": $AMOUNT_4,
            "currency": "$CURRENCY_CODE"
          },
          "start_time": "$START_TIME",
          "end_time": "$END_TIME"
        }
      ],
      "ignore_warnings": $BOOLEAN
    }
  ]
}

Price Update JSON Requirements

General Requirements

  • One JSON may include a maximum of 1,000 product_price entries.
  • The price updates must all be for a single Merchant ID.
  • All fields and values are mandatory, except for the promotional_price field.
  • Each combination of ean and sales_channel_id in the list of product_prices must be unique.

EAN

The ean of the article should already exist in the Zalando Catalog. In case the ean does not exist in the Zalando Catalog, the price update is delayed until the ean is added to the Catalog.

Sales Channel ID

Use the Sales Channels API to get the available sales channels for a merchant. For more information, and for a list of sales channels codes, see Sales Channels API.

Regular Price

  • The value of amount must be greater than 0.
  • The value of currency must be one of the following ISO 4217 currency codes:
Currency ISO 4217 Currency Code
Euro EUR
Swiss Franc CHF
Polish Złoty PLN
Norwegian Krone NOK
Swedish Krona SEK
Danish Krone DKK
Pound Sterling GBP
Czech Koruna CZK
Croatian Kuna HRK

Warning

The currency MUST correspond to the country you are attempting to set the price in, otherwise your price update will be rejected!

Promotional Price

For each article per sales channel, you may set a promotional price in addition to the regular price by including the promotional_price field in addition to the regular_price value.

Setting a value for promotional_price makes the following changes to how the article is displayed:

  • The article shows the regular price crossed out with the sales price listed in red.
  • The percentage reduction from the regular price is displayed near the price.
  • The article will be visible in the "Sale" section of the Zalando Fashion Store.

If this price update was not part of a schedule, then when the promotional period has ended, you must set the article back to its standard price by submitting a new update with the regular_price field entered as normal, and with no promotional_price field.

The promotional_price field has the following requirements:

  • The promotional price amount value must be greater than 0.
  • The difference between the promotional price and the regular price must be at least 0.01.
  • The promotional price must be less than the regular price.
  • The promotional price must have the same currency type as the regular price.

Scheduling

By using the scheduling feature you can steer when and for how long the price of your article should be online. Each article in the request can have a list of scheduled prices associated with it. A schedule contains a regular_price and an optional promotional_price. It must have a start_time, but it is optional to provide and end_time. If no end_time is provided, then the scheduled price will remain active until it is replaced by another price update or overwritten by another schedule.

start_time and end_time must be in ISO-8601 extended date-time format with an offset from UTC, as defined by RFC 3339, section 5.6, with a resolution up to a microsecond. Examples: "2021-02-02T16:30:15.000Z", "2021-02-02T17:30:15.000+01:00".

Submitting a new price update for an EAN overrides all the existing schedules with the ones provided in the new update. This means that sending a new price update without any schedules will remove any existing schedules for the EAN.

If the base price of the price update is rejected due to being invalid or if the update fails to be applied due to an internal error, then all the schedules will be rejected too and will not be applied.

If one schedule is rejected due to being invalid, then all the schedules will be rejected too and will not be applied.

  • The maximum number of schedules per article is 3.
  • The regular_price and promotional_price must follow the same rules described above.
  • The start_time must be a least 120 minutes after the price update request submission time.
  • There must be a minimum of 60 minutes between any 2 start_times provided.
  • As a start_time you can only use a date/time in the future, not from the past.
  • If an end_time is provided, there must be a minimum of 60 minutes between the start_time and the end_time.
  • If an end_time is provided, it can't be younger than the start_time

Validation

Price Updates will pass through further validation after being initially accepted. Our validation can result in status messages with one of 3 different status codes:

Severity Description
OK This message is for your information. The price update will be applied as expected.
WARNING The price update looks suspicious. See section Enforcing Warnings to change the behaviour of the API to reject all price updates containg a warning.
ERROR The price update is invalid and will be rejected.

The status message for a given price update can be seen in the Price Reporting API. These are the currently possible status messages:

Warning

The set of validations is continuously changing as we improve the validation system to better catch potential errors before they reach the customer.

Code Message Severity
REJECTED_CURRENCY_DOES_NOT_MATCH_SALES_CHANNEL Error - The price must be set in the local currency. ERROR
REJECTED_REGULAR_PRICE_LOWER_EQUAL_THAN_EUR_PRICE Error - The regular price in PLN, SEK, DKK, NOK, CZK, HRK is the same as, or less than, the regular price in EUR. ERROR
REJECTED_REGULAR_PRICE_MIGHT_BE_TOO_HIGH Error - The regular price is more than 6000 EUR when converted. Please contact Zalando’s support team if you want to be excluded from this rule. ERROR
REJECTED_PRICE_TOO_LOW Error - The regular or promotional price is equal to, or less than, the equivalent of 1 EUR. ERROR
REJECTED_DISCOUNT_MIGHT_BE_TOO_HIGH Error - The discount is more than 80%. Please contact Zalando’s support team if you want to be excluded from this rule. ERROR
REJECTED_REGULAR_PRICE_CHANGE_MIGHT_BE_TOO_HIGH Error - The regular price has been decreased by more than 80%. Please contact Zalando’s support team if you want to be excluded from this rule. ERROR
REGULAR_PRICE_CHANGE_TOO_HIGH Warning - The regular price has been increased by more than 330%. WARNING
NEW_REGULAR_PRICE_TOO_LOW Warning - The initial regular price in the new market is less than 20% of the regular equivalent price in EUR. WARNING
INITIAL_REGULAR_PRICE_TOO_LOW Warning - The initial regular price in the new market is less than 20% of the average equivalent price in EUR on zDirect. WARNING

Enforcing Warnings

By default, any price update that failed a validation with a severity of WARNING will simply serve as information and the update will be processed as normal. If you would like your price updates to be rejected when a WARNING is raised, you can set the ignore_warnings field to false.

Note

The ignore_warnings field is set to true by default. That means if the ignore_warnings field is not provided in your request, then all price updates that result in a warning will be processed as normal.

Price Update JSON Example

This example illustrates a JSON that would update the price of two EAN in the same sales channel, with one schedule for the first EAN and the ignore_warnings field set to false, and an optional promotional price for the second EAN:

{
  "product_prices": [
    {
      "ean": "5901234123457",
      "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
      "regular_price": {
        "amount": 89.95,
        "currency": "EUR"
      },
      "scheduled_prices": [
        {
          "regular_price": {
            "amount": 89.95,
            "currency": "EUR"
          },
          "promotional_price": {
            "amount": 50,
            "currency": "EUR"
          },
          "start_time": "2020-05-01T14:00:00Z",
          "end_time": "2020-05-05T22:00:00Z"
        }
      ],
      "ignore_warnings": false
    },
    {
      "ean": "6661234123457",
      "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
      "regular_price": {
        "amount": 59.95,
        "currency": "EUR"
      },
      "promotional_price": {
        "amount": 24.95,
        "currency": "EUR"
      }
    }
  ]
}

Use the Prices API to POST the JSON

Authentication

The zDirect API requires OAuth 2.0 authentication for all API calls. Use the Authentication API to generate access tokens as described in the Authentication section.

Submit the JSON

Use the Prices API to submit the JSON:

POST /merchants/{$MERCHANT_ID}/prices

The following httpie command will POST the file price_update.json to zDirect:

http POST \
https://api-sandbox.merchants.zalando.com\
/merchants/e18e458a-de38-40ee-8119-4130eed7486a/prices \
"Authorization:Bearer $YOUR_ACCESS_TOKEN" \
< price_update.json

Response: Successful

After successful execution of the POST, you receive an HTTP 207 response code. This multi-status response provides a status, code, and optional description value for every price update in the request.

Note

A 207 response cannot be taken in itself as an indication of success. You may receive a 207 response to submissions with errors. The status value following each product_price field must be separately parsed.

Here is an example response:

{
  "results": [
    {
      "product_price": {
        "ean": "5901234123457",
        "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
        "regular_price": {
          "amount": 89.95,
          "currency": "EUR"
        },
      "scheduled_prices": [
        {
          "regular_price": {
            "amount": 89.95,
            "currency": "EUR"
          },
          "promotional_price": {
            "amount": 50,
            "currency": "EUR"
          },
          "start_time": "2020-05-01T14:00:00Z",
          "end_time": "2020-05-05T22:00:00Z",
          "status": "ACCEPTED",
          "code": 0,
          "description": null
        }
      ],
      "ignore_warnings": true
      },
      "status": "ACCEPTED",
      "code": 0,
      "description": null
    },
    {
      "product_price": {
        "ean": "6661234123457",
        "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
        "regular_price": {
          "amount": 59.95,
          "currency": "EUR"
        },
        "promotional_price": {
          "amount": 24.95,
          "currency": "EUR"
        },
      "scheduled_prices": [],
      "ignore_warnings": false
      },
      "status": "ACCEPTED",
      "code": 0,
      "description": null
    }
  ]
}

The status value ACCEPTED indicates that the price update is queued, and will be applied if the EAN exists in the Zalando Catalog, otherwise it will be queued until the EAN is added to the Catalog, and then applied.

Warning

Price updates can take up to 60 minutes to be applied, depending on the load. There could be some situations when we experiencing higher load than usual, which causes the time for price updates to be applied to exceed 60 minutes. This happens approximately once or twice a month.

Response: Unsuccessful

400 (Bad Request)

You will receive an HTTP 400 (Bad Request) response in the following circumstances:

  • One or more required fields are missing
  • The product_price request body is empty
  • The product_price request body includes more than 1,000 items
  • The JSON includes one or more duplicates of a combination of ean and sales_channel_id.

207

Most other invalid submissions are rejected with a multi-status HTTP 207 response code which enumerates the reason for rejection.

In this example, a product_price update was rejected because the regular price amount was zero:

{
  "results": [
    {
      "product_price": {
        "ean": "5901234123457",
        "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
        "regular_price": {
          "amount": 0,
          "currency": "EUR"
        },
        "scheduled_prices": [],
        "ignore_warnings": true
      },
      "status": "REJECTED",
      "code": 101,
      "description": "Regular price amount 0 is not greater than 0."
    }
  ]
}

In this example, a product_price base price update was accepted, but the schedules were rejected because one of the schedules had a duration that was too short:

{
  "results": [
    {
      "product_price": {
        "ean": "5901234123457",
        "sales_channel_id": "01924c48-49bb-40c2-9c32-ab582e6db6f4",
        "regular_price": {
          "amount": 70,
          "currency": "EUR"
        },
        "promotional_price": null,
        "scheduled_prices": [
          {
            "regular_price": {
              "amount": 70,
              "currency": "EUR"
            },
            "promotional_price": {
              "amount": 60,
              "currency": "EUR"
            },
            "start_time": "2020-08-01T14:00:00Z",
            "end_time": "2020-08-01T14:05:00Z",
            "status": "REJECTED",
            "code": 101,
            "description": "Schedule duration is too short. Provided duration: 5 minutes. Minimum allowed schedule duration: 60 minutes."
          },
          {
            "regular_price": {
              "amount": 70,
              "currency": "EUR"
            },
            "promotional_price": {
              "amount": 50,
              "currency": "EUR"
            },
            "start_time": "2020-08-01T16:00:00Z",
            "end_time": "2020-10-05T17:00:00Z",
            "status": "REJECTED",
            "code": 101,
            "description": "There was at least one invalid schedule, so all schedules will be rejected."
          },
          {
            "regular_price": {
              "amount": 70,
              "currency": "EUR"
            },
            "promotional_price": {
              "amount": 40,
              "currency": "EUR"
            },
            "start_time": "2020-08-01T18:00:00Z",
            "end_time": "2020-10-05T19:00:00Z",
            "status": "REJECTED",
            "code": 101,
            "description": "There was at least one invalid schedule, so all schedules will be rejected."
          }
        ],
      "ignore_warnings": true
      },
      "status": "PARTIALLY_ACCEPTED",
      "code": 105,
      "description": "Update Partially Successful: Base Price accepted, check scheduled_prices field for scheduled price update results"
    }
  ]
}

Additional Resources

Contact Support