Overview
The Product Offers syndication functionality allows for the smooth exchange of product offer data (such as price, stock, conditions, and promotions) between the Activation platform and various retailers and marketplaces, starting with Amazon Seller Central and MIRAKL-powered marketplaces. This documentation explains how to set up and use this feature effectively.
Currently, the export of product offers is technical and only available through the API.
The product offers API lets you create and update one or multiple offers for various products. It also supports partial updates, such as changing only prices, currencies, or stock levels.
It is not possible to delete product offers via the API. You can, however, set the quantity to “0” to ensure the product cannot be available for purchase on the channel side.
Data Flow
Here is how the end-to-end workflow works to send product offers:
- You need to call the offer API (made available via a simple endpoint URL)
- The data gets pushed from your source via the API
- The data is then hosted on the Activation side, translating the logic to what the marketplaces expect.
- A scheduler automatically sends the pushed product offer data via the API to the marketplaces every 15 minutes.
- The product offer data is stored in Activation and attached to the corresponding product (s).
Access Token
- To call the API successfully, you must access a token. Every new customer is assigned a unique access token when connecting a PIM to the Activation App.
- Accessing the API requires the use of this access token.
- To create a new access token to call the API you can generate it from the Activation app via this link
- Go to the Activation settings
- Select the “Activation settings” tab
- Click the generate token button with arrows
Offer description
To ensure you send the correct information when creating or updating product offers, review the sections below that detail the expected data in the API.
An offer is always associated with a product, and you can attach multiple offers to the same product.
An offer includes several sections (price, inventory, condition, promotion). Each offer is linked to one Activation channel and cannot be part of multiple Activation channels at the same time. You can update each section independently for one or more products.
Identifier
This data is needed to uniquely identify an offer and the product it is attached to.
- You need to be able to identify how to attach a product to an offer, for that a product identifier is required such as an SKU or an EAN
- You need to be able to identify an offer uniquely, for that, you can use a unique identifier such as an Offer SKU.
- Each marketplace can have a specific way of identifying its offers
- Amazon with the ASIN
- MIRAKL-powered marketplaces with the Product Offer SKU
- Each marketplace can have a specific way of identifying its offers
Price Section
This data relates to an offer price
- Contains pricing information
- Amount
- Currency
- Offer Times (start/end)
- Additional time-related metrics
- Potential discounts and promotions
Stock Section
This data relates to an offer inventory
- Provides details about the product's stock:
- Condition (new/used/refurbished)
- Quantity
- Days to ship (handling time)
Promotions
Each offer can have multiple promotions, each with a specific
- Start/end time
- Price
- Condition
Sending Multiple Offers
- You can create and update multiple offers per product, each with its specifications.
- For example, Offer A could be for a "new" product, while Offer B could be for a "used/refurbished" product.
Current limitations
To date, it is not possible from the Activation app to:
- see the product offer export job from your activation channel reports tab
MIRAKL marketplaces specific use case
Only one offer discount can be sent per offer. When you send multiple discounts, only the first one will be used. If you want to send multiple discounts for the same product, you will have to create as many offers as discounts for that product. It is not possible to send product condition (ie “used”) to MIRAKL.
Working with the API
You can review the API documentation in this API guide to understand how to successfully call it and push product offers to the supported marketplaces.
See below the different API body sections:
Verb
POST
for creation
PUT
for update
Required for the very first API call, creating the offer
From the second call onward, PUT could be used to update price and/or stock data
Headers
access_token
- Required
- Equal to 'xxx', 'xxx' being the App authentication token
- Provided by the Activation tech team
- Works with the PIM connection
Path parameters
flow_id
- Required
- string
- Identifier for the targeted flow (channel in Activation)
Query parameters
syndication_channel_product_identifier
- required
- string
- Corresponds to the SKU in the PIM
offers:offer_sku
- required
- string
- Corresponds to the Offer identifier for a partner (channel)
- For Amazon, it needs to be
syndication_channel_product_identifier
- For MIRAKL, it corresponds to an identifier on the MIRAKL side. It might need to be created by MIRAKL (to be checked)
- For Amazon, it needs to be
offers:offer_sku:prices:base
- required for the first call (POST)
- Optional (PUT call)
- object
offers:offer_sku:prices:base:amount
- required
- number
- product price
offers:offer_sku:prices:base:currency
- required
- number
- product currency
offers:offer_sku:prices:base:startDate
- Optional
- string
- format : yyyy-mm-dd
- offer start date
offers:offer_sku:prices:base:endDate
- Optional
- String
- format: yyyy-mm-dd
- offer end date
offers:offer_sku:prices:discounted
- required
- array
- could be empty
- discount flag
offers:offer_sku:prices:discounted:amount
- required
- number
- discounted product price
offers:offer_sku:prices:discounted:currency
- required
- number
- discounted product currency
offers:offer_sku:prices:discounted:startDate
- Optional
- string
- format : yyyy-mm-dd
- discounted offer start date
offers:offer_sku:prices:discounted:endDate
- Optional
- String
- format: yyyy-mm-dd
- discounted offer end date
offers:offer_sku:stock
- required if the price object is missing, otherwise optional
- object
offers:offer_sku:stock:condition
- required
- string
- Corresponds to the state of the product
- Required format
- new
offers:offer_sku:stock:quantity
- required
- number
- Corresponds to the product stock count. 0 est accepté
offers:offer_sku:stock:daysToShip
- Optional
- number
- Handling time is the number of days between when you receive payment for an item and when your package is scanned by your shipping carrier (eBay definition)
Examples
These are the different calls that can be made when calling the product offers API:
Complete informations (POST & PUT)
{
"syndicationChannelProductIdentifier": {
"offers": {
"offerSku": {
"prices": {
"base": {
"amount": 17.77,
"currency": "USD",
"startDate": "2024-01-01",
"endDate": "2024-12-31"
},
"discounted": [
{
"amount": 12.50,
"currency": "USD",
"startDate": "2024-03-01",
"endDate": "2024-04-15"
},
{
"amount": 13.57,
"currency": "USD",
"startDate": "2024-04-16",
"endDate": "2024-05-01"
},
]
},
"stock": {
"condition": "new",
"quantity": 0,
"daysToShip": 5
}
}
}
}
}
Without discounted (POST & PUT)
{
"syndicationChannelProductIdentifier": {
"offers": {
"offerSku": {
"prices": {
"base": {
"amount": 17.77,
"currency": "USD",
"startDate": "2024-03-01",
"endDate": "2024-04-15"
},
"discounted": []
},
"stock": {
"condition": "new",
"quantity": 0,
"daysToShip": 5
}
}
}
}
}
Update only prices (PUT only)
{
"syndicationChannelProductIdentifier": {
"offers": {
"offerSku": {
"prices": {
"base": {
"amount": 17.77,
"currency": "USD",
"startDate": "2024-03-01",
"endDate": "2024-04-15"
},
"discounted": []
}
}
}
}
}
Update only stock (PUT only)
{
"syndicationChannelProductIdentifier": {
"offers": {
"offerSku": {
"stock": {
"condition": "new",
"quantity": 0,
"daysToShip": 5
}
}
}
}
}
Errors
These are the different errors that can happen when calling the product offers API:
- Wrong
flow_id
⇒403 - Forbidden
- Wrong
access_token
⇒403 - Forbidden
- Product not found |
200 - OK
{
"*syndication_channel_product_identifier*": [
{
"type": "product_not_found",
"severity": "warning",
"message": "Could not find product *syndication_channel_product_identifier*"
}
]
}
- Missing property |
400 - Bad Request
{
"type": "update_sellable_product.bad_request",
"message": "The request is not valid",
"payload": {
"errors": [
{
"instancePath": "/body/*syndication_channel_product_identifier*",
"schemaPath": "#/properties/body/additionalProperties/required",
"keyword": "required",
"params": {
"missingProperty": "offers"
},
"message": "must have required property 'offers'"
}
]
}
}
- Try to create an existing product |
400 - Bad Request
{
"type": "update_sellable_product.bad_request",
"message": "The request is not valid",
"payload": {
"errors": [
{
"instancePath": "/method",
"schemaPath": "#/properties/method/const",
"keyword": "const",
"params": {
"allowedValue": "PUT"
},
"message": "must be equal to constant"
}
]
}
}
- Try to update an offer that has not been created |
400 - Bad Request
{
"*syndication_channel_product_identifier*": [
{
"type": "invalid_offer",
"severity": "error",
"message": "At least one of the product new offers has missing prices or stock"
}
]
}
- Wrong allowed value (example
stock:condition
) |400 - Bad Request
{
"type": "update_sellable_product.bad_request",
"message": "The request is not valid",
"payload": {
"errors": [
{
"instancePath": "/body/*syndication_channel_product_identifier*/offers/offer_sku/stock/condition",
"schemaPath": "#/properties/body/additionalProperties/properties/offers/additionalProperties/properties/stock/properties/condition/enum",
"keyword": "enum",
"params": {
"allowedValues": [
"new"
]
},
"message": "must be equal to one of the allowed values"
}
]
}
}