Offer API
This API is currently in beta with limited availability. If you want to participate, you can look here. If you have any questions or remarks that can improve this API, mail us at retailerapi-beta@bol.com. Updates to this beta will be communicated via our developers portal. |
The bol offer API allows you to execute the following actions on the bol marketplace:
-
Creating offer data
-
Create a new offer: this endpoint allows you to create a new offer
-
-
Retrieving offer data
-
Get an offer: this endpoint allows you to retrieve a single offer
-
Get offers: this endpoint allows you to retrieve your offer data by a given criteria in a paginated manner
-
Get not for sale reasons: this endpoints allows you to retrieve the reasons why an offer is not for sale
-
-
Updating offer data
-
Update an offer: this endpoint allows you to update offer content
-
-
Deleting offer data
-
Delete an offer: this endpoint allows you to delete an offer
-
In case you are looking for offer related events, please take a look at our Subscription API.
Please be aware that the offer API as of version 11 is processing data synchronously. This means that you do not need the process status flow anymore when using this version of the offer API. |
Creating offer data
Creating an offer on the bol marketplace can be done via this POST endpoint, which will instantly return back a success or error. The following fields and objects are present when creating an offer:
Field | Description |
---|---|
|
The EAN number associated with this product. In case you provide an ISBN, the ISBN will be replaced with the actual EAN belonging to this ISBN. |
|
In case this product is not known to the bol marketplace you can use this field to identify this particular product. If a product is known to bol, this field will be ignored. A maximum of 500 characters is supported. |
|
The economic operator entity. See the economic operator API for more information. |
|
An optional user-defined reference that help you identify this particular offer. A maximum of 100 characters is supported. |
|
Temporarily pauses this offer from listing on the bol marketplace. |
|
The condition details that apply to this offer. |
|
The pricing details that apply to this offer. |
|
The country in which you want to sell this offer. This can be the Dutch market |
|
Fulfilment details on how you want to fulfil an order to the customer. |
|
Information on your stock level. |
The unique combination within the bol marketplace to create an offer is retailerId
+ ean
+ condition
+ countryAvailabilities.countryCode
.
If you want to know which fields are mandatory to provide, you can check our ReDoc documentation page.
ean
The ean
field is used to identify the item that you want to sell on bol. The ean
is required and it is also allowed to provide an ISBN (International Standard Book Number) in this field. When you provide an ISBN, the bol marketplace will link it to the actual ean of that item. In that case, the ISBN is discarded. The ean
is part of the unique key of an offer within the bol marketplace and can therefore not be changed if the offer is created successfully. If you want to change the ean
of an offer, you need to delete the current offer and create a new one.
unknownProductTitle
In case the bol marketplace doesn’t know the provided ean
for this offer, it might be difficult to find this product back in the bol systems. Therefore, you can provide an unknownProductTitle
that allows you to easily find back this offer. If you want to know if the bol marketplace already knows this ean
, you can use the GET product-ids endpoint for this. If this endpoint provides you a bolProductId
, then the bol marketplace already knows this ean
.
economicOperatorId
In accordance with the Digital Services Act, the bol marketplace must show consumers who is the responsible economic operator in the EU for a product before they purchase it. Every retailer is individually responsible for providing the required economic operator information. The economicOperatorId
is the identifier of the created economic operator. If you do not have an economicOperatorId
yet, then you need to create this first. You can do this by using our Economic Operator API. You can update the economic operator anytime.
The bol marketplace is required to provide the economic operator to customers by EU legislation. Therefore your offer will only become online if this data is provided. If you fail to provide this data, customers will never be able to purchase an item via this offer. |
reference
The reference
field can be used to define a custom reference. The bol marketplace only uses this reference to help you find data back within the bol marketplace. You can therefore use this for your own recognition. It is not mandatory to provide a reference but if you do so, then take into account that the field size is limited to 100 characters. It is always possible to update the reference
afterwards.
onHoldByRetailer
The onHoldByRetailer
field can be used to temporarily pause this offer. This only applies if your offer is online on the bol marketplace. If your offer is already marked as offline, pausing it will have no effect. If you want to pause an online offer, you can set this field to true
. If you want to continue selling this offer, you can set this field back to false
.
condition
The condition
object contains information regarding the condition of the product that you want to sell on the bol marketplace. Depending on the type
of the condition, logic applies to what data you need to provide. The type
can only be any of the following:
-
NEW
- indicates that the product being sold is new. -
SECONDHAND
- indicates that he product being sold is not new anymore. In case you provideSECONDHAND
as the condition, you are also required to provide theattributes
object:-
You need to provide the
state
. The state refers to the state of the product. This can only beAS_NEW
,GOOD
, orMODERATE
. -
You can optionally provide a
comment
. The comment is an addition to the state of the product. You can provide any text here (for instance: "slightly used" or "scratch on side of the product") up to 2000 characters. E-mail addresses are not allowed in this field.
-
-
REFURBISHED
- indicates that the item being sold is refurbished. In case you provideREFURBISHED
as the condition, you are also required to provide theattributes
object:-
You need to provide
grade
. The grade can either beA
,B
, orC
. The grade refers to the quality of the refurbished item, where gradeA
means "the best quality; near-mint condition." , gradeB
means: "second-best quality; light scratches" and gradeC
means: "low cosmetic quality". -
You need to provide the
margin
. The margin can either betrue
orfalse
and indicates whether there is a margin adjustment due to the condition.
-
The |
pricing
The pricing
object refers to the base pricing that applies to this offer. This price does not include any promotions. The bol marketplace allows you to use up to four prices. It is not required to use more than 1 price, but you do need to provide at least 1. You cannot set the pricing
to null
(as it is mandatory to provide) nor you can send an empty array.
You can set the price using the bundlePrices
object. If you plan to provide more than 1 price, you need to reward your customers with a (small) discount if they buy more than 1 unit (volume discount). The quantity
therefore needs to increase per element in the array, whereas the unitPrice
needs to decrease. An example of selling an item with two prices is the following:
{
"pricing": {
"bundlePrices": [
{
"quantity": 1,
"unitPrice": 9.99
},
{
"quantity": 2,
"unitPrice": 8.99
}
]
}
}
In this example, if a customer buys the product with a quantity of 2, the customer gets both products for 8,99 euro (17,98 euro in total). You can always adjust the price in the future if necessary.
The bol marketplace accepts a |
countryAvailabilities
The countryAvailabilities
object indicates in which country you want to sell this offer, via the countryCode
field. You have four options to indicate where you want to sell this item:
-
You omit this object entirely. If you do not provide a
countryCode
, the bol marketplace will use the default country setting that is attached to your retailer account. If it is set to Dutch, your offer will only be published in the Netherlands. If it is set to Belgium, it will only be published in Belgium. Be aware that if you change this setting on your account, all your offers will also be affected by this change. -
You add the
countryCode
withNL
- in this case you overrule your account setting. Your offer will only be published on the Dutch marketplace. -
You add the
countryCode
withBE
- in this case you overrule your account setting. Your offer will only be published on the Belgium marketplace. -
You add both country codes (
NL
andBE
) to this array. You overrule your account setting. Your offer will be published to the Belgium and Dutch marketplace. If you change your account setting, this change will not affect these offers.
It is always possible to change the country availability afterwards. If you want to change the country availability back to your default account setting, you can send null
or omit it from they payload (that will default to null
). Note that sending an empty array is not allowed.
fulfilment
The fulfilment
object indicates how you want to fulfil a potential customer order. Depending on the method
of the fulfilment, logic applies to what data you need to provide. The method
can only be any of the following:
-
FBB
- indicates that the fulfilment is done by bol (via the logistics via bol proposition). If you provideFBB
, you do not need to provide more data. Bol with handle the fulfilment based on the most optimal conditions towards the customer. -
FBR
- indicates that you do the fulfilment yourself. If you provideFBR
, you also need to provide aschedule
. This schedule can be one of the following types:-
MY_DELIVERY_PROMISE
- this schedule refers to your custom created delivery promise. You can create this delivery promise via the seller dashboard under "settings". If you did not create a custom delivery promise via the seller dashboard but do provide this value via the API, the bol marketplace will mark your offer as "offline" as the bol marketplace cannot find the corresponding schedule. As a consequence, it is unknown to provide the customer with a correct delivery promise. -
SHIPPING_VIA_BOL
- this schedule refers to the shipping via bol proposition. If you are using shipping via bol, you can use this option to mark this offer for shipping via bol. If you did not register for shipping via bol but are using this schedule, the bol marketplace will mark your offer as "offline" as you are not participating in this proposition. -
BOL_DELIVERY_PROMISE
. this schedule refers to delivery promises that are predefined by bol. If you use this schedule, you also need to provide thedeliveryPromise
object. The following combinations are possible:-
Delivered within 24 hours with a cut-off order time of 12:00 PM:
minimumDaysToCustomer
=0
.maximumDaysToCustomer
=1
.ultimateOrderTime
=12:00
-
Delivered within 24 hours with a cut-off order time of 11:00 PM:
minimumDaysToCustomer
=0
.maximumDaysToCustomer
=1
.ultimateOrderTime
=23:00
-
NOTE: The
ultimateOrderTime
accepts the following values:12:00
,13:00
,14:00
,15:00
,16:00
,17:00
,18:00
,19:00
,20:00
,21:00
,22:00
,23:00
-
Delivered within 1 to 2 days:
minimumDaysToCustomer
=1
.maximumDaysToCustomer
=2
. -
Delivered within 2 to 3 days:
minimumDaysToCustomer
=2
.maximumDaysToCustomer
=3
. -
Delivered within 3 to 5 days:
minimumDaysToCustomer
=3
.maximumDaysToCustomer
=5
. -
Delivered within 4 to 8 days:
minimumDaysToCustomer
=4
.maximumDaysToCustomer
=8
. -
Delivered within 1 to 8 days:
minimumDaysToCustomer
=1
.maximumDaysToCustomer
=8
. -
NOTE: If the delivery takes longer than 1 day, you do not need to provide the
ultimateOrderTime
.
-
-
Stock levels within the |
stock
The stock
object indicates the amount of products that you have. Whether you need to provide this object depends on the type of offer that you are creating:
-
fulfilment.method
=FBB
: if you are creating an offer for stock via our "Logistics via bol" proposition, the warehouse manages your stock levels and inventory. In that case you do not need to provide thestock
object. If you want to know how much stock there is left in our warehouse, you can use the FBB inventory endpoint. -
fulfilment.method
=FBR
: if you are creating an offer for stock that you are fulfilling from your own (or 3rd party) warehouse, then you need to provide theamount
of stock you have left in your warehouse and determine whether you want to manage stock levels yourself (by using themanagedByRetailer
flag). If you want the bol marketplace to manage your stock levels, you can set this flag tofalse
. In that case, the bol marketplace automatically takes open orders into account by (temporarily) reserving a part of your stock, to avoid overselling. In case you set themanagedByRetailer
flag totrue
, the bol marketplace will not reserve stock for your already placed orders. Be aware that if you manage it yourself, your performance indicator might be impacted if you oversell and -as a consequence- fail to meet your delivery promise towards the customer.
You can update the stock levels anytime in the future.
Offer response
In case of a successful request to the bol marketplace, you will receive a response code with code 201
. In the response you will also find the assigned offerId
to this offer. Save this offerId
as it is the unique key tied to this offer. All subsequent requests to bol require this offerId
.
Get an offer
In order to retrieve your offer data, you can use this endpoint. Provide the offerId
in the path and the bol marketplace will retrieve all your corresponding offer data if the provided offerId
is known and valid to bol. The response includes all the data that you have provided upon creating this offer. See this section for an explanation of all the fields and object when creating an offer. Next to that data you will find the following additional data in the response:
Field | Description |
---|---|
|
The unique identifier of this offer. |
|
The date and time when this offer was last modified, including an offset from UTC. The datetime is based on ISO-8601 standard. |
|
The amount of stock minus handled order items and minus open order items. When this reaches 0, your offer will be marked as "offline". |
|
Indicates if this offer is for sale in the corresponding country. |
|
The bol marketplace identifier of the product. |
offerId
The offerId
is the unique bol identifier that is assigned to this offer. It is not possible to change the offerId
.
lastModifiedDateTime
The lastModifiedDateTime
is the timestamp in which this offer was updated last according to the bol marketplace. Be aware that the bol marketplace will update this timestamp if any change has impacted this offer. For instance, an offer is marked as offline initially, but right after that it becomes online again. It would mean like the offer itself hasn’t changed but this change can cause the lastModifiedDateTime
to be updated.
The datetime is according to the ISO-8601 standard and includes an offset from UTC time.
stock
Within the stock
object you will find the correctedStock
field. The field applies to both an FBB
and FBR
offer. The value of this field will always be calculated, unless the stock.managedByRetailer
flag is set to true
for fulfilment.method
= FBR
offers. As the correctedStock
field is calculated by the bol marketplace, it is not possible to update this field yourself. If you make a change to your stock level (stock.aoumt
), the bol marketplace will recalculate the correctedStock
. This might take some time.
In order to understand how the correctedStock
is calculated, take a look at the examples below.
Table 1: FBR offer stock management where managedByRetailer
= false
Event | stock.amount |
stock.correctedStock |
Explanation |
---|---|---|---|
Retailer updates stock (@10:00:00) |
10 |
10 |
|
Reservation ( |
10 |
9 |
|
Retailer decreases stock (@11:00:00) |
9 |
8 |
|
Customer cancellation ( |
9 |
9 |
|
Reservation ( |
9 |
8 |
|
Retailer decreases stock (@11:30:00) |
2 |
1 |
cancelled order ( |
Shipment ( |
2 |
1 |
shipping an order does not change the |
Retailer decreases stock (@11:50:00) |
1 |
1 |
cancelled order ( |
Table 2: FBR offer stock management where managedByRetailer
= true
Event | stock.amount |
stock.correctedStock |
Explanation |
---|---|---|---|
Retailer updates stock (@10:00:00) |
10 |
10 |
|
Reservation ( |
10 |
9 |
|
Retailer decreases stock (@11:00:00) |
9 |
9 |
open order ( |
Customer cancellation ( |
9 |
9 |
customer cancellation ( |
Reservation ( |
9 |
8 |
|
Retailer decreases stock (@11:30:00) |
2 |
2 |
cancelled order ( |
Shipment ( |
2 |
2 |
shipping an order does not change the corrected stock |
Retailer decreases stock (@11:50:00) |
1 |
1 |
cancelled order ( |
countryAvailabilities
Within the countryAvailabilities
object you will find the forSale
field. The forSale
field will indicate if this offer is for sale in the corresponding country, based on the countryCode
. The forSale
flag is only present for the countries this offer is listed in. It is also not possible to update this field yourself.
Note that changes in the bol marketplace might cause your offer to be reevaluated at certain times. If you want to know when a change has taken place you can use our Subscription API and subscribe to our FOR_SALE
and NOT_FOR_SALE
events.
Get offers
This endpoint allows you to search offer related data from the bol marketplace. To do this efficiently, you can use any of the following query parameters.
Query parameter | Description |
---|---|
|
Search offers based on a set of `offerId’s. A maximum of 100 `offerId’s is supported. |
|
Search offers based on a set of `ean’s. A maximum of 100 `ean’s is supported. |
|
Search offers based on a reference that you defined yourself when creating an offer. |
|
Search for offers that are for sale in the Netherlands, Belgium or both. |
|
Search for offers that have changed since the last modified date time with an offset from UTC. The datetime is according to ISO-8601 standard. |
|
The number of offers per page. |
|
The cursor token to retrieve the next page of this search. |
In the response, you will find the following additional metadata.
Field | Description |
---|---|
|
Metadata that describes the page size and provides the |
Get not for sale reasons
When you create or update an offer on the bol marketplace, this offer will be validated against the platform policies of bol. When this process is done, and the offer is marked as offline (not for sale), you can fetch the details via this endpoint. The offerId
must be provided in the path.
If you want to know when the processing of your newly created (or updated) offer is completed you can use our Subscription API. Subscribe to our |
Field | Description |
---|---|
|
The unique identifier of this offer. |
|
The countries in which this offer is potentially offline. |
|
The reasons why your offer is marked offline. |
offerId
The offerId
is the bol identifier that is uniquely assigned to this offer. You cannot change the offerId
.
countries
With the countries
object, you will find the countryCode
field and the corresponding reasons
for for this country. The countryCode
field refers to the country in which you want to sell this offer (NL
for the Netherlands and BE
for Belgium). You provided this when creating an offer, or it is taken from you Retailer account setting.
Not-for-sale (offline) reasons apply per country. This means that, when you create an offer for both NL
and BE
, your offer can be offline within Belgium (forSale
= false
), but online within the Netherlands (forSale
= true
). In this endpoint, you will only see reasons if there is at least one offer offline in any of the two countries. In this case, you will therefore only find reasons for countryCode
with NL
.
In case your offer is online completely, you will not receive any content in this endpoint. Also it is not possible to update or change the data in this endpoint.
reasons
The reasons
object contains a code
field, and a description
field. The code
field is a unique number assigned to this reason. Based on this code
, you can define a solution that could automatically resolve this reason. The code is explained functionally by the description
field, which can be used to understand why this offer is offline. If all the reasons are resolved, your offer should normally go online.
When it comes to offline reasons, it is good to take note of the following:
-
Not all reasons can be resolved by the retailer itself. This can for instance happen because your offer contains a product that is not allowed to be sold on the bol marketplace. In such a situation, there is no way for you, as a retailer, to resolve this reason.
-
Different resolutions can resolve the same reason. For instance, if an offer runs out of stock, you can either choose to switch to another fulfilment method or increase the stock levels for this offer. Both will likely resolve this offline reason.
-
Reason A is more important than reason B. The bol marketplace stops processing an offer if a specific reason is considered more important than another reason. When this reason is resolved, the bol platform will continue processing as usual. However, if, during that process, a new reason pops-up, you will encounter a new offline (not-for-sale) reason that was previously not visible.
Updating an offer
There can be several reasons to update an offer. The most common use cases to update (parts of) an offer is usually price or stock related. To update an offer, you will need to add the offerId
to the path in this endpoint.
Please read this page carefully before continuing to avoid possible data loss. |
The PATCH implementation can vary per marketplace. Below it is described how a specific payload is interpreted at the bol marketplace. It is good to follow these conventions:
-
Omitting an attribute: not specifying an attribute in the PATCH endpoint means the fields won’t be updated.
-
Sending
null
within your payload is treated as:-
For fields: "empty this field". If a previous value was present, it will be cleared.
-
For (nested) objects: not possible.
-
For arrays: not possible, except for the
countryAvailabilities
field.
-
-
Sending an empty string
""
within your payload is treated as:-
For fields:
""
is considered a value. If a previous value was present, it will be overwritten with this new value. -
For arrays: not possible.
-
Keep in mind that:
-
Arrays are interpreted as a full replace. If you want to add or remove an element to the array, you are required to send all elements in the array, even if they already existed before.
-
A boolean field can never be set to
null
. -
Enumerations can never be set to
null
. -
Required fields can never be set to
null
.
bol either accepts or rejects the whole request. If a part of the payload is correct and a part of the payload is incorrect, the whole request will be rejected. See our Offer API use case guide for specific use cases. |
Update a field
If you want to update a field with a new value, like the reference
field, you can send this new value to the PATCH endpoint. For instance, if the value for the reference
field is currently This is my first reference
and you want to update it to This is my second reference
, you can send the following payload to this PATCH endpoint:
{
"reference": "This is my second reference"
}
If you want to delete the value for the reference
field, you can send the following payload:
{
"reference": null
}
If you want to remain the value of the reference
field you omit this field from your payload. If the field is defined as an enumeration, you cannot set this field to null
or ""
.
Update a boolean
If you want to update a boolean field like the onHoldByRetailer
, you send a new value. For instance, if you want to set the onHoldByRetailer
flag to true
, you send the following payload:
{
"onHoldByRetailer": true
}
If you want to remain the value of the onHoldByRetailer
field you omit this field from your payload. You cannot set this field to null
or ""
.
Update an array
If you want to update an array, like the countryAvailabilities
, you are required to send the whole array. This array will replace the previous array. For instance, you want to sell this offer in both the Netherlands (countryCode
= NL
) and Belgium (countryCode
= BE
). Currently, this offer is only available in Belgium (countryCode
= BE
). To achieve this, you need to send the following payload:
{
"countryAvailabilities": [
{
"countryCode": "NL"
},
{
"countryCode": "BE"
}
]
}
It is not possible to send null
or ""
to bundlePrices
(a price is always required), but for countryAvailabilities
object this is allowed.
Update an object
If you want to update an object, you can send the fields within that object that you want to update. Whether a field is within an object or not, does not affect the way they are processed. If a field (or nested object) is required within the object you want to update, you are required to send it as well.
For instance, you want to update the fulfilment schedule. Within this schedule, the method
field is required. Therefore, you need to send the method
field as well:
{
"fulfilment": {
"method": "FBR",
"schedule": "MY_DELIVERY_PROMISE"
}
}
Updating more than one field at the same time
If you want to update your stock level as well as your selling price, you can provide both objects in one single request. For instance, you want to set the price per piece to 9.99
euro and your amount of stock needs to be adjusted to 46
. The quantity
and unitPrice
fields are mandatory, so they need to be present in the payload.
To achieve this, you can send the following payload to the bol marketplace:
{
"pricing": {
"bundlePrices": [
{
"quantity": 1,
"unitPrice": 9.99
}
]
},
"stock": {
"amount": 46
}
}
Deleting an offer
If you want to delete an offer, you only need the offerId
and this endpoint that allows deletion of an offer. The offerId
can be attached to the path parameter. When the offerId
is known to bol and successfully delete, you will receive a 204
code. From that moment, you cannot update this offer anymore or retrieve it from the bol marketplace.