Orders Cancel
Cancel Order — PATCH /orders/v1/{orderId}/cancel
Section titled “Cancel Order — PATCH /orders/v1/{orderId}/cancel”State-guarded behaviour
Section titled “State-guarded behaviour”The cancel endpoint checks whether the order is still eligible for cancellation before acting. That check is made server-side, so the client does not need to reason about internal order state:
| Outcome | What happens |
|---|---|
| Order can be cancelled | Cancellation is submitted. Returns 204 No Content. |
| Order already cancelled | Treated as a no-op. Returns 204 No Content. |
| Order not eligible | Cannot be cancelled in its current state. Returns 422 Unprocessable Entity. |
status: "Open"does not guarantee cancellable. Eligibility is evaluated at a finer grain than thestatusfield. To check up front, callGET /orders/v1/{orderId}/allowed-actionsand inspectcanBeCancelled. Either way, act on the cancel response:204means it is (or will be) cancelled,422means it is not eligible.
The operation is asynchronous. A
204response means the cancellation request was accepted, not that the order has already reached theCancelledstate. PollGET /orders/v1/{orderId}untilevents.Cancelledappears if you need to confirm the final state.
Success Scenarios
Section titled “Success Scenarios”Open Order — Cancellation Accepted
Section titled “Open Order — Cancellation Accepted”Order exists, is eligible for cancellation, and the caller has access. The cancellation request is submitted.
Request
PATCH /orders/v1/2000100001/cancelAuthorization: ******Ocp-Apim-Subscription-Key: <subscription_key>Response — 204 No Content
(empty body)After the cancellation is processed, a subsequent GET /orders/v1/2000100001 will show:
{ "order": { "orderId": "2000100001", "events": { "Placed": "2026-06-18T09:38:03.0729832+02:00", "Cancelled": "2026-06-18T12:01:58.565+02:00" }, "orderLines": [ { "lineNumber": "100", "name": "Logitech MX Keys S Trådløst Tastatur", "quantity": { "total": 1, "fulfilled": 0, "cancelled": 1 }, "categories": ["PHYSICAL_ITEM"], "orderLines": [] }, { "lineNumber": "200", "name": "Hjemlevering", "quantity": { "total": 1, "fulfilled": 0, "cancelled": 1 }, "categories": ["DELIVERY"], "orderLines": [] } ], "expectedDeliveries": [], "deliveries": [], "billings": [] }}Key points:
events.Cancelledis added with the cancellation timestamp- All order line quantities:
cancelledincremented to matchtotal;fulfilledstays0 expectedDeliveriesis cleared to[]
Already Cancelled — Idempotent No-Op
Section titled “Already Cancelled — Idempotent No-Op”Order was previously cancelled. The endpoint treats this as a success and returns 204 without
resubmitting the cancellation. This makes the operation safe to retry.
Request
PATCH /orders/v1/2000100003/cancelAuthorization: ******Ocp-Apim-Subscription-Key: <subscription_key>Response — 204 No Content
(empty body)The order state is unchanged. The Cancelled event timestamp in events is the original one.
Error Scenarios
Section titled “Error Scenarios”422 — Order Shows Open But Is Not Eligible
Section titled “422 — Order Shows Open But Is Not Eligible”The status field can still read Open while the order is no longer (or not yet) eligible for
cancellation. This is not distinguishable from a cancellable Open order by looking at status
alone — attempt the cancellation and handle the 422.
Request
PATCH /orders/v1/2000100009/cancelAuthorization: ******Ocp-Apim-Subscription-Key: <subscription_key>Response — 422 Unprocessable Entity
{ "code": "ERR_PROCESSING", "traceId": "TRACE000000000009:00000001", "type": "https://<store-url>/swagger#ProcessingError", "title": "Unprocessable Request", "status": 422, "detail": "Order cannot be cancelled in its current state.", "instance": "/orders/v1/2000100009", "extensions": {}}422 — Order Is Completed
Section titled “422 — Order Is Completed”A completed order has events.Completed present. All lines are either fulfilled or cancelled.
Cancellation is not applicable.
Request
PATCH /orders/v1/2000100002/cancelAuthorization: ******Ocp-Apim-Subscription-Key: <subscription_key>Response — 422 Unprocessable Entity
{ "code": "ERR_PROCESSING", "traceId": "TRACE000000000005:00000001", "type": "https://<store-url>/swagger#ProcessingError", "title": "Unprocessable Request", "status": 422, "detail": "Order cannot be cancelled in its current state.", "instance": "/orders/v1/2000100002", "extensions": {}}400 — Validation Error
Section titled “400 — Validation Error”Returned when orderId is empty or whitespace-only.
{ "errors": [ { "fieldName": "OrderId", "message": "OrderId cannot be null or empty." } ], "code": "ERR_VALIDATION_0001", "traceId": "TRACE000000000006:00000001", "type": "https://<store-url>/swagger#Validation", "title": "Validation Failed", "status": 400, "detail": "Some fields have validation errors", "instance": "/orders/v1/%20", "extensions": {}}401 — Unauthorized
Section titled “401 — Unauthorized”No response body. The request is missing or has an invalid Authorization header.
403 — Forbidden (no scope)
Section titled “403 — Forbidden (no scope)”No response body. The token is valid but does not include the order:write scope.
403 — Access Denied
Section titled “403 — Access Denied”Having order:write scope is necessary but not sufficient — the API also checks ownership.
An order is accessible to your token if your account matches either soldTo (the account the goods are billed to)
or placedBy (the account that placed the order). If neither matches, you receive ERR_ACCESS even with a valid,
scoped token. See the order ownership model for details.
Returned when the caller’s token is valid and scoped, but the order belongs to a different account.
{ "code": "ERR_ACCESS", "traceId": "TRACE000000000007:00000001", "type": "https://<store-url>/swagger#AccessError", "title": "Access Denied", "status": 403, "detail": "You do not have access to this order.", "instance": "/orders/v1/2000100008", "extensions": {}}404 — Not Found
Section titled “404 — Not Found”Returned when the orderId does not exist.
{ "code": "ERR_NOTFOUND", "traceId": "TRACE000000000008:00000001", "type": "https://<store-url>/swagger#NotFound", "title": "Not Found", "status": 404, "detail": "Order not found.", "instance": "/orders/v1/non-existing-id", "extensions": {}}