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.
This topic provides an explanation of the offer processes and common mistakes that can be made while connecting to our API. For the complete reference Offers documentation refer to the Redoc.
The 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 handle all offer related processes dependently, in a fast and efficient way regardless of which channel is used by the partners. To achieve this we have designed the new version of the API so that it is optimally 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. You should only communicate changes to us to ensure as small a load as possible for both of our systems.
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 for 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 due to the fact that more logic is tied to those fields within our platform, thus increasing processing times.
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 this way, since it wastes resources on both sides. You should only send specific messages for the components that need 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 scenarios 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 allow enough bandwidth to process all the necessary changes.
Retailers who are overloading us with non-relevant messages, especially with bulk requests, negatively impact other retailers who are correctly communicating changes and cause us to needlessly spend resources.
Our offer API makes use of offer IDs with which you can update or delete your offers. All processes require this offer ID so it’s important that you retrieve all offer IDs for your assortment.
There are two ways to retrieve your offer IDs, described here.
Bear in mind that a retailer can use a different flow, for example the Seller Dashboard, to create an offer which won’t be known until you use the offer export. If you use the offer export you can also retrieve the offer IDs tied to this newly created 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 uses 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 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 IDs here and advise using 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 an offer ID as the requested offer could not be created. In the case of a timeout we advise users to retry the process, since it is most likely to be related to increased processing times within our internal services.
In the case of a failure we advise looking at the
errorMessage field as we use that field to explain the reasons for failures.
The duplicate offer error is a common cause of a failed create offer request. We return this error when we already have an 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
referenceCodewill 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: allows you to adjust a offer to not for sale while keeping it visible for the retailer in their 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, you are indicating that the product can be sold.
unknownProductTitle: 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: allows you to set the
deliverycodefor a product and indicate when it will be delivered to the customer. The list of available delivery codes 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 of our systems is by excluding Fulfillment By Retailer (FBR) offers with 0 stock from your update flows. We often receive a lot of price and delivery option updates for offers that don’t have stock.
These are useless requests and needlessly require processing capacity.
We prefer 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 frees up room for other retailers and processes.
This call allows you to update only the price of your item. The structure of this request is aimed at bundle prices but it is not required to create multiple bundles.
We discourage our partners from using the following practices with the Offer API:
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, so please make sure you design your own system in such a way that you can alter the specific components.
We have noticed that retailers sometimes reuse a single 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 an EAN.
We also advise you to actively monitor the amount of traffic you are generating and check if it 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. We recommend the same steps as described 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 affect 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 create request that follows.
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 use 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 use 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 invalid, in which case you will also receive its 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.