Version 3 of the Retailer API has been deprecated. Please migrate to the v4 API as soon as possible.
Offers are the backbone of any partner’s ability to use the bol.com platform. Without an offer it’s impossible to sell an article, as we need to know the price, stock level, delivery promise and fulfillment method.
In this functional documentation we provide a brief explanation of the offer processes and common mistakes that can be made while connecting to our API. For the technical documentation and a clear explanation of each field in each request you should check our redoc.
The v3 offers API has been designed to support the continuing growth of our platform and the increasing complexity of the offer domain. Our main focus is to dependently handle all offer related processes in a fast and efficient way regardless of the channel they use. To achieve this we have designed the new version of the API in such a way that it’s ideally connected to systems that are completely aware of specific changes to the assortment of a retailer.
We expect retailers to know which offers specifically need to be updated and also which components have changed for those offers. Only changes need to be communicated to us to ensure as small a load as possible for both your own systems but also for our platform.
This is why we have introduced component-specific update messages for the offer flow. By doing so we encourage you to design your own flow in such a way that you can specifically adjust, for example, a price field without having to send us the unchanged stock, fulfillment option and other offer-related information.
This is achieved by designing three distinct offer update messages, one aimed at updating the price of your offer, another at updating the stock and a third at adjusting the deliverypromise of your offer and whether it’s going to be fulfilled by us (FBB) or the retailer himself (FBR).
The create offer request does combine all these components as all the fields are needed to create a new offer. For updates however it is more efficient to pull the components apart as the updating of a price can be handled far quicker by our systems than the alteration of the deliverypromise (more logic is tied to those fields within our platform thus increasing processing time).
Hence the version is designed for single update messages which specifically update a single component of the offer.
We have noticed that some retailers are combining the three distinct update messages even if they are actually only updating one component of the offer. Please make sure you are not building your feed in such a way as it’s a waste of both our resources. Only send in a specific message for the component that needs to be updated.
We have also decided to only provide single create, delete and update requests without a bulk option. The reason for this is that it is most suited for the design of our API and allows us to both to process the requests as fast as possible but also to properly communicate the failure/success scenario’s with the use of a process status request.
Bulk offer updates are also heavier for our internal infrastructure to process which cause request and processing times to be considerably longer. We have also noticed that most users of our old bulk offer requests weren’t communicating specific changes but were sending us their entire assortment whether anything changed or not.
We expect retailers to do their own delta-determination and only send us relevant changes. The single offer requests are most suited for this scenario and with the use of rate limits we still give enough room to actually process all the necessary changes.
Retailers who are overloading us with non-relevant messages, especially if they are doing this with bulk requests negatively impact other retailers who are correctly communicating changes as we are needlessly spending resources.
Our offer API makes use of Offer ID’s with which you can update or delete your offers. All processes require this offer ID so it’s important you retrieve all offer ID’s for your assortment.
There are two ways with which you can retrieve your offer ID’s, these can be found here.
Keep in mind that a retailer can use a different flow (for example the seller dashboard) to create a offer which you won’t know until you use the offer export. If you use the offer export you can also retrieve the offer ID’s tied to this newly create offer.
The addition of a new offer should be done with the use of a Create Offer request. This request is the only way available in the API to add a new offer to your assortment. The create offer request works with an asynchronous process which means that a process status request is needed to determine if the process has succeeded or not.
A 202 accepted response thus only indicates that your request was technically valid but there are still a lot of (asynchronous) business processes which determine whether we can actually create the requested offer.
If the process status of the request becomes successful then it means we have successfully created the new offer. You will need to retrieve the Offer ID of the newly created offer if you want to update or delete the specific offer in the future.
We have explained the ways to retrieve your Offer ID’s here and advise the process status flow for newly created offers.
Create offer requests can also end up in a Failure or a Time-out. In those cases we do not expose a Offer-ID as the requested offer could not be created. In the case of a time-out we advise to retry the process as it is most likely a issue with increased processing times within our internal services.
In the case of a failure it’s advised to look at the errorMessage field as we use that field to explain the reason for the failure.
A common cause of a failed create offer request is the duplicate offer error. We return this error when we already have a active offer with the specified combination of RetailerId, product and Condition. If this is the case we also communicate the offerID of the active offer, either use that offerId as the new identifier of the product you were creating or delete the active offer and retry your create offer request.
As explained earlier there are three distinct requests that update different components of an offer.
This call allows you to update the following components:
referenceCode: a user-defined identifier which the retailer can set for a specific offer. The ReferenceCode will be exposed in several other domains such as with the Order Retrieval endpoints to allow you to recognize the specific product in your own systems.
onHoldByRetailer: this field allows you to adjust a offer to ‘not for sale’ while keeping it visible for the retailer in his seller dashboard. If this field is set to ‘true’ then we will not be exposing the product in our webshop. If it’s set to ‘false’ then you’re indicating that the product can be sold.
unknownProductTitle: this field allows you to set a temporary product title which is only visible in our systems when the product hasn’t been categorized yet in terms of content categories. The title provided in this field will not be used for our content services but is only temporarily visible in the seller dashboard and allows you to recognize the offer and accordingly add a product category.
fulfillment.type: This field indicates whether the offer is going to be fulfilled by bol.com (FBB) or by the retailer (FBR).
fulfilment.deliveryCode: With this field you can set the deliverycode for a product and indicate when it will be delivered to the customer. Available deliverycodes can be found here.
This call allows you to update the stock for a specific offer and also allows you to indicate if you want your system to be in the lead for the stock countdown process or if you want use our corrected stock flow.
The specific implementation and an explanation of the differences can be found here.
One of the ways you can reduce the load on both your own system but also on our is by excluding FBR (fulfillment by retailer) offers with 0 stock from your update flows. We have noticed that we receive a lot of price and delivery option updates for offers that don’t even have stock.
These are useless requests and needlessly require processing capacity.
Our preference is that you exclude these offers from your feed until they are back in stock again. This cuts down the requests sent by your system and also the load we have to process and freeing up room for other retailers and processes.
This call allows you to solely update the price of your item. The structure of this request is aimed at bundle prices but it’s not required to create multiple bundles.
Unfortunately we have noticed that some retailers are combing the three update requests and sending all three requests every time they are updating a portion of the offer. The API is designed for partial updates, please make sure you design your own system in such a way that you can alter the specific components.
Unfortunately we have noticed that retailers sometimes re-use a EAN for different products (for example different versions or colors of the same product.
If the offers have different prices or references then the specific EAN is continuously updated from version a to version b and back again. Please make sure you always only have one product and one value mapped to a EAN.
We also advise you to actively monitor the amount of traffic you are generating and check if that is in line with the amount of offers that you have. Tracking the amount of updates for single products is also wise as that will easily make issues visible.
We are also actively monitoring these numbers and will require you to fix these flows if it’s obvious you have mapped products incorrectly.
The same behavior can be seen when a retailer has multiple active projects where EANs are in both but with differing values. The same advise applies here as stated above.
Please make sure you don’t use a ‘Delete – Create’ flow which means that for every update you want to process you delete the existing offer and create a new one. We realize this flow allows you to use the create offer request and thus only requires one request instead of three separate requests to update the entire offer.
This however has a negative effect as these types of requests are far more costly for us to process and also greatly affects the processing times of your updates. The create offer request takes the longest to process and has a lower priority compared to update offer requests.
As a result of this flow your assortment will go offline for a period of time as a result of the delete request and stay offline until we have processed the following create request.
We consider the ‘Delete – Create’ flow to be a process that negatively affects the performance of our systems. As such we will be monitoring the behavior and enforce change under our API terms of service if you build your systems accordingly.
The delete offer request can be used to permanently remove the offer from the assortment of a retailer. If the request results in a success (for which the process status request can be used) the specified offer will no longer be visible in the assortment of the retailer.
Please make sure this is the specific user case that you want to fulfill as it’s also possible to set a product to ‘onholdbyretailer’ which also removes the offer from the webshop (but not the assortment of the retailer).
Another option to remove the product from the webshop is by setting the stock of the offer to 0. In this case the offer also remains visible in the seller dashboard of the retailer.
Make sure you know which user case the retailer is expecting by performing this action. If a full delete is required then the Delete offer request is advised. If the retailer still expects to see the item in their seller dashboard but wants it paused or removed from the webshop then we advise the ‘onholdbyretailer’ option.
With this request you can retrieve the status and the values we currently have for the offer tied to the specified offer ID.
This request is currently the only option to determine if a offer is valid and active in the webshop or if it’s invalid in which case you also receive the blocking issues.
We are looking into providing a scalable solution for the retrieval of invalid offers but unfortunately at this moment the only option is to retrieve single offers to determine whether or not they are invalid.