Sending Product Offers to Marketplaces

Summary

The Akeneo Activation Offer API lets you push product offer data — price, stock, condition, and promotions — from your own system directly into Activation. Once received, Activation automatically forwards the offer data to connected marketplaces such as Amazon Seller Central, MIRAKL-powered marketplaces, Google Shopping, eBay, and Octopia.

Offer data is separate from product catalog data. Product catalog data (titles, descriptions, attributes) is sent to marketplaces through Activation channels. Offer data (pricing, stock, conditions) is pushed through the Offer API described in this article.

It is not possible to delete product offers via the Offer API. To make a product unavailable for purchase on the marketplace, set its stock quantity to 0.

Before you start

  • You need a PIM connected to Akeneo Activation and at least one Activation channel set up.
  • All Offer API calls use the PUT method — for both creating and updating offers.
  • API calls require an access token. See Generate an access token below.

How offer data flows through Activation

The Akeneo Activation Offer API processes offer data as follows:

  1. You call the Offer API endpoint with your offer data (prices, stock, promotions).
  2. Activation receives and stores the data, linking each offer to the corresponding product.
  3. When automated offer export is enabled on the Activation channel, Activation sends the stored offer data to the marketplace every 15 minutes.

To enable or disable automated export, or to trigger a manual export, see Managing your product offers in Akeneo Activation.

Generate an access token

Every API call to the Akeneo Activation Offer API requires an access token. Each PIM connection has a unique access token.

To generate or regenerate your access token in Akeneo Activation:

  1. In Activation, go to Settings.
  2. Select the Activation settings tab.
  3. In the API token section, click the regenerate token button (the circular arrows icon).

Activation settings page showing the API token section with the regenerate token button

The screenshot above shows the Activation settings page, Activation settings tab, with the API access token field and the regenerate token button.

Offer structure

In Akeneo Activation, an offer is always attached to a product. A product can have multiple offers, and each offer is associated with one Activation channel.

Each offer contains up to four data sections:

  • Identifier — how the product and offer are uniquely identified
  • Price — base price, currency, validity dates, and optional discounts
  • Stock — quantity, condition, handling time, and restocking details
  • Marketplace-specific details — additional fields required by specific marketplaces (Octopia, eBay)

You can update each section independently in a single PUT call.

Identifier

To attach an offer to a product in Akeneo Activation, you need two identifiers:

  • Product identifier — the SKU or EAN that identifies the product in your catalog. This corresponds to the SKU in the PIM.
  • Offer SKU — a unique identifier for the offer within a channel. Each marketplace uses a different identifier:
  • Amazon — use the product identifier (ASIN)
  • MIRAKL-powered marketplaces — use the marketplace-assigned Product Offer SKU

Price section

The price section contains:

  • Amount — required; the product price as a number
  • Currency — required; the currency code as a string (e.g., "USD")
  • Start date — optional; format yyyy-mm-dd
  • End date — optional; format yyyy-mm-dd
  • Discounts (discounted) — an array of discounted price objects; can be empty. Each discount contains amount, currency, start date, and end date.

Stock section

The stock section contains:

  • Condition — required; currently only "new" is accepted via the API
  • Quantity — required; the number of units in stock. Accepts 0.
  • Days to ship (daysToShip) — optional; the handling time in days (time between receiving payment and carrier pickup)
  • Next refill date (nextRefillDate) — optional; format yyyy-mm-dd
  • Is infinite (isInfinite) — optional; set to true for unlimited stock. Default: false

Promotions

Each offer can include multiple promotions in the discounted array. Each promotion has a start date, end date, price, and currency.

MIRAKL-specific limitation

Only one discount per offer is accepted by MIRAKL-powered marketplaces. If you send multiple discounts, only the first one is used. To send multiple discounts for the same product on MIRAKL, create one offer per discount. Sending a product condition other than "new" to MIRAKL is not supported.

Marketplace-specific details

Some marketplaces require additional offer fields beyond the standard price and stock sections. These are passed in the marketplaceOfferDetails object. A single offer can contain at most one marketplace-specific block.

Octopia channels:

  • originPrice — original price (number)
  • taxes — array of tax objects, each with code (e.g., "VAT") and value
  • condition — product condition string (e.g., "New")
  • preparationTime — preparation time in days (number)
  • deliveryModes — array of delivery mode objects with code, cost, and additionalCost

eBay channels:

  • originalRetailPrice — original retail price (number)
  • minimumAdvertisedPrice — minimum advertised price (number)
  • originallySoldForRetailPriceOn — context string (e.g., "ON_EBAY")

Sending multiple offers per product

A product can have multiple offers, each with its own specifications. For example:

  • Offer A for a "new" product
  • Offer B for a different condition or price tier
Current limitations

The offer export job does not appear in the Activation channel reports tab.

API reference

The Akeneo Activation Offer API is documented at api.retail.app.akeneo.cloud.

Endpoint

PUT /v1/channel-connections/{channel_connection_id}/offers

Use PUT for both creating and updating offers. Partial updates are supported — you can update only prices or only stock on an existing offer.

Required headers

pim_connection_id

  • Required
  • string
  • Your PIM connection identifier. Found in the Activation app URL: https://retail.app.akeneo.cloud/{pim_connection_id}/flow

access_token

  • Required
  • string
  • Your API access token, available from Settings > Activation settings in the Activation app. See Generate an access token above.

Path parameter

channel_connection_id

  • Required
  • string
  • The Activation channel connection identifier. Found in the Activation app URL when viewing your channel: https://retail.app.akeneo.cloud/{pim_connection_id}/flow/{channel_connection_id}/dashboard

Request body fields

The request body is a JSON object. Top-level keys are product identifiers. Each product object contains an offers object whose keys are offer SKUs.

{syndicationChannelProductIdentifier}

  • Required
  • string (used as a key)
  • The product SKU from the PIM

offers.{offer_sku}

  • Required
  • string (used as a key)
  • Unique offer identifier for the channel

offers.{offer_sku}.prices.base

  • Required for new offer creation; optional for partial updates
  • object

offers.{offer_sku}.prices.base.amount

  • Required
  • number
  • Base product price

offers.{offer_sku}.prices.base.currency

  • Required
  • string
  • Currency code (e.g., "USD")

offers.{offer_sku}.prices.base.startDate

  • Optional
  • string
  • Format: yyyy-mm-dd

offers.{offer_sku}.prices.base.endDate

  • Optional
  • string
  • Format: yyyy-mm-dd

offers.{offer_sku}.prices.discounted

  • Required (can be an empty array [])
  • array
  • List of discounted price objects

offers.{offer_sku}.prices.discounted[].amount

  • Required when discount is present
  • number
  • Discounted price

offers.{offer_sku}.prices.discounted[].currency

  • Required when discount is present
  • string
  • Currency code (e.g., "USD")

offers.{offer_sku}.prices.discounted[].startDate

  • Optional
  • string
  • Format: yyyy-mm-dd

offers.{offer_sku}.prices.discounted[].endDate

  • Optional
  • string
  • Format: yyyy-mm-dd

offers.{offer_sku}.stock

  • Required if prices is absent; otherwise optional
  • object

offers.{offer_sku}.stock.condition

  • Required
  • string
  • Product condition. Currently only "new" is accepted via the API.

offers.{offer_sku}.stock.quantity

  • Required
  • number
  • Stock count. 0 is accepted.

offers.{offer_sku}.stock.daysToShip

  • Optional
  • number
  • Handling time in days

offers.{offer_sku}.stock.nextRefillDate

  • Optional
  • string
  • Format: yyyy-mm-dd

offers.{offer_sku}.stock.isInfinite

  • Optional
  • boolean
  • Set to true for unlimited stock. Default: false

offers.{offer_sku}.marketplaceOfferDetails

Examples

Complete offer (create or update)

{
    "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 discounts

{
    "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 prices only

{
    "syndicationChannelProductIdentifier": {
        "offers": {
            "offerSku": {
                "prices": {
                    "base": {
                        "amount": 17.77,
                        "currency": "USD",
                        "startDate": "2024-03-01",
                        "endDate": "2024-04-15"
                    },
                    "discounted": []
                }
            }
        }
    }
}

Update stock only

{
    "syndicationChannelProductIdentifier": {
        "offers": {
            "offerSku": {
                "stock": {
                    "condition": "new",
                    "quantity": 0,
                    "daysToShip": 5
                }
            }
        }
    }
}

Errors

403 - Forbidden — wrong channel_connection_id or wrong access_token

200 - OK with warning — product not found

{
    "*syndication_channel_product_identifier*": [
        {
            "type": "product_not_found",
            "severity": "warning",
            "message": "Could not find product *syndication_channel_product_identifier*"
        }
    ]
}

400 - Bad Request — missing required property

{
    "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'"
            }
        ]
    }
}

400 - Bad Request — wrong HTTP method (this endpoint only accepts PUT)

{
    "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"
            }
        ]
    }
}

400 - Bad Request — trying to update an offer that has not been created yet

{
    "*syndication_channel_product_identifier*": [
        {
            "type": "invalid_offer",
            "severity": "error",
            "message": "At least one of the product new offers has missing prices or stock"
        }
    ]
}

400 - Bad Request — invalid stock.condition value

{
    "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"
            }
        ]
    }
}

Related articles