Cancel Customer Order
Overview
The Cancel Order API allows authenticated customers to cancel their pending orders. This mutation validates order ownership, checks cancellation eligibility, and reverses inventory allocation when successful.
Endpoint
GraphQL Mutation URL: POST /api/graphql
Authentication
Required: Bearer Token (Sanctum)
Scope: Customer only (order must belong to authenticated customer)
Request
GraphQL Mutation Schema
mutation CreateCancelOrder($input: CancelOrderInput!) {
createCancelOrder(input: $input) {
cancelOrder {
success # Boolean: true if cancel succeeded
message # String: response message
orderId # Int: the order ID
status # String: final order status
}
}
}Input Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
orderId | Integer | Yes | The numeric ID of the order to cancel |
Response
Success Response (200 OK)
{
"data": {
"createCancelOrder": {
"cancelOrder": {
"success": true,
"message": "Order has been canceled successfully",
"orderId": 2,
"status": "canceled"
}
}
}
}Failure Response - Cannot Cancel
When order cannot be canceled (already canceled, shipped, or completed):
{
"data": {
"createCancelOrder": {
"cancelOrder": {
"success": false,
"message": "Order cannot be canceled. It may have already been processed, shipped, or canceled",
"orderId": 2,
"status": "canceled"
}
}
}
}Error Response - Unauthorized (401)
{
"errors": [
{
"message": "Unauthenticated",
"extensions": {
"code": "UNAUTHENTICATED"
}
}
]
}Error Response - Order Not Found (404)
When order ID doesn't exist or belongs to a different customer:
{
"data": {
"createCancelOrder": null
}
}Business Logic
Cancellation Eligibility
An order can be canceled if:
- Order status is
pending(not shipped, completed, or already canceled) - Order belongs to the authenticated customer
- Order is not a composite/grouped order (or all child items are cancelable)
When Cancellation Succeeds
- Order Status: Changed from
pending→canceled - Inventory: All ordered items are returned to stock
- Qty Canceled: Updated to match ordered quantity for all items
- Events Fired:
order.cancel.before— before cancel operationsorder.cancel.after— after successful cancellation
- Database: Order and item records updated atomically
When Cancellation Fails
- Order status remains unchanged
- No inventory is returned
- Appropriate error message returned
State Transitions
pending → canceled (valid)
shipped → (cannot cancel)
completed → (cannot cancel)
canceled → (cannot re-cancel)Use Cases
- Cancel unwanted orders before processing
- Allow customers to self-service cancel pending orders
- Automatically restore inventory when customers cancel
- Reduce support requests by enabling customer-driven cancellation
- Workflow: Customer views order → clicks cancel → inventory restored
Testing Examples
Test Case 1: Cancel Pending Order (Success)
Precondition: Order #2 with status pending exists for customer #2
Query:
mutation {
createCancelOrder(input: { orderId: 2 }) {
cancelOrder {
success
message
orderId
status
}
}
}Expected Result:
{
"success": true,
"message": "Order has been canceled successfully",
"orderId": 2,
"status": "canceled"
}Database Verification:
SELECT id, status FROM orders WHERE id = 2;
-- Result: id=2, status='canceled'
SELECT order_id, qty_ordered, qty_canceled FROM order_items WHERE order_id = 2;
-- Result: qty_canceled should equal qty_ordered for all itemsTest Case 2: Re-Cancel Already Canceled Order (Failure)
Precondition: Order #2 with status canceled (from Test Case 1)
Query:
mutation {
createCancelOrder(input: { orderId: 2 }) {
cancelOrder {
success
message
orderId
status
}
}
}Expected Result:
{
"success": false,
"message": "Order cannot be canceled. It may have already been processed, shipped, or canceled",
"orderId": 2,
"status": "canceled"
}No Database Changes: Order remains in canceled status
Test Case 3: Cancel Without Authentication (Failure)
Query (without Authorization header):
curl -X POST http://127.0.0.1:8000/api/graphql \
-H "Content-Type: application/json" \
-H "X-STOREFRONT-KEY: pk_storefront_qrr4vsdbs6xNpL7DN0GHUcB0XnhjnjIS" \
-d '{"query":"mutation { createCancelOrder(input: { orderId: 2 }) { cancelOrder { success message } } }"}'Expected Result:
HTTP 401 Unauthorized
{
"errors": [
{
"message": "Unauthenticated",
"extensions": {"code": "UNAUTHENTICATED"}
}
]
}Implementation Details
Files Involved
| File | Purpose |
|---|---|
CancelOrderInput.php | Input DTO with orderId parameter |
CancelOrderProcessor.php | Handles mutation business logic |
CancelOrder.php | Response model with success/message/orderId/status |
Key Components
CancelOrderProcessor:
- Authenticates request via
Auth::guard('sanctum') - Scopes orders to authenticated customer only
- Delegates to
OrderRepository::cancel()for business logic - Returns
CancelOrderresponse model
OrderRepository::cancel():
- Validates
$order->canCancel()method - Fires
order.cancel.beforeevent - Iterates order items and returns inventory
- Updates
qty_canceledfor each item - Calls
updateOrderStatus('canceled') - Fires
order.cancel.afterevent
HTTP Status Codes
| Code | Scenario |
|---|---|
| 200 | Mutation executed (check success field for actual result) |
| 400 | Invalid request (missing storefront key, malformed query) |
| 401 | Unauthorized (missing or invalid Bearer token) |
| 422 | Validation error (invalid orderId type) |
Rate Limiting
No specific rate limiting for cancel mutations. General API rate limits apply per storefront key.
Notes
- Customer isolation: Orders are scoped to the authenticated customer. A customer cannot cancel another customer's order.
- Inventory restoration: When an order is canceled, all items are returned to inventory automatically.
- Status tracking: The operation is governed by Bagisto's order cancellation rules and configuration.
- Event hooks: Extensions can listen to
order.cancel.beforeandorder.cancel.afterevents. - Localization: All messages are localized to the customer's language.
Related Resources
- Get Customer Orders — Query all customer orders
- Get Customer Order — Query a specific order before canceling
- Reorder Customer Order — Re-add items from a canceled order
- Customer Login — Obtain authentication token
- Place Order — Create new orders

