Managing Inventory

Basic Inventory Concepts

You as a seller may sell the same product in many different ways. Two copies of a book for sale may both be in used condition, but show very different signs of use. Or you sell many copies of one book in new condition, with some stored in one warehouse and some in another warehouse (such that handling and transport times differ). The Kaufland marketplace permits you to save an id_offer on inventory units to uniquely identify different units of the same product, so these similar units can be tracked and managed independently of one another.

Every inventory change is performed with respect to a single storefront. Inventory changes performed directly by REST API specify the storefront, and adding an inventory CSV file requires specifying which storefront the file pertains to. If you are selling on multiple storefronts, units will be connected via your id_offer. When units are connected by id_offer, we ensure that their warehouse and quantity are kept in sync. Other properties of connected units are allowed to differ by storefront and are not kept in sync (e.g., prices, shipping group, handling time, note).

If you don't want inventory and warehouse to be considered as shared information between two units, they must have different id_offer. In order to minimize erroneous synchronization of quantity and warehouse, we will reject attempts to create a unit if we already store a unit with same id_offer and different EAN or condition, or which is fulfilled by Kaufland.

Note: Please note that the id_offer field must be UNIQUE across the seller's entire inventory.
For example, if you use the id_offer value "xyz-123" to offer a product, then you cannot use the same id_offer value "xyz-123" for any other offer unless offering same Product in a different storefront.

Creating Units

Once you have added an product to the Kaufland marketplace (see the Managing Product Data page), or if the product already exists on the site, you need to add your inventory information. There are two ways to do this:

  1. REST API: use the /units/ endpoint to upload inventory data one product at a time.
  2. CSV Files: use the /import-files/ REST API endpoints to send inventory data for multiple products at once.

Adding new inventory with the REST API

The simplest way to update your inventory data is to send JSON requests to the /units/ REST API endpoint. However, you can only update one product at a time this way, so far large volumes of changes, sending CSV files is more efficient.

Note: We prevent this action for units fulfilled by Kaufland and respond with an HTTP 403 error code. Read more about FBK.

To use this endpoint, you need to send a POST request with a JSON object that describes your inventory. Here's an example JSON object:

{
	"id_product": 35903281,
	"ean": "4011905437873",
	"condition": "NEW",
	"listing_price": 5999,
	"minimum_price": 5100,
	"amount": 200,
	"note": "",
	"id_offer": "AB1234",
	"handling_time": 2,
	"id_warehouse": "1345",
	"id_shipping_group": "3457",
	"storefront": "de",
	"vat_indicator": "standard_rate"
}

Here are explanations for each property of the object:

  • id_product: The internal Kaufland ID of the product. You must either specify an id_product or ean (or both).
  • ean: The EAN of the product. You must either specify an id_product or ean (or both).
  • condition: "NEW" means that the product is not used. The available conditions are listed below.
  • listing_price: The price you would like to sell the product at, in integral cents in the currency of the storefront (CZK or EUR or PLN). This value must be greater than zero, and has a maximum that differs by currency (maximum 25 million CZK, 1 million EUR or 4.5 million PLN).
  • minimum_price: The minimum price you would be willing to sell at, in integral cents of the storefront currency. If this property is specified, the price of your inventory will automatically be adjusted. Only relevant if you want to use Smart Pricing.
  • amount: How many of the product you have in stock. Note that amount is limited to 99999.
  • note: A note about the products condition for the customer. This gives some extra details for used products. This is limited to 250 characters.
  • id_warehouse: The warehouse ID the product is located in. If not specified, your default warehouse.
  • id_offer: Your internal ID for the unit (offer and unit are synonyms on the Kaufland marketplace). Whatever you set here will be included in the unit, but not the product data. This is used to identify units which should be connected over several storefronts. Read more here.
  • handling_time: The amount of working days till the order is handed over to the carrier. (Always use with transport_time, which is part of the shipping group.) Has to be equal to or bigger than zero [>=0].
  • id_shipping_group: ID of the shipping group the unit should be assigned to.
  • storefront: The storefront parameter indicates on which marketplace the offer should be placed.
  • vat_indicator: VAT indicator determining the VAT rate of the unit. The indicator should match the available VAT indicator of the storefront. You can find the most recent VAT indicator mapping at the /vat-indicators/ REST API endpoint.

If you get a 201 response code, then the unit was created successfully. Otherwise, you should get a JSON object back with an error message in the message property, for example:

{
	"message": "Can not decode body"
}

Note: The POST /units/ endpoint should be used to add new units to an product. However, if you send data for an product for which you already have a unit, it might update the existing unit, instead of creating a new unit. Here are the rules for what happens:

When a new unit is created:

  • You have no existing units for the product on the same storefront.
  • You have existing units for the product on the same storefront, and they do not have an id_offer set, and the newly submitted unit has no id_offer, but the new unit has a different condition than all of the existing units.
  • You have existing units for the product on the same storefront, and they do not have an id_offer set, but the new unit has an id_offer.
  • You have existing units for the product on the same storefront, and they have an id_offer set, but the new unit has a different id_offer.
  • You have existing units for the product on the same storefront, and they have an id_offer, but you send a new unit without an id_offer.

When an existing unit is updated:

  • You have existing units for the product on the same storefront, and they do not have an id_offer set, and the newly submitted unit has no id_offer, but the new unit has the same condition as one of the existing units.
  • You have existing units for the product on the same storefront, and they have an id_offer set, and the new unit has the same id_offer as one of the existing units.

Available Conditions

String Integer
"NEW" 100
"USED___AS_NEW" 200
"USED___VERY_GOOD" 300
"USED___GOOD" 400
"USED___ACCEPTABLE" 500

Updating inventory with CSV files

Since you can only add or update one product at a time through the /units/ REST API endpoint, it can be more efficient to send a batch file with many units in it. There are two types of inventory CSV files:

  1. INVENTORY FEED file: a full dump of your entire inventory. Details about this type of file are available on the Inventory CSV Files page.
  2. INVENTORY COMMAND file: a list of commands to alter your existing inventory in the Kaufland marketplace. Details about this type of file are available on the Inventory CSV Files page.

Allowed VAT indicators

Each storefront has a set of eligible VAT indicators for units. Use the /vat-indicators/ endpoint to find the allowed VAT indicators and their corresponding VAT rates for a storefront. For example, the German storefront allows 'standard_rate' and 'reduced_rate_1' indicators, corresponding to 19% and 7% VAT rates respectively. Order units will have a VAT rate in the vat field corresponding to the VAT indicator provided for the unit.

Retrieving Units

You can get a list of all of your own units by sending a GET request to the /units/ endpoint. Note: it can take several minutes for units to show up in this list after they are created.

Note: By default this endpoint only returns units which need to be fulfilled by the seller. To get units fulfilled by Kaufland an appropriate filter parameter needs to be applied. Read more about FBK.

Updating Units

To update a single unit, send a PATCH request to the /units/{id_unit}/ REST API endpoint, replacing {id_unit} in the URL with the internal Kaufland ID of the unit. The body of the request should contain a JSON object, similar to the JSON you send to create a new unit, with one difference: you cannot change the id_product or id_offer of a unit. To change those properties, you must delete the unit and create a new one.

Note: We prevent this action for units fulfilled by Kaufland and respond with an HTTP 403 error code. Read more about FBK.

Note: you can also update units by sending a POST request to the /units/ endpoint. See the above note on updating with a POST request for details.

Updating Units in Bulk

Note: We prevent this action for units fulfilled by Kaufland and respond with an HTTP 400 error code. Read more about FBK.

To update multiple units within the same request you can send a POST request to the /units/bulk REST API endpoint, the body of the request should contain an array of JSON objects where each one represent a single unit update, each unit request object would look like the following (The example uses handling time, Please refer to the following page for a full list of fields):

[
    {
        "unit_id": 12345,
        "unit_data": {
            "handling_time": 1
        }
    }
]

This will update the handling time of the unit with id 12345, upon a successful request (not a successful unit update, rather the whole request succeeded) the return code will be 207 which means Multi Status and the response will be an array of objects each one representing the result of a unit update, with a successful unit update the response should look like the following example:

{
    "data": [
        {
            "id_unit": 12345,
            "status_code": 200,
            "unit": {
                "id_unit": 12345,
                "status": "AVAILABLE",
                "currency": "EUR",
                "condition": "NEW",
                "note": null,
                "id_warehouse": null,
                "id_shipping_group": null,
                "id_offer": null,
                "listing_price": 100,
                "minimum_price": 100,
                "price": 100,
                "id_product": 1,
                "amount": 1,
                "date_inserted_iso": "2023-11-30T00:00:00.000Z",
                "date_lastchange_iso": "2023-11-30T00:00:00.000Z",
                "handling_time": 1,
                "shipping_rate": 1,
                "storefront": "DE",
                "transport_time_min": 1,
                "transport_time_max": 1,
                "fulfillment_type": "fulfilled_by_merchant"
            }
        }
    ]
}

The id_unit and status_code combination can be used to determine whether the unit was successfully updated or not, the table below explain what each status code stands for as well as an example response:

Status code Representation Example
200 Success
{
    "data": [
        {
            "id_unit": 12345,
            "status_code": 200,
            "unit": {
                "id_unit": 12345,
                "status": "AVAILABLE",
                "currency": "EUR",
                "condition": "NEW",
                "note": null,
                "id_warehouse": null,
                "id_shipping_group": null,
                "id_offer": null,
                "listing_price": 100,
                "minimum_price": 100,
                "price": 100,
                "id_product": 1,
                "amount": 1,
                "date_inserted_iso": "2023-11-30T00:00:00.000Z",
                "date_lastchange_iso": "2023-11-30T00:00:00.000Z",
                "handling_time": 1,
                "shipping_rate": 1,
                "storefront": "DE",
                "transport_time_min": 1,
                "transport_time_max": 1,
                "fulfillment_type": "fulfilled_by_merchant"
            }
        }
    ]
}
400 Validation error
{
   "data":[
      {
         "id_unit":12345,
         "status_code":400,
         "message":"Parameters [handlingTime] are missing or have wrong value.",
         "errors":[
            {
               "field":"handling_time",
               "message":"handling_time must be greater than 0"
            }
         ]
      }
   ]
}
404 Unit Not found
{
   "data":[
      {
         "id_unit":12345,
         "status_code":404,
         "message":"ItemUnit with id 12345 not found",
         "errors":[]
      }
   ]
}
500 Internal server error
{
   "data":[
      {
         "id_unit":12345,
         "status_code":500,
         "key":"internal_server_error",
         "message":"Internal server error"
      }
   ]
}

Important: There are a couple of rules to keep in mind when using this endpoint, failure to respect these rules will result in the failure of the entire request: :

  1. Your request SHOULD NOT have more than 150 units in the body, exceeding this limit will result in a 400 response and will fail the whole request.
  2. The request SHOULD NOT contain duplicate units, if duplicates are detected the whole request is rejected.

Note: Sending an empty request with just {"data": []} will result in an empty response [] and won't fail the request. Status code will still be 207.

Full example

The following is an example of a request that will contain three unit updates, where one will update successfully, the second will fail with a validation error and the third one will fail with an internal server error in order to demonstrate the three different cases combined:

The request body:

[
  {
    "id_unit": 12345,
    "unit_data": {
      "handling_time": 4,
    }
  },
  {
    "id_unit": 45678,
    "unit_data": {
      "listing_price": 0,
    }
  },
  {
    "id_unit": 68576,
    "unit_data": {
      "note": "",
    }
  }
]

The response:

{
   "data":[
      {
         "id_unit":12345,
         "status_code":200,
         "unit":{
            "id_unit":12345,
            "status":"AVAILABLE",
            "currency":"EUR",
            "condition":"NEW",
            "note":null,
            "id_warehouse":null,
            "id_shipping_group":null,
            "id_offer":null,
            "listing_price":100,
            "minimum_price":100,
            "price":100,
            "id_product":1,
            "amount":1,
            "date_inserted_iso":"2023-11-30T00:00:00.000Z",
            "date_lastchange_iso":"2023-11-30T00:00:00.000Z",
            "handling_time":4,
            "shipping_rate":1,
            "storefront":"DE",
            "transport_time_min":1,
            "transport_time_max":1,
            "fulfillment_type":"fulfilled_by_merchant"
         }
      },
      {
         "id_unit":45678,
         "status_code":400,
         "message":"Parameters [listingPrice] are missing or have wrong value.",
         "errors":[
            {
               "field":"listing_price",
               "message":"listing_price must be greater than 0"
            }
         ]
      },
      {
         "id_unit":68576,
         "status_code":500,
         "key":"internal_server_error",
         "message":"Internal server error"
      }
   ]
}

Deleting Units

To delete a unit, send a DELETE request to the /units/{id_unit}/ endpoint, replacing {id_unit} in the URL with the internal Kaufland ID of the unit.

Note: We prevent this action for units fulfilled by Kaufland and respond with an HTTP 403 error code. Read more about FBK.

Retrieving Single Units

You can get the stored information for a single unit if you have its ID. Just send a GET request to the /units/{id_unit}/ endpoint, replacing {id_unit} in the URL with the internal Kaufland ID of the unit.