Channel API: cancellations
About this article
This article explains how cancellations flow between your channel and ChannelEngine. It covers how to poll for merchant-initiated cancellations, how to submit a single channel-initiated cancellation, and how to submit multiple cancellations in one request.
Table of contents
- Endpoint: poll for merchant-initiated cancellations
- Endpoint: submit a single channel cancellation
- Endpoint: submit bulk channel cancellations
Introduction
Cancellations flow in both directions between your channel and ChannelEngine. Merchants can cancel orders they are unable to fulfill, and your channel can submit cancellations on behalf of buyers. Use the three cancellation endpoints described in this article to keep order statuses consistent across your marketplace and ChannelEngine.
401 Unauthorized response. If you are a merchant looking to cancel your own orders, use the Merchant API instead.
Overview
Refer to the flowchart below to visualize how cancellations travel between your channel, ChannelEngine, and the merchant.
Requirements
- Channel API key - pass it as a URL query parameter:
?apikey={your-key}. Find it on at given channel at Setup, General, API key. - Orders on ChannelEngine - for the POST endpoints, orders must already exist on ChannelEngine (submitted via
POST /v2/orders) before you can cancel them. The identifiers you use in the cancellation must match records that ChannelEngine already holds. - Identifier strategy - decide how your integration will reference orders and order lines before making requests. See Identifier types explained.
Available API endpoints
There are three cancellation endpoints in the Channel API, covering both directions of cancellation flow.
-
Poll for merchant-initiated cancellations:
GET /v2/cancellations
Use this endpoint to retrieve cancellations that merchants have raised against orders on your channel. Poll it regularly as part of your order-sync loop and update the corresponding order status on your marketplace when a cancellation appears. -
Submit a single channel cancellation:
POST /v2/cancellations/channel
Use this endpoint to submit a single cancellation on behalf of your channel – for example, when a buyer cancels before the merchant has dispatched the item. -
Submit bulk channel cancellations:
POST /v2/cancellations/channel/bulk
Use this endpoint to submit multiple channel-initiated cancellations in a single request, reducing the number of API calls needed when processing a batch.
Endpoint: poll for merchant-initiated cancellations
-
Retrieve merchant cancellations
GET /v2/cancellations
Use this endpoint to retrieve cancellations that merchants have raised against orders on your channel. Poll it regularly as part of your order-sync loop and update the corresponding order status on your marketplace when a cancellation appears.
GET /v2/shipments before updating your marketplace.
Making the request
Send a GET request to the cancellations endpoint, passing your API key as a query parameter:
GET https://{tenant}.channelengine.net/api/v2/cancellations?apikey={your-key}Example using cURL – fetching all cancellations since 1 June 2026:
curl -X GET \ "https://demo.channelengine.net/api/v2/cancellations?fromDate=2026-06-01T00:00:00Z&apikey=YOUR_API_KEY" \ -H "Accept: application/json"
fromDate filter in production. Without it, the endpoint returns all cancellations ever recorded for your channel. Use your last sync timestamp as the cursor to keep each poll lightweight.
Query parameters
| Parameter | Type | Required | Description |
apikey |
string | Required | Your Channel API key. |
fromDate |
ISO 8601 | Optional | Return cancellations created or updated on or after this date (inclusive). Strongly recommended in production as your polling cursor. |
toDate |
ISO 8601 | Optional | Return cancellations created or updated before this date (exclusive). Combine with fromDate to reprocess a specific date range. |
channelOrderNos |
array[string] | Optional | Filter to specific orders by your channel's order numbers. Useful for on-demand lookups when a buyer queries a cancellation status. |
merchantOrderNos |
array[string] | Optional | Filter to specific orders by the merchant's order numbers. |
isMerchantCreator |
boolean | Optional | When true, returns only merchant-initiated cancellations. When false, returns only channel-initiated cancellations. |
page |
integer | Optional | The page to retrieve. Starts at 1. Use with TotalCount in the response to retrieve all pages. |
Response structure
A successful call returns HTTP 200 with a JSON body. Cancellations are wrapped in the standard ChannelEngine response envelope.
{
"Content": [ /* array of cancelation objects */ ],
"Count": 1,
"TotalCount": 14,
"ItemsPerPage": 100,
"StatusCode": 200,
"Success": true
}Use TotalCount and ItemsPerPage to determine how many pages to request. Increment the page parameter until all pages are retrieved.
Example cancellation object
{
"ChannelOrderNo": "CH-ORDER-1001",
"MerchantCancellationNo": "CANCEL-9876",
"IsMerchantCreator": true,
"Reason": "Item no longer available",
"ReasonCode": "NOT_IN_STOCK",
"IsTest": false,
"CreatedAt": "2026-06-07T14:30:00Z",
"UpdatedAt": "2026-06-07T14:30:00Z",
"Lines": [ /* see line fields below */ ]
}Cancellation fields
Each object in the Content array represents one cancellation.
| Field | Type | Description |
ChannelOrderNo |
string | Your channel's unique identifier for the order being cancelled. Use this to match the cancellation to the correct order in your system. |
MerchantCancellationNo |
string | The merchant's internal reference for this cancellation. |
IsMerchantCreator |
boolean | true when the merchant initiated the cancellation; false when it was submitted by the channel. |
Reason |
string | Free-text reason explaining why the cancellation was raised. |
ReasonCode |
string | Machine-readable reason code. See Cancellation reason codes. |
IsTest |
boolean | true if this cancellation was created in a test or sandbox context. Exclude these from production processing. |
CreatedAt |
datetime | When the cancellation was first created on ChannelEngine (ISO 8601). |
UpdatedAt |
datetime | When the cancellation record was last modified (ISO 8601). Use as your fromDate cursor when polling for changes. |
Lines |
array | The order lines included in this cancelation. See Line fields below. |
Line fields
Each entry in Lines identifies a specific product line included in the cancellation. It contains both the product references and a nested OrderLine snapshot with full detail from the original order.
{
"ChannelProductNo": "CH-PROD-42",
"MerchantProductNo": "SKU-00123",
"Quantity": 1,
"ShipmentStatus": "NOT_SHIPPED",
"OrderLine": {
"Status": "IN_PROGRESS",
"IsFulfillmentByMarketplace": false,
"Quantity": 1,
"CancellationRequestedQuantity": 1,
"UnitPriceInclVat": 24.99,
"UnitVat": 4.34,
"LineTotalInclVat": 24.99,
"LatestShipmentDate": "2026-06-10T23:59:00Z",
"ShippingMethod": "PostNL",
"Condition": "NEW"
}
}Top-level line fields
| Field | Type | Description |
ChannelProductNo |
string | Your channel's product reference for this line. |
MerchantProductNo |
string | The merchant's SKU for this line. |
Quantity |
integer | Number of units being cancelled on this line. |
ShipmentStatus |
enum | Shipment status of this line at the time of cancellation. A value of SHIPPED means the item was already dispatched – treat this as a return request rather than a standard cancellation. |
OrderLine |
object | The original order line. See OrderLine fields below. |
OrderLine fields
| Field | Type | Description |
Status |
enum | Order line status at time of cancellation (e.g. IN_PROGRESS). |
IsFulfillmentByMarketplace |
boolean | true if this line is fulfilled by the marketplace rather than the merchant. |
Gtin |
string | Global Trade Item Number (barcode) of the product. |
Description |
string | Product description as submitted when the order was created. |
Quantity |
integer | Total quantity originally ordered on this line. |
CancellationRequestedQuantity |
integer | Quantity for which this cancellation was requested. |
UnitPriceInclVat |
decimal | Unit price paid by the buyer, including VAT. |
UnitVat |
decimal | VAT amount per unit. |
LineTotalInclVat |
decimal | Total line value including VAT (unit price × quantity). |
LineVat |
decimal | Total VAT amount for the line. |
OriginalUnitPriceInclVat |
decimal | Original unit price before any discounts were applied. |
OriginalLineTotalInclVat |
decimal | Original line total before any discounts were applied. |
FeeFixed |
decimal | Fixed fee charged by the channel for this line. |
FeeRate |
decimal | Percentage-based fee charged by the channel for this line. |
Condition |
enum | Condition of the product: NEW, USED, REFURBISHED, etc. |
ExactDeliveryDate |
datetime | Confirmed delivery date promised to the buyer, if applicable. |
ExpectedDeliveryDate |
datetime | Estimated delivery date based on the shipping method selected. |
LatestDeliveryDate |
datetime | The deadline by which the order must be delivered to the buyer. |
ExactShipmentDate |
datetime | Confirmed date on which the item was or will be shipped. |
ExpectedShipmentDate |
datetime | Estimated date the merchant will ship this line. |
LatestShipmentDate |
datetime | The deadline by which the merchant must ship this line. |
ShippingMethod |
string | Carrier or shipping method requested for this line (e.g.: PostNL, DHL). |
ShippingServiceLevel |
string | Service level associated with the shipping method (e.g.: STANDARD, EXPRESS). |
BundleProductMerchantProductNo |
string | Merchant product number of the parent bundle, if this line is part of a product bundle. |
Response envelope fields
| Field | Type | Description |
Count |
integer | Number of cancellations returned on this page. |
TotalCount |
integer | Total number of cancellations matching your filters across all pages. |
ItemsPerPage |
integer | Maximum number of items returned per page. |
StatusCode |
integer | HTTP-equivalent status code within the response body (normally 200). |
RequestId |
string | Unique identifier for this API call. Include this in any support request for faster diagnosis. |
LogId |
string | Internal ChannelEngine log reference. Also useful when contacting support alongside RequestId. |
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 itself was malformed. |
Success field in your integration – not just the HTTP status code. In some cases the HTTP response may return 200 while Success is false, indicating a business-logic error. Read Message and ValidationErrors for details.
Endpoint: submit a single channel cancellation
-
Send a buyer cancellation to ChannelEngine:
POST /v2/cancellations/channel
Use this endpoint to submit a single cancellation on behalf of your channel. A typical use case is when a buyer cancels their order through your marketplace before the merchant has shipped the item.
Lines array. Partial cancellations – where only some lines are cancelled – are supported.
Making the request
Send a POST request with a JSON body and your API key as a query parameter:
POST https://{tenant}.channelengine.net/api/v2/cancellations/channel?apikey={your-key}Example using cURL:
curl -X POST \
"https://demo.channelengine.net/api/v2/cancellations/channel?apikey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"LineIdentifierType": "ORDER_LINE_ID",
"IdentifierType": "ORDER_ID",
"Model": {
"ChannelCancellationNo": "CANCEL-2026-001",
"Identifier": "CH-ORDER-1001",
"Reason": "Buyer requested cancelation before dispatch",
"ReasonCode": "BUYER_CANCELLATION",
"IsForcedCancellation": false,
"Lines": [
{ "OrderLineIdentifier": "LINE-001", "Quantity": 1 }
]
}
}'Request body fields
Top-level fields
| Field | Type | Required | Description |
IdentifierType |
string | Required |
How the order is identified in the Identifier field. See Identifier types explained. |
LineIdentifierType |
string | Required |
How each order line is identified in OrderLineIdentifier. See Identifier types explained. |
Model |
object | Required | The cancellation details. See Model fields below. |
Model fields
| Field | Type | Required | Description |
ChannelCancellationNo |
string | Required | Your channel's unique reference for this cancellation. Must be unique per channel. |
Identifier |
string | Required | The identifier of the order to cancel. The format depends on the IdentifierType you chose. |
Reason |
string | Optional | Free-text reason for the cancellation, visible to the merchant. |
ReasonCode |
string | Required | Machine-readable reason code. See Cancellation reason codes. |
IsForcedCancellation |
boolean | Optional | When true, the cancellation is applied even if the merchant has already processed the order. This overrides normal eligibility checks. Use with caution. Defaults to false. |
Lines |
array | Required | The order lines to cancel. See Line fields below. |
Line fields
| Field | Type | Required | Description |
OrderLineIdentifier |
string | Required | Identifier for the specific order line to cancel. The format depends on the LineIdentifierType you chose. |
Quantity |
integer | Required | Number of units to cancel on this line. Must be greater than 0 and cannot exceed the original ordered quantity. |
Response
A successful submission returns HTTP 200 with Success: true in the response body. No Content array is returned – only the standard envelope fields.
Success in the response body. If Success is false, read the Message and ValidationErrors fields for the specific failure reason.
Endpoint: submit bulk channel cancellations
-
Send buyer cancellations to ChannelEngine in bulk:
POST /v2/cancellations/channel/bulk
Use this endpoint to submit multiple channel-initiated cancellations in a single request. It is functionally identical to POST /v2/cancellations/channel, but accepts an array of cancellations in Models instead of a single object in Model. This reduces the number of API calls needed when processing a batch.
IdentifierType and LineIdentifierType apply to all cancellations in the batch. If different orders in your batch use different identifier schemes, split them into separate bulk requests.
Making the request
Send a POST request with a JSON body and your API key as a query parameter:
POST https://{tenant}.channelengine.net/api/v2/cancellations/channel/bulk?apikey={your-key}Example using cURL – submitting two cancellations in one request:
curl -X POST \
"https://demo.channelengine.net/api/v2/cancellations/channel/bulk?apikey=YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"LineIdentifierType": "ORDER_LINE_ID",
"IdentifierType": "ORDER_ID",
"Models": [
{
"ChannelCancellationNo": "CANCEL-2026-001",
"Identifier": "CH-ORDER-1001",
"Reason": "Buyer requested cancelation",
"ReasonCode": "BUYER_CANCELLATION",
"IsForcedCancellation": false,
"Lines": [
{ "OrderLineIdentifier": "LINE-001", "Quantity": 2 }
]
},
{
"ChannelCancellationNo": "CANCEL-2026-002",
"Identifier": "CH-ORDER-1002",
"Reason": "Item out of stock",
"ReasonCode": "NOT_IN_STOCK",
"IsForcedCancellation": false,
"Lines": [
{ "OrderLineIdentifier": "LINE-002", "Quantity": 1 }
]
}
]
}'Request body fields
| Field | Type | Required | Description |
IdentifierType |
string | Required | How orders are identified across the entire batch. See Identifier types explained. |
LineIdentifierType |
string | Required | How order lines are identified across the entire batch. See Identifier types explained. |
Models |
array of objects | Required | One or more cancellation objects. Each uses the same field structure as Model in the single endpoint – see Request body fields above. |
Identifier types explained
Both POST endpoints require you to declare how you identify the order and its lines. This lets ChannelEngine match your cancellation to the correct records regardless of which reference you have available.
IdentifierType (for the order)
| Value | Description |
ORDER_ID |
Identify the order using your channel's order number (ChannelOrderNo). This is the most common option for channel integrations. |
MERCHANT_ORDER_NO |
Identify the order using the merchant's internal order number. |
LineIdentifierType (for order lines)
| Value | Description |
ORDER_LINE_ID |
Identify each line using the ChannelEngine-assigned order line ID. Recommended when you store line IDs from the original order response. |
CHANNEL_PRODUCT_NO |
Identify each line using your channel's product number for that line. |
MERCHANT_PRODUCT_NO |
Identify each line using the merchant's product number. |
CHANNEL_PRODUCT_NO or MERCHANT_PRODUCT_NO and the same product appears more than once in an order, ChannelEngine cannot distinguish between duplicate lines. Use ORDER_LINE_ID wherever possible to ensure precision.
Cancellation reason codes
The ReasonCode field accepts the following values. Choose the code that most accurately reflects the situation – merchants use this information to understand why orders are being cancelled.
| Code | When to use |
NOT_IN_STOCK |
The item is unavailable – the merchant cannot fulfill the order because the product is out of stock. |
BUYER_CANCELLATION |
The buyer requested the cancellation before the item was shipped. |
DUPLICATE_ORDER |
The order was placed more than once in error and the duplicate needs to be cancelled. |
PRICING_ERROR |
The listed price was incorrect and the order cannot be fulfilled at the displayed price. |
OTHER |
The cancellation does not fit any other code. Use the free-text Reason field to provide more detail when using this value. |
Common issues
| Symptom | Likely cause | How to fix |
| 401 Unauthorized | API key is missing, incorrect, or belongs to the Merchant API instead of the Channel API. | Check the apikey query parameter. Make sure you are using a Channel API key. |
200 with empty Content |
No cancellations match the applied filters, or no cancellations have been created yet. | Widen the fromDate range, remove filters, or confirm cancellations exist in the ChannelEngine web interface. |
200 with Success: false |
The request was received but a business-logic error prevented processing (e.g. order not found, line already cancelled). | Read the Message and ValidationErrors fields. Correct the identified issues and resubmit. |
| Order not found | The Identifier value does not match any known order, or the wrong IdentifierType was used. |
Verify the order identifier and confirm the IdentifierType matches the format of the value you are sending. |
| Quantity exceeds original | The Quantity in a cancellation line is higher than the original ordered quantity. |
Check the original order to confirm the line quantity and resubmit with a corrected value. |
| 429 Too many requests | Rate limit reached. | Read the X-Rate-Limit-Reset header and wait until that time before retrying. |
| 500 Server error | Unexpected error on ChannelEngine's side. | Wait and retry. If the issue persists, contact ChannelEngine support with the full request URL, request body, and response body. |
Testing
Use the ChannelEngine demo environment at demo.channelengine.net to test your cancellation integration end-to-end before pointing it at a production tenant.
-
Set up test orders in the demo environment - submit one or more orders via
POST /v2/ordersusing your demo API key. Note theChannelOrderNovalues – you will need them when submitting and retrieving cancellations.
Orders must exist on ChannelEngine before you can cancel them. Use the demo environment to avoid affecting live merchant data. -
Submit a channel-initiated cancellation - call
POST /v2/cancellations/channelwith one of your test order numbers, a validReasonCode, and at least one line. Confirm the response returnsSuccess: true.
Log in todemo.channelengine.netand navigate to Orders, Cancellations to verify that the cancellation appears with the correct details. - Simulate a merchant-initiated cancellation - in the ChannelEngine demo interface, open a test order and manually trigger a cancellation from the merchant side. This creates a record your channel can retrieve.
-
Poll
GET /v2/cancellationsand verify the response - callGET /v2/cancellationswith afromDatecovering your test window. Confirm that the merchant-initiated cancellation appears in theContentarray withIsMerchantCreator: true.
Check thatChannelOrderNo,ReasonCode, and line quantities all match what was entered in the demo interface. - Test the bulk endpoint - submit two or more cancellations in a single
POST /v2/cancellations/channel/bulkrequest. Verify that both appear in the ChannelEngine demo interface and thatSuccess: trueis returned for the batch. -
Test error cases - intentionally send a cancellation with an unknown
ChannelOrderNo, a quantity exceeding the original order line, and a missing required field. Confirm each returns a meaningfulMessageorValidationErrorsentry withSuccess: false.
Validating your error-handling logic here prevents silent failures in production.
Next steps
After cancellations are flowing, connect these related endpoints:
GET /v2/shipments- retrieve shipment updates to check whether an order has already been dispatched before processing a cancellation.POST /v2/returns/channel- submit buyer-initiated returns when a buyer contacts your marketplace after receiving their order.GET /v2/orders/new- understand the full order lifecycle to identify which orders are eligible for cancellation.- Use
RequestIdandLogIdfrom any response when contacting ChannelEngine Support about a specific API call.
Comments
0 comments
Article is closed for comments.