- Callback Events
- Order Cancel Resolutions
Callback Events
Order Cancel Resolutions
Webhook event sent when asynchronous order cancel requests are resolved
Order Cancel Resolution events notify you of the success or failure of order cancellation requests. When you submit a cancel request, this event confirms whether the cancellation was processed or if the order was already too far in fulfillment.
Orders can only be canceled before they are packed. Once packing begins, cancellation requests will fail.
Event Payload
{
"callback_url": "https://client.com/api/orderCancelResolution",
"message_type": "orderCancelResolution",
"message_id": "0896116f-e54b-4756-9d3e-1b0c4a25d821",
"data": [
{
"id": "0b744e29-b668-4486-85dd-82528b5da0dd",
"customer_order_id": "12345",
"status": "failure",
"reason": "Order already packed",
"created_at": "2018-08-05T17:32:28Z",
"updated_at": "2018-08-05T17:32:28Z"
}
]
}
Payload Fields
Your registered webhook endpoint URL
Always orderCancelResolution for this event type
Unique identifier for this event. Use for idempotency checks.
Array of cancel resolution records. Each record contains:
Resolution Status Values
Success
Order was successfully canceled and inventory released
Failure
Order could not be canceled (reason provided)
Common Failure Reasons
| Reason | Description | Action |
|---|---|---|
Order already packed | Order is packed and ready to ship | Cannot cancel - initiate RMA after delivery |
Order already shipped | Order has been shipped | Cannot cancel - process return via RMA |
Order already canceled | Order was previously canceled | No action needed |
Order not found | Order doesn’t exist in system | Verify order ID |
Cancellation Window
Orders can only be canceled during these stages:
Order Received
Order has been transmitted to MasonHub - Cancellation available ✓
At Warehouse
Order received at distribution center - Cancellation available ✓
In Process
Order being picked - Cancellation may be available (time-sensitive) ⚠️
Packed
Order packed and ready to ship - Cancellation NOT available ✗
Fulfilled
Order shipped - Cancellation NOT available ✗
Example Payloads
Successful Cancellation
{
"message_type": "orderCancelResolution",
"message_id": "abc123",
"data": [
{
"id": "0b744e29-b668-4486-85dd-82528b5da0dd",
"customer_order_id": "12345",
"status": "success",
"reason": null,
"created_at": "2018-08-05T17:32:28Z",
"updated_at": "2018-08-05T17:32:30Z"
}
]
}
Failed Cancellation
{
"message_type": "orderCancelResolution",
"message_id": "def456",
"data": [
{
"id": "1c855f30-c779-5597-96ee-93639c6eb0ee",
"customer_order_id": "67890",
"status": "failure",
"reason": "Order already packed",
"created_at": "2018-08-05T17:45:10Z",
"updated_at": "2018-08-05T17:45:12Z"
}
]
}
Implementation Example
@app.route('/api/orderCancelResolution', methods=['POST'])
def handle_order_cancel_resolution():
try:
payload = request.get_json()
message_id = payload['message_id']
# Check if already processed
if is_message_processed(message_id):
return 'OK', 200
# Process each resolution
for resolution in payload['data']:
order_id = resolution['customer_order_id']
status = resolution['status']
reason = resolution.get('reason')
if status == 'success':
# Mark order as canceled
mark_order_canceled(order_id)
# Process refund
process_refund(order_id)
# Notify customer
send_cancellation_confirmation(order_id)
logger.info(f"Order {order_id} canceled successfully")
else: # failure
# Log failure
log_cancel_failure(order_id, reason)
if reason == "Order already packed":
# Inform customer they need to return after delivery
notify_customer_return_required(order_id)
# Prepare RMA for when package arrives
prepare_return_label(order_id)
elif reason == "Order already shipped":
# Initiate return process
create_rma(order_id)
send_return_instructions(order_id)
logger.error(f"Order {order_id} cancel failed: {reason}")
mark_message_processed(message_id)
return 'OK', 200
except Exception as e:
logger.error(f"Cancel resolution webhook error: {e}")
return 'Error', 500
app.post('/api/orderCancelResolution', async (req, res) => {
try {
const payload = req.body;
const messageId = payload.message_id;
// Check if already processed
if (await isMessageProcessed(messageId)) {
return res.status(200).send('OK');
}
// Process each resolution
for (const resolution of payload.data) {
const orderId = resolution.customer_order_id;
const status = resolution.status;
const reason = resolution.reason;
if (status === 'success') {
// Mark order as canceled
await markOrderCanceled(orderId);
// Process refund
await processRefund(orderId);
// Notify customer
await sendCancellationConfirmation(orderId);
console.log(`Order ${orderId} canceled successfully`);
} else {
// Log failure
await logCancelFailure(orderId, reason);
if (reason === 'Order already packed') {
// Customer needs to return after delivery
await notifyCustomerReturnRequired(orderId);
await prepareReturnLabel(orderId);
} else if (reason === 'Order already shipped') {
// Initiate return process
await createRMA(orderId);
await sendReturnInstructions(orderId);
}
console.error(`Order ${orderId} cancel failed: ${reason}`);
}
}
await markMessageProcessed(messageId);
res.status(200).send('OK');
} catch (error) {
console.error('Cancel resolution webhook error:', error);
res.status(500).send('Error');
}
});
Cancel Request Flow
- Submit Cancellation - Call
DELETE /orders/{id}orPUT /orders/{id}/cancel - Receive Acknowledgment - API returns 202 Accepted
- Wait for Resolution - MasonHub processes cancellation asynchronously
- Receive Event - Get
orderCancelResolutionwebhook with success/failure
sequenceDiagram
participant Customer
participant Your System
participant MasonHub API
participant Warehouse
participant Webhook
Customer->>Your System: Cancel order request
Your System->>MasonHub API: DELETE /orders/12345
MasonHub API-->>Your System: 202 Accepted
MasonHub API->>Warehouse: Process cancel request
alt Order can be canceled
Warehouse->>MasonHub API: Cancellation success
MasonHub API->>Webhook: orderCancelResolution (success)
Webhook-->>MasonHub API: 200 OK
Your System->>Customer: Cancellation confirmed
else Order already packed
Warehouse->>MasonHub API: Cancellation failed
MasonHub API->>Webhook: orderCancelResolution (failure)
Webhook-->>MasonHub API: 200 OK
Your System->>Customer: Return instructions
end
Use Cases
Cancellation Confirmation
Confirm order cancellations and process refunds
Return Fallback
Automatically prepare RMA for failed cancellations
Customer Communication
Inform customers of cancellation status
Refund Processing
Trigger refunds only after successful cancellation
Best Practices
Cancel Immediately
Submit cancellation requests as soon as customer requests to maximize success
Have RMA Fallback
Automatically prepare returns for failed cancellations
Process Refunds Correctly
Only refund after successful cancellation confirmation
Clear Communication
Inform customers whether they’ll get a refund or need to return
Never process refunds before receiving a successful cancellation resolution. Failed cancellations mean the order shipped and requires a return.
Cancellation Tips
Maximize Success Rate
- Submit cancellations immediately when customers request
- Monitor order status - Don’t attempt to cancel packed/shipped orders
- Check order events - Use real-time order events to track fulfillment stage
- Set customer expectations - Inform them cancellations aren’t guaranteed
Handle Failures Gracefully
- Prepare return labels automatically for failed cancellations
- Send clear instructions to customers about return process
- Create RMA preemptively to streamline returns
- Update order status to reflect it will be delivered
Response Requirements
Your webhook endpoint must:
- Respond within 30 seconds - Return HTTP 200 to acknowledge receipt
- Handle both statuses - Implement logic for success and failure
- Process refunds correctly - Only refund successful cancellations
- Prepare for returns - Set up RMA flow for failed cancellations
Related Events
- Order Events - Monitor order status to know if cancellation is possible
- Order Update Resolutions - Update request confirmations
- RMA Events - Handle returns for failed cancellations