Channel API: retrieve product content
About this article
This article explains how the GET /v2/products/data endpoint works via the Channel API, what each field in the response means, and how to use the response to keep your product catalogue in sync.
Table of contents
Introduction
When building a channel integration on top of ChannelEngine, your application needs to know which products to list, update, or delist on the marketplace. The GET /v2/products/data endpoint is the primary way to retrieve that information. It returns a structured list of products organised into three buckets:
- Products to create
- Products to update
- Products to remove
This overview enables you to act on each group without having to compare states on your side.
ChannelEngine tracks the status of every product for every connected channel. When a merchant adds a new product, changes a price, or delists a product, ChannelEngine marks it with the appropriate action. When your integration calls GET /v2/products/data, ChannelEngine returns only the products that need attention — not your entire catalogue — making each synchronisation cycle efficient.
/v2/products/data endpoint is designed for incremental (delta) updates. On each call, you receive only the changes since the last successful sync, not a full product dump. This keeps response sizes manageable even for large catalogues.
Aside from the product data, it is also possible to retrieve product offers (price and stock) via the Channel API. For details on retrieving product offers via the Channel API, check out /v2/products/offers.
Overview
Refer to the flowchart below to visualize how product data travels between your channel, ChannelEngine, and the merchant.
Requirements
Before making calls to this endpoint, make sure you have the following in place:
- A valid Channel API key for your ChannelEngine integration
- Your integration registered as a channel on ChannelEngine (not a merchant API key)
- At least one merchant connected to your channel with products in an active status
Available API endpoints
Product data covers all non-offer attributes of a product: titles, descriptions, images, categories, GTINs, and other content fields. Use the product data endpoints to keep your marketplace listings up to date with the latest content changes from merchants.
-
Retrieve product data changes:
GET /v2/products/data
Use this endpoint to retrieve all products that have changed since your last acknowledgement. The response groups products into three sets:Created,Updated, andRemoved. Process each group accordingly on your marketplace before acknowledging. -
Acknowledge product data changes:
POST /v2/products/data
Call this endpoint after successfully processing the product data changes fromGET /v2/products/data. Supply the ChannelReference values of the products that were processed. ChannelEngine then records the timestamp of this acknowledgement and uses it to determine which products to return in subsequent calls. Products in theUpdatedandRemovedsets must be referenced by theChannelReferencevalues supplied in a previousCreatedacknowledgement.
ChannelReference you supply in POST /v2/products/data must be unique per product. ChannelEngine stores this reference and uses it to track which products your channel has acknowledged.
Product reference: ChannelProductNo vs MerchantProductNo
Every order line must reference a product so ChannelEngine can match it to the correct item in the merchant's catalog. You have two options, and the right choice depends on whether your channel performs product acknowledgement.
What is product acknowledgement?
When a channel integrates with ChannelEngine, it can retrieve the merchant's product catalog via GET /v2/products/data and then call POST /v2/products/data to confirm which products it has received and processed. During this acknowledgement step, the channel assigns its own ChannelProductNo to each product. ChannelEngine then stores the mapping between the merchant's reference and the channel reference.
| Your channel situation | Field to use in Lines | KeyIsMerchantProductNo |
Your channel does acknowledge products (you call POST /v2/products/data) |
ChannelProductNo |
false |
| Your channel does not acknowledge products — you receive orders directly without syncing the catalog | MerchantProductNo |
true |
Endpoint: retrieve product content
- Retrieve product data changes:
GET /v2/products/data
Authenticate by passing your Channel API key in the request header:
X-CE-KEY: your-channel-api-key
Query parameters
All parameters are optional. When none are provided, the endpoint returns all pending products across all buckets without HTML stripping, starting from page 1.
| Parameter | Type | Default | Description |
maxCount |
integer | — | Limits the number of products returned per bucket (ToBeCreated, ToBeUpdated, ToBeRemoved). When omitted, no per-bucket cap is applied. |
stripHtml |
boolean | true | When true (the default), HTML tags are stripped from all text fields. Set to false if your integration needs to preserve HTML formatting. |
page |
integer | 1 | The page number to return. Use in combination with pageSize to paginate through large catalogues. |
pageSize |
integer | — | The number of products to return per page. Set this to a manageable number (e.g. 250–500) when processing large catalogues. |
pageSize and page together for reliable paginated sync. Set pageSize=250&page=1 on the first call, then increment page until no products are returned.
stripHtml defaults to true. If your marketplace renders HTML in product descriptions, explicitly pass stripHtml=false — otherwise formatting will be lost.
Response structure
A successful response returns an HTTP 200 with a JSON body. The top-level structure has a Content object containing the three action buckets, plus envelope fields for counts, status, and diagnostics.
{
"Content": {
"ToBeCreated": [ /* array of product objects */ ],
"ToBeUpdated": [ /* array of product objects */ ],
"ToBeRemoved": [ /* array of ChannelProductNo strings */ ]
},
"ToBeCreatedTotalCount": 42,
"ToBeUpdatedTotalCount": 15,
"ToBeDeletedTotalCount": 3,
"Success": true,
"StatusCode": 200
}
The three action buckets
| Bucket | What it contains | What your integration should do |
ToBeCreated |
Products that do not yet exist on your channel and need to be listed for the first time. | Create a new listing on the marketplace using the provided product data. |
ToBeUpdated |
Products already listed on your channel where one or more fields have changed. | Send an update to the marketplace for the affected product. |
ToBeRemoved |
A list of ChannelProductNo strings identifying products that should be delisted. | Remove or deactivate the corresponding listing on the marketplace. |
ToBeRemoved contains only the ChannelProductNo string — not a full product object. Store the mapping between your internal product IDs and ChannelProductNo values during creation so you can look them up during removal.
MappedFields vs. default attributes
The product object contains two distinct sources of attribute data. Which one your integration should use depends entirely on how your channel is set up in ChannelEngine.
| Your integration type | Read from | Why |
| Built on the Channel Management API — your channel defines its own attribute schema | MappedFields |
Sellers map their product data to your registered attributes, and those mapped values are returned here — ready to send to your marketplace. |
| Built directly on the ChannelEngine data structure — your channel consumes CE's standard product format | Default attributes (Name, Description, Brand, etc.) |
MappedFields will be empty in this scenario. Use the standard CE fields directly. |
How MappedFields works
When your channel uses the Channel Management API, you register the attributes your marketplace requires — each with a unique system name. Sellers map their own product data to each attribute. When you call GET /v2/products/data, those mapped values come back in MappedFields keyed by your system names.
{
"MappedFields": {
"fabric_type": "100% organic cotton",
"product_category_id": "apparel_tops_tshirts",
"bullet_point_1": "Machine washable at 30°C"
},
"Name": "Basic Tee",
"Description": "A comfortable everyday t-shirt."
}
In this example, use fabric_type, product_category_id, and bullet_point_1 for the marketplace listing. Name and Description are the seller's raw source data and should be ignored for this integration type.
MappedFields keys may be missing or empty. Flag those products for follow-up rather than silently falling back to default attributes — the default values have not been prepared for your channel's requirements.
Product object fields
Both ToBeCreated and ToBeUpdated contain the same product object shape.
| Field | Type | Description |
Id |
integer | Internal ChannelEngine product ID. Use this as a stable reference key across sync cycles. |
ChannelProductNo |
string | Your channel's own product identifier. This is the value used in ToBeRemoved. |
ParentChannelProductNo |
string | The ChannelProductNo of the parent product, if this is a child (variant) product. |
GrandparentChannelProductNo |
string | The ChannelProductNo of the grandparent product, used in three-level product hierarchies. |
MappedFields |
object | Key-value pairs where each key is the system name of a channel attribute you defined, and each value is the seller's mapped data for that attribute. |
ProductType |
enum | Structural role: SINGLE PARENT CHILD |
Name |
string | Default attribute. Product title from the seller's source system. |
Description |
string | Default attribute. Product description. May contain HTML. |
Brand |
string | Default attribute. The product brand name. |
Size |
string | Default attribute. Size value (e.g. "XL", "42"). |
Color |
string | Default attribute. Colour value from the seller's source system. |
Segment |
string | Default attribute. Product segment or category as defined by the merchant. |
Ean |
string | EAN/GTIN barcode. Used for product matching on many marketplaces. |
ManufacturerProductNumber |
string | MPN — the manufacturer's own product reference number. |
MerchantProductNo |
string | The merchant's own SKU or product number. |
Price |
number | The selling price (inclusive of VAT where applicable). |
MinPrice |
number | Minimum allowed price, if the merchant has set a floor price rule. |
MaxPrice |
number | Maximum allowed price, if the merchant has set a ceiling price rule. |
MSRP |
number | Manufacturer's Suggested Retail Price. Useful for displaying a "was" price. |
PurchasePrice |
number | The cost price of the product to the merchant. Not displayed to buyers. |
VatRateType |
enum | STANDARD REDUCED SUPER_REDUCED ZERO |
ShippingCost |
number | Shipping cost associated with this product. |
ShippingTime |
string | Human-readable shipping lead time (e.g. "2-3 business days"). |
Url |
string | Direct URL to the product page on the merchant's webshop. |
ImageUrl |
string | URL of the main product image. |
ExtraImageUrl1 - ExtraImageUrl9 |
string | URLs for up to nine additional product images, in display order. |
IsFrozen |
boolean | When true, the merchant has frozen this product. See Frozen products below. |
CategoryTrail |
string | The full category path (e.g. "Electronics > Audio > Headphones"). |
ExtraData
Each product can carry a list of ExtraData entries — additional attributes that don't fit into the standard fields above, such as marketplace-specific metadata or localised content.
| Field | Type | Description |
Key |
string | The attribute name (e.g. material, warranty_years). |
Value |
string | The attribute value as a string. |
Type |
enum | Data type hint: TEXT NUMERIC BOOLEAN DATE |
FieldType |
enum | UI field type: TEXT SELECT MULTISELECT CHECKBOX NUMERIC DATE |
IsPublic |
boolean | Whether this attribute is intended to be shown to buyers on the marketplace. |
IsReadonly |
boolean | When true, your integration should treat this attribute as read-only. |
LanguageIsoCode |
string | ISO 639-1 language code (e.g. en, nl, de). Empty when language-neutral. |
Response envelope fields
| Field | Type | Description |
ToBeCreatedTotalCount |
integer | Total products pending creation — may be higher than the number returned if maxCount is set. |
ToBeUpdatedTotalCount |
integer | Total products pending update. |
ToBeDeletedTotalCount |
integer | Total products pending removal. |
StatusCode |
integer | HTTP-equivalent status code within the response body (normally 200). |
RequestId |
string | Unique identifier for this API call. Include in any support request for faster diagnosis. |
LogId |
string | Internal ChannelEngine log reference. Also useful when contacting support. |
Success |
boolean | true when the request completed without errors. |
Message |
string | Human-readable message, usually empty on success. |
ExceptionType |
string | Machine-readable error classification when Success is false. |
ValidationErrors |
object | Field-level validation errors, keyed by field name. Only populated when the request was malformed. |
Pagination and sync strategy
The endpoint supports page-based pagination via the page and pageSize parameters. Use the *TotalCount fields in the response to determine whether there are more products to process.
-
Call the endpoint with a
pageSizethat fits your processing capacity andpage=1.
You receive the first batch of products across the three buckets. - Process the full batch - create listings from
ToBeCreated, update fromToBeUpdated, and delist fromToBeRemoved. -
Acknowledge the batch by calling
POST /v2/products/datawith the IDs you have successfully processed.- Acknowledged products do not appear in subsequent responses.
- Check the
TotalCountvalues. If the total count is higher thanpage × pageSize, incrementpageby 1 and repeat from Step 1. Continue until the response buckets are empty.
Always acknowledge products after processing them. If you do not call the acknowledgement endpoint, those products will appear in every subsequent response, causing duplicate processing.
Endpoint: acknowledging products
- Acknowledge product data changes:
POST /v2/products/data
After retrieving and processing a batch of products, your integration must tell ChannelEngine which products have been successfully handled. Until a product is acknowledged, it will continue to appear in every subsequent GET /v2/products/data response.
X-CE-KEY: your-channel-api-key Content-Type: application/json
Request body
{
"Created": [
{
"Id": 1042,
"ChannelProductNo": "MYSHOP-SKU-001"
}
],
"Updated": [
"MYSHOP-SKU-002",
"MYSHOP-SKU-003"
],
"Removed": [
"MYSHOP-SKU-099"
]
}
Request body fields
| Field | Type | Corresponds to | Description |
Created |
array of objects | ToBeCreated |
Products successfully listed for the first time. Each entry requires Id (ChannelEngine internal ID) and ChannelProductNo (your channel's own identifier for this listing). |
Updated |
array of strings | ToBeUpdated |
The ChannelProductNo values of products successfully updated on the marketplace. |
Removed |
array of strings | ToBeRemoved |
The ChannelProductNo values of products successfully delisted from the marketplace. |
ChannelProductNo you supply in the Created acknowledgement is stored by ChannelEngine and used from that point on as the stable identifier for this product on your channel. Choose a value that is unique and meaningful within your system.
Partial acknowledgement
You do not have to acknowledge all products in a single call. If your integration processes products in smaller batches, send a separate acknowledgement for each batch as it completes. ChannelEngine will clear only the acknowledged products and keep the rest pending.
Frozen products
A product with "IsFrozen": true has been deliberately locked by the merchant. Frozen products should still be listed on your channel — they are included in ToBeCreated or ToBeUpdated just like any other product. However, your integration should not send price or stock changes for frozen products until they are unfrozen.
Treat IsFrozen as a signal to list (or keep listed) the product at its current values without overwriting them with downstream updates.
First-time onboarding
When a seller connects to your channel for the first time, your integration must perform three sequential API calls — one for each level of the product hierarchy — each followed by an acknowledgement before the next call is made. This sequencing ensures parent–child relationships are established in the correct order.
-
Grandparent products
- The first call returns only grandparent products — the top level of the product hierarchy. These are structural grouping containers and are not directly sold. They provide the framework that parent and child products attach to.
- After retrieving and processing all grandparent products (paginating as needed), acknowledge them via
POST /v2/products/databefore making call 2.
-
Parent products
- The second call returns parent products — variant group containers that sit beneath the grandparent level. Each parent references its grandparent via
GrandparentChannelProductNo. - Acknowledge all parent products before making call 3.
- The second call returns parent products — variant group containers that sit beneath the grandparent level. Each parent references its grandparent via
-
Child & standalone products
- The third call returns the sellable items: child products (variants) and standalone (single) products. Child products reference their parent via
ParentChannelProductNo. These are the products that get listed as purchasable items on the marketplace. - Acknowledge them to complete the initial onboarding sync.
- The third call returns the sellable items: child products (variants) and standalone (single) products. Child products reference their parent via
Onboarding flow summary
-
Fetch grandparent products - call
GET /v2/products/dataand paginate until all grandparents are retrieved.- Response contains only
ProductType: GRANDPARENTproducts inToBeCreated.
- Response contains only
-
Acknowledge grandparents— call POST /v2/products/data with all grandparent IDs.
- ChannelEngine marks grandparents as processed and unlocks parent products.
-
Fetch parent products - call
GET /v2/products/dataagain.- Response contains
ProductType: PARENTproducts referencing previously acknowledged grandparents.
- Response contains
-
Acknowledge parents - call
POST /v2/products/datawith all parent IDs.- ChannelEngine marks parents as processed and unlocks child and standalone products.
-
Fetch child & standalone products - call
GET /v2/products/dataonce more.- Response contains
ProductType: CHILDandProductType: SINGLEproducts ready to list.
- Response contains
-
Acknowledge children & standalones - call
POST /v2/products/datawith all remaining IDs.- Initial onboarding complete. Future calls return only incremental changes.
Common issues
| Symptom | Likely cause | Fix |
| Listings contain incorrect or generic attribute values | Integration is reading default attributes instead of MappedFields. |
Always use MappedFields as the primary source for marketplace listings. |
Some MappedFields keys are missing or empty |
The seller has not completed their attribute mapping in ChannelEngine. | Flag affected products for review rather than silently falling back to default attributes. |
| Child products appear with missing or broken parent references during onboarding | Parent or grandparent products were not acknowledged before fetching the next level. | Follow the three-call onboarding sequence strictly. Do not skip acknowledgement between calls. |
Success: false with no ValidationErrors |
Authentication failure or incorrect API key. | Verify the Channel API key is correct and issued for this channel integration. |
| Same products reappear on every GET call | Products are not being acknowledged after processing. | Call POST /v2/products/data after each successful batch. |
ToBeCreated and ToBeUpdated are both empty but ToBeDeletedTotalCount is non-zero |
Normal behaviour when only removals are pending. | Process ToBeRemoved normally and acknowledge. No action needed for the empty buckets. |
Unexpected null values for optional fields |
The merchant has not configured those fields. | Handle null gracefully. Do not treat missing optional fields as errors. |
| Response payload is very large and slow | pageSize not set, so all pending products are returned in one response. |
Set pageSize to a manageable number (e.g. 250) and paginate using the page parameter. |
Next steps
- Review the Acknowledging products section to make sure your integration clears processed products from the queue correctly
- Use the RequestId and LogId values from any GET response when contacting ChannelEngine Support about a specific API call
- Review the Channel API authentication documentation for guidance on API key management and rotation
Comments
0 comments
Article is closed for comments.