Channel API: getting started
About this article
This article explains how to build a reliable Channel API integration with ChannelEngine — covering authentication, the response envelope, product data and offers, product identifiers, posting orders, post-order flows, rate limits, and debugging. It is intended for channel developers starting a new integration or reviewing an existing one.
Table of contents
ChannelProductNo vs MerchantProductNo
Integration readiness checklist
Introduction
The Channel API is the integration layer between your marketplace channel and ChannelEngine. It allows your channel to receive merchant product data, submit orders on behalf of buyers, and exchange post-order information such as shipments, cancelations, and returns.
Building a reliable integration takes more than reading individual endpoint references. This guide captures the patterns that work, the mistakes that cause subtle bugs, and the shortcuts that save debugging time. Read it before you start, and keep it on hand when something unexpected comes up.
Requirements
- A Channel API key issued for your channel. This is a separate key type from the Merchant API key — they are not interchangeable.
- Access to the demo environment at
demo.channelengine.netfor development and testing. - Familiarity with REST APIs and JSON response handling.
Available API endpoints
The following endpoints are covered in this article. Each is described in detail in its respective section below.
-
Retrieve product data changes:
GET /v2/products/data
Retrieve products that have changed since your last acknowledgement, grouped intoCreated,Updated, andRemovedsets. -
Acknowledge product data changes:
POST /v2/products/data
Confirm that your channel has processed a batch of product data changes. -
Retrieve offer changes:
GET /v2/products/offers
Retrieve price and stock changes since your last acknowledgement. -
Acknowledge offer changes:
POST /v2/products/offers
Confirm that your channel has processed a batch of offer changes. -
Submit an order:
POST /v2/orders
Post a buyer order to ChannelEngine for routing to the merchant. -
Retrieve shipments:
GET /v2/shipments
Poll for fulfilment updates from merchants, including tracking information. -
Submit a channel-initiated cancelation:
POST /v2/cancellations/channel
Cancel one or more order lines on behalf of the buyer or the channel. -
Submit a bulk cancelation:
POST /v2/cancellations/channel/bulk
Cancel multiple orders in a single request. -
Submit a return:
POST /v2/returns/channel
Notify ChannelEngine that a buyer has returned one or more items. -
Retrieve returns:
GET /v2/returns/channel
Poll for return records created since a given timestamp.
Authentication
All Channel API requests must include your Channel API key. Pass it in the X-CE-KEY request header:
X-CE-KEY: your-channel-api-key
401 Unauthorized or Success: false with no further context. Confirm which key type you are using whenever you set up a new environment.
Both the X-CE-KEY header and an apikey query parameter are accepted, but always use the header in production. Query parameters appear in server logs and browser history; the header keeps your key out of those records.
If you receive 403 Forbidden after rotating a key, check every environment — staging, production, and CI — for the old value. A 403 means the key is structurally valid but does not have access to this channel, which is almost always a wrong-key issue following a rotation.
Response envelope
Every Channel API response wraps its content in a standard envelope. Ignoring envelope fields is the most common source of silent failures in channel integrations.
200 while Success: false. This happens when a request is technically valid but a business-logic error occurs — for example, an inactive channel or a malformed field value. Always check the Success field, not just the HTTP status code.
The key envelope fields are described in the table below.
| Field | Type | Description |
Success |
Boolean | Indicates whether the operation succeeded. Always check this field explicitly. |
Message |
String | Human-readable description of the error when Success is false. |
ValidationErrors |
Object | Map of field-level validation failures keyed by field name. Log this in full when diagnosing errors. |
RequestId |
String | Unique identifier for the request. Provide this to ChannelEngine Support when reporting an issue. |
LogId |
String | Log identifier used by the ChannelEngine Support team to trace the exact request in their system. |
Log both RequestId and LogId on every API call in production. When you report an issue, providing both values allows the support team to locate your exact request without requiring you to reproduce it.
Product data and offers
ChannelEngine delivers product content and offer data (price and stock) to your channel through two separate endpoint pairs. Each pair follows a retrieve-then-acknowledge pattern: your channel GETs the pending changes, processes them, and then POSTs an acknowledgement to confirm the records have been handled.
Acknowledgement
Acknowledgement is how ChannelEngine tracks what your channel has already processed. After retrieving and processing a batch of product data changes with GET /v2/products/data, confirm the batch by calling POST /v2/products/data. The same pattern applies to offers: call POST /v2/products/offers after each GET /v2/products/offers batch.
For large catalogues, acknowledge each page immediately after processing it rather than waiting until the entire catalogue has been fetched. This keeps the queue clear as you go. If your integration crashes mid-batch, only the unacknowledged pages are re-queued.
MappedFields
Product data responses contain both MappedFields and default attributes such as Name and Color. Always use MappedFields as the primary source for marketplace listings. Default attributes are raw data from the merchant's source system and are not prepared for your channel's requirements.
MappedFields, it usually means the merchant has not completed their attribute mapping — not that the value exists in a default field. Do not silently fall back to default attributes. Surface the gap in your onboarding flow so the merchant can resolve it. Falling back silently pushes incorrect data to the marketplace without anyone noticing.
Any optional field can be null when the merchant has not provided a value. Build null-safe mapping logic from the start. Crashes caused by unexpected nulls account for a significant share of integration instability.
First-time onboarding
Parent-child product hierarchies require a specific sequence during the first full product sync. Skipping any step results in broken or missing parent references on child products.
Follow this sequence strictly:
- Fetch and acknowledge grandparent products.
- Fetch and acknowledge parent products.
- Fetch and acknowledge child products.
ChannelProductNo vs MerchantProductNo
Every order line, cancelation, and return must reference a product so ChannelEngine can match it to the correct item in the merchant's catalogue. There are two identifier types, and using the wrong one — or mixing them inconsistently — is a common source of failed order lines and unmatched post-order operations.
| Identifier | What it is | Assigned by | When to use it |
ChannelProductNo |
Your channel's own reference for a product. Assigned by you during the product acknowledgement step and stored by ChannelEngine as the mapping to the merchant's catalogue. | Your channel | When your channel syncs and acknowledges the merchant catalogue via GET /v2/products/data. |
MerchantProductNo |
The merchant's own SKU or EAN. Assigned by the merchant in their source system. ChannelEngine stores this alongside the ChannelProductNo once acknowledgement has taken place. |
The merchant | When your channel does not sync or acknowledge the catalogue. Set KeyIsMerchantProductNo: true so ChannelEngine looks up by the merchant's reference. |
MerchantProductNo without setting KeyIsMerchantProductNo: true causes ChannelEngine to look up by the wrong key and the product match will fail. Decide on one identifier strategy per integration and apply it consistently across all order flows.
Impact on order submission
When submitting an order via POST /v2/orders, each entry in the Lines array must identify its product. The field and flag you use depend on whether your channel acknowledges the product catalogue.
- Channel acknowledges products: use
ChannelProductNoin order lines. LeaveKeyIsMerchantProductNoasfalse(the default) or omit it. ChannelEngine resolves the mapping automatically. - Channel does not acknowledge products: use the merchant's SKU in the
MerchantProductNofield and setKeyIsMerchantProductNo: trueat the order level.
If ChannelEngine cannot match the product reference to a known item in the merchant's catalogue, the order line will fail to process. This surfaces as Success: false with a validation error on the product field.
Impact on cancelations and returns
The same identifier logic applies to all post-order operations. For cancelations via POST /v2/cancellations/channel, set the LineIdentifierType field to one of the following values:
ORDER_LINE_ID— use the internal line ID returned in the order creation response. This is the most precise method and the recommended default.CHANNEL_PRODUCT_NO— use your channel's product reference.MERCHANT_PRODUCT_NO— use the merchant's SKU.
CHANNEL_PRODUCT_NO or MERCHANT_PRODUCT_NO on orders where the same product appears on multiple lines. ChannelEngine cannot distinguish between duplicate lines using a product-based identifier, so the wrong line may be canceled. Use ORDER_LINE_ID in these cases.
For returns via POST /v2/returns/channel, use ChannelProductNo in the return line when your channel acknowledges products. Use MerchantProductNo and set KeyIsMerchantProductNo: true on the parent object when you only have the merchant's SKU available.
Every GET response for shipments, cancelations, and returns includes both ChannelProductNo and MerchantProductNo in each line, so you can always reconcile against whichever reference your system stores.
The table below summarises which identifier to use in each operation:
| Operation | Field | Flag required | Notes |
POST /v2/orders (channel acknowledges) |
ChannelProductNo |
KeyIsMerchantProductNo: false (default) |
Standard approach for full channel integrations |
POST /v2/orders (no catalogue sync) |
MerchantProductNo |
KeyIsMerchantProductNo: true |
Required when your channel does not sync or acknowledge the catalogue |
POST /v2/cancellations/channel |
Line ID, channel no., or merchant no. | LineIdentifierType (required) |
Prefer ORDER_LINE_ID to avoid ambiguity |
POST /v2/returns/channel (channel acknowledges) |
ChannelProductNo |
KeyIsMerchantProductNo: false (default) |
Standard when channel acknowledges products |
POST /v2/returns/channel (no catalogue sync) |
MerchantProductNo |
KeyIsMerchantProductNo: true |
Use when only the merchant's SKU is available |
| GET responses (shipments, cancelations, returns) | Both identifiers returned | — | Reconcile against whichever reference your system stores |
Posting orders
Use POST /v2/orders to submit buyer orders to ChannelEngine for routing to the relevant merchant.
ChannelOrderNo must be unique per channel. Submitting a duplicate returns 409 Conflict. Before retrying a failed submission, always query the order first to confirm it was not already created — a network timeout does not mean the order was not received.
When an order is created successfully, the response includes Lines[].Id — ChannelEngine's internal identifier for each order line. Capture and persist these IDs at order creation time. You will need them when creating shipments or cancelations later.
Test all order scenarios in the demo environment before going to production. This includes multi-line orders, pickup point addresses (AddressType: PICKUP_POINT), and orders containing service lines.
Post-order flows
Post-order flows cover the three types of update that occur after an order has been submitted: shipments from the merchant, channel-initiated cancelations, and buyer returns. Each follows the general rule that applies throughout the Channel API — always check Success in the response body on every POST, not just the HTTP status.
Shipments
Poll for fulfilment updates using GET /v2/shipments. Pass the timestamp of your last successful sync as fromDate to retrieve only new shipments. Advancing this cursor with each cycle is more efficient than fetching a wide date range every time.
A shipment with status PENDING has no tracking number yet — TrackTraceNo will be empty. If your integration requires a tracking number, add statuses=SHIPPED to your request to exclude pending shipments.
Cancelations
Use POST /v2/cancellations/channel/bulk when processing more than one cancelation at a time. This reduces API call volume. All cancelations in a bulk request must share the same IdentifierType and LineIdentifierType — split your batch if they differ.
The IsForcedCancellation flag cancels the order even if the merchant has already processed it. Use it only when genuinely necessary, as it can create data inconsistencies on the merchant side.
Returns
Submit buyer returns using POST /v2/returns/channel. Poll for existing return records using GET /v2/returns/channel, passing the timestamp of your last successful GET as createdSince to retrieve only new returns.
When fetching returns via GET, the OrderLine field and its children can be null if the original order line has been archived or reached a terminal state. Build null-safe mapping logic from the start — do not assume the linked order line data is always present.
Rate limits and pagination
Respect the rate limit - read the reset header before retrying. The Channel API enforces a rate limit of 1,000 requests per 15 minutes, shared across all endpoints. On a 429 Too Many Requests response, read the X-Rate-Limit-Reset header and pause until that timestamp before retrying. Retrying immediately in a loop will continue producing 429 responses and deplete your available request budget.
Set pageSize explicitly for large catalogues - always set pageSize explicitly on paginated endpoints — for example, pageSize=250. When no page size is specified, all pending records may be returned in a single response, which can produce very large payloads and increase the risk of timeouts on large catalogues.
Add a small delay between paginated requests - during bulk catalogue retrieval, add a minimum delay of 500 ms between paginated requests to stay comfortably within rate limits. For offer data, complete the full pagination cycle as quickly as possible — prices and stock levels can change between paginated requests.
Debugging and support
Log RequestId and LogId from every API response in production. When reporting an issue to ChannelEngine Support, provide both values so the team can locate your exact request in their system without requiring you to reproduce it.
When a GET returns empty results or unexpected data, first log in to the ChannelEngine interface and confirm the data is present. An empty API response often means no records match your current filters — not that the API has a bug. Checking the interface rules out configuration or merchant-side issues before you start investigating your integration.
Use demo.channelengine.net for all development, QA, and edge case testing. The demo environment behaves identically to production and is the safest place to verify your full order-to-shipment loop, cancelation handling, and return flows end to end.
Common issues
| Area | Mistake | Impact | Fix |
| Auth | Using a Merchant API key on Channel API endpoints | 401 or silent Success: false |
Confirm key type before every new environment setup |
| Products | Not acknowledging processed products or offers | Infinite re-queuing; duplicate processing | POST acknowledgement after every processed batch |
| Products | Reading default attributes instead of MappedFields |
Incorrect or generic listing content on the marketplace | Always use MappedFields as the primary source |
| Products | Silently falling back to defaults when a MappedFields key is absent |
Bad data pushed live without the merchant being aware | Flag and surface the gap; do not fall back silently |
| Products | Skipping acknowledgements in the first-time onboarding sequence | Broken parent or child references on products | Follow the grandparent → parent → child sequence strictly |
| Orders | Not storing Lines[].Id from the order creation response |
Unable to create shipments or cancelations later | Capture and persist line IDs at order creation time |
| Orders | Retrying a failed order POST without checking whether it was already created | 409 Conflict on retry; duplicate order risk |
Query first; only submit if the order does not exist |
| Post-order | Only checking HTTP status on write POSTs | Silent failures — operation failed but code assumes success | Always check Success in the response body |
| Post-order | Not handling null on OrderLine in return responses |
Crash when the original order line is archived or in a terminal state | Build null-safe mapping logic from the start |
| Product IDs | Using MerchantProductNo without setting KeyIsMerchantProductNo: true |
Product match fails; order line does not process | Always set the flag when using the merchant's SKU as the identifier |
| Product IDs | Using a product-based LineIdentifierType on orders with duplicate product lines |
Wrong line may be canceled | Use ORDER_LINE_ID for precise line matching |
| Product IDs | Mixing identifier strategies across order and post-order flows | Inconsistent matching; hard-to-trace failures in post-order operations | Pick one identifier strategy and apply it consistently across all endpoints |
| General | Retrying 429 immediately without reading X-Rate-Limit-Reset |
Continued throttling; wasted request budget | Pause until the reset timestamp, then retry |
| General | Not setting pageSize on product endpoints |
Large payloads; timeout risk on large catalogues | Always set pageSize explicitly and paginate |
| General | Not logging RequestId and LogId |
Slow, difficult support investigations | Log both on every API call in production |
Integration readiness checklist
Run through this checklist before going live.
- Using a Channel API key (not a Merchant API key) in every environment
- API key passed via the
X-CE-KEYheader (not the query string) in production - Checking the
Successfield on every API response, not just the HTTP status - Logging
RequestIdandLogIdfrom every response in production - Acknowledging product data (
POST /v2/products/data) after every processed batch - Acknowledging offers (
POST /v2/products/offers) after every processed batch - Using
MappedFieldsas the primary source for all marketplace listing attributes - Handling
nullgracefully on all optional fields - Following the grandparent → parent → child acknowledgement sequence for first-time product sync
- Identifier strategy decided upfront:
ChannelProductNo(with product acknowledgement) orMerchantProductNo(without) KeyIsMerchantProductNo: trueset wherever the merchant's SKU is used in order or return lines- Cancelation
LineIdentifierTypeset toORDER_LINE_IDfor orders where the same product may appear on multiple lines - Storing
Lines[].Idfrom the order creation response for use in later shipment and cancelation calls - Validating
ChannelOrderNouniqueness before each order POST - Filtering shipments with
statuses=SHIPPEDwhen tracking numbers are required - Respecting
X-Rate-Limit-Resetbefore retrying after a 429 - Setting explicit
pageSizeon all paginated endpoints - Full order-to-shipment loop, cancelation handling, and return flows tested end-to-end in the demo environment
Next steps
With the patterns in this article applied, you will avoid the most common integration pitfalls and have a solid foundation for a reliable Channel API connection. Refer to the individual endpoint articles below for full field references and request/response examples.
-
GET /v2/products/data— Product data sync and onboarding Channel API: retrieve product content -
GET /v2/products/offers— Price, stock, and offer sync Channel API: retrieve product offers -
POST /v2/orders— Submitting orders to merchants Channel API: orders -
GET /v2/shipments— Retrieving fulfilment updates Channel API: shipments -
POST /v2/cancellations/channel— Channel-initiated cancelations Channel API: cancelations -
POST /v2/returns/channel— Submitting buyer returns Channel API: returns
Comments
0 comments
Article is closed for comments.