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.

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",
    "eco_participation": 99,
    "battery_participation": 100,
    "manufacturer_guarantee_years": 2,
}

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. Required for non-EU sellers with more than one warehouse, or for EU sellers with more than one warehouse with at least one non-EU warehouse. If not specified, your default warehouse will be used — if no default warehouse is configured, the request will be rejected.
  • 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.
  • eco_participation: The Eco-Participation value in eurocents (integer). If provided, has to be bigger than zero [>0]. Only relevant for specific products on the French storefront.
  • battery_participation: The Battery-Participation value in eurocents (integer). If provided, has to be bigger than zero [>0].
  • manufacturer_guarantee_years: Duration of the manufacturer guarantee in years (integer). If provided, has to be bigger than zero [>0] and cannot exceed 99.

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
"REFURBISHED___AS_NEW" 110
"REFURBISHED___VERY_GOOD" 120
"REFURBISHED___GOOD" 130
"REFURBISHED___ACCEPTABLE" 140

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.

Checking Whether Units Are Live

Unit responses include an is_live boolean field that indicates whether your offer is currently visible and active on the storefront. Unlike the status field, which only reflects the unit's own state, is_live takes all factors into account - including product data validity and blocklisting. Use is_live: true as the single reliable signal that your offer is live on Kaufland.

Retrieving Not-Live Reasons

If is_live is false for one of your units, you can retrieve the specific reason(s) by sending a POST request to the /units/status REST API endpoint, passing the unit IDs in the JSON request body as unit_ids. The lookup is scoped to a single storefront, so query each storefront your units are listed on separately:

POST /units/status?storefront=de
Content-Type: application/json

{ "unit_ids": [1, 2, 999] }

The response will be a 200 with an array of objects, each one representing the result for a single unit:

{
	"data": [
		{
			"id_unit": 1,
			"status_code": 200,
			"is_live": false,
			"reasons": [
				{
					"reason": "stock_update_needed",
					"reason_description": "The stock quantity is set to zero. Please update your stock to reactivate the offer."
				},
				{
					"reason": "product_data_incomplete",
					"reason_description": "Some product data is incomplete or needs review. Please review and update the product data.",
					"details_url": "https://www.kauflandglobalmarketplace.com/en/seller-university/selling/product-data/general/"
				}
			]
		},
		{
			"id_unit": 2,
			"status_code": 200,
			"is_live": true,
			"reasons": []
		},
		{
			"id_unit": 999,
			"status_code": 404,
			"message": "Unit not found"
		}
	]
}

The id_unit and status_code combination can be used to determine whether the unit was found. The table below explains what each status code stands for:

Status code Representation Description
200 Success The unit was found. is_live and reasons (empty if live) are included.
404 Unit not found No unit with this id_unit exists on the requested storefront. A unit that is listed on a different storefront is also reported as not found, so check the storefront you queried before assuming the unit was deleted. Only id_unit, status_code and message are included.

Each entry in reasons has the following fields:

Field Description
reason Machine-readable identifier of the reason. See Not-Live Reason Codes for the full list.
reason_description Human-readable description of the reason, in English. Intended to be shown to the seller, not parsed by software.
details_url (Optional) Link with more information for the seller. Only present where available - its absence is not an error.

Important:

  1. Your request must not contain more than 20 unit IDs in the unit_ids array; exceeding the limit rejects the whole request with a 400 rather than returning a partial result. See the endpoint reference for the full unit_ids rules.
  2. This endpoint is intended for on-demand lookups (e.g. triggered by a seller check or a support flow), not for default or bulk polling. Requests are rate-limited, see the Rate limits page. To learn when a unit stops being live without polling, subscribe to the item_unit_not_live push notification and call this endpoint for the unit it reports.
  3. If the reasons for a unit that is not live cannot be determined, the whole request fails rather than returning an incomplete reasons list: 503 when the downstream service is unavailable or times out, 500 for any other downstream failure. Both are safe to retry, and neither means "this unit has no reasons".

Not-Live Reason Codes

The reason values that /units/status can return, with the reason_description and, where one exists, the details_url sent alongside each of them:

Reason Reason description More info
unverified_authenticity The authenticity of this product could not be confirmed. Seller guidelines
image_usage_issue The image usage rights for this product could not be confirmed. Product data guideline
intellectual_property_issue A potential intellectual property concern has been identified. Seller guidelines
brand_authorization_issue Your authorisation to sell this brand could not be confirmed. Seller guidelines
other_compliance_issue This offer doesn't currently meet the General Terms and Conditions of Kaufland Global Marketplace. Seller guidelines
regulatory_review The product does not comply with our General Terms and Conditions. Seller guidelines
price_check_needed The listed price needs a quick check. Please review and update the price. Offers
product_data_mismatch Some product data doesn't match the item listed. Please review and update the product data. Product data
divid_number_needed This offer is subject to the Single-Use Plastics Fund Act. Please register on the EPR compliance page in the Seller Portal to activate this offer. EPR general information
idu_number_needed This offer is subject to the French IDU number requirement. Please register on the EPR compliance page in the Seller Portal to activate this offer. EPR France
epr_number_needed This offer is subject to the Extended Producer Responsibility (EPR) requirement. Please register on the EPR compliance page in the Seller Portal to activate this offer. EPR general information
gpsr_info_needed This offer needs the contact details of an EU-based responsible person under the GPSR. Please add the name, address, phone number, and e-mail address to continue. GPSR
weee_number_needed This offer needs a valid WEEE registration number. Please add one in the Seller Portal to continue. EPR general information
ioss_threshold Offers under €150 shipped from outside the EU will be paused from 1 July 2026 under IOSS regulations. Offers
recommerce_eligibility This offer isn't currently eligible for recommerce. Please contact Seller Support for more information. Seller guidelines
eco_fee_pending The EPR eco fee for this offer is still being calculated. It will go live automatically once the calculation is complete and all pending issues are resolved. EPR management by Kaufland
account_documentation_needed Some account documentation, such as your VAT ID, needs to be updated. Please update your details in the Seller Portal. Formal framework
product_data_incomplete Some product data is incomplete or needs review. Please review and update the product data. Product data
stock_update_needed The stock quantity is set to zero. Please update your stock to reactivate the offer. Offers
offer_paused This offer is currently paused. Please reactivate it to make it visible again. Offers
unknown_reason This offer is currently not live. Please contact Seller Support for more information. -

New reasons may be added over time - this is a non-breaking change. Always fall back to displaying reason_description for reasons you do not recognize yet, rather than failing the request.

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: 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

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",
                "is_live": true
            }
        }
    ]
}

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",
                "is_live": true
            }
        }
    ]
}
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",
            "is_live":true
         }
      },
      {
         "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.

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.