4WS Suite
Home
API Reference
API Reference
  • Data mangement API
  • Documents API
Home
API Reference
API Reference
  • Data mangement API
  • Documents API
Fourwayshop
  1. Orchestrated Orders
  • Document Manager
    • Orders
      • Save Sale Order
      • Save Return Order
    • Orchestrated Orders
      • Orchestrated Order
        POST
      • Orchestrated Return order
        POST
      • Orchestrated Update order
        POST
      • Orchestrated Sale Order: Cancel Purchased Quantities
        POST
    • Cart
      • Cart Validation
      • Cart Full Validation
    • Sales
      • Save receipt
      • Salve only Order
      • Replace or update sale
      • Get last digital order
    • Warehouse
      • Save Entry from supplier
      • Save Transfer document
      • Save Free Entry
    • Purchase
      • Save Purchase
    • Get Document
      GET
    • Update Document External Reference & Note
      POST
  • Customer
    • Get Customer
      GET
    • Set Customer Opt-in
      POST
  • Loyalty vouchers
    • Get customer loyalty vouchers
      GET
    • Get loyalty vouchers at a time interval
      GET
    • Get last loyalty vouchers
      GET
  • Giftcard
    • Get Giftcard
      GET
    • Update Giftcard
      POST
    • Generate Gift Card Barcode
      POST
    • Gift Card PDF Generation
      POST
  • Stock
    • Get Stock
      POST
    • Get last stock
      GET
    • Insert Stock
      POST
  1. Orchestrated Orders

Orchestrated Sale Order: Cancel Purchased Quantities

POST
/api
Last modified:2026-10-16 13:23:06
Available from release:3.2.1

Cancel Purchased Quantities on a Sales Order#

This API allows an external system to request the cancellation (partial or total) of the quantities purchased for one or more order rows belonging to a sales order that originated outside of Four Way Shop and is currently orchestrated by the OMS. The caller submits, for each affected row, the residual quantity that should remain on the order after the cancellation. The OMS validates the request, applies the quantity reduction to the order, propagates the change to the fulfillment flow, and returns the updated state of the affected rows. Because order rows may already be engaged in downstream fulfillment steps (picking, shipment, invoicing, etc.), the operation is processed asynchronously: the synchronous response only acknowledges receipt of the request, while the actual outcome of the cancellation is delivered later through the callback URL supplied by the caller.
Only Click&Collect orders & use pickup-store stock only
This API is available only for Click&Collect orders whose orchestration configuration is set to use pickup-store stock only.
Orders configured to use network stock, non-Click&Collect orders, and manually managed orders are rejected during the synchronous validation phase with the corresponding error message (see Handled Errors).

Preconditions#

The sales order must already exist in the OMS and must have been created via the standard order intake process from the external channel.
The order must be in a state that allows quantity changes (i.e. it must not be fully invoiced, fully shipped, or already cancelled/closed).
Each rowId passed in the request must correspond to an existing, active row of the target order.
The requested quantity for each row must be lower than or equal to the quantity currently residual on that row (this API reduces quantities, it does not increase them).
The external system must have the necessary permissions and access to the document creation service, please refer to Authentication.
Callback Endpoint (External Client): The callback used by Four Way Shop to asynchronously notify the client of success/failure and to return the order ID must be handled (How Testing callback response).
Monitoring / Alerting System: Handling integration errors and retries logs and warnings, as reported in nBest Practices for Error Handling in External System.
The external system must provide a reachable callback URL able to receive the asynchronous outcome of the operation.

Main Success Scenario#

1.
The external system sends a POST request to Orchestrated Cancel order, passing the transactionId, the list of items (each with rowId and the new residual quantity), and the callback URL.
2.
The OMS authenticates the request and validates the payload against the preconditions (order existence, row existence, state, requested quantity, uniqueness of transactionId).
3.
The OMS synchronously responds with success: true and echoes the transactionId, acknowledging that the request has been accepted for processing.
4.
The OMS applies the quantity reduction to the order rows and propagates the change through the orchestrated fulfillment flow (e.g. adjusting picking/shipment quantities not yet processed).
5.
Once processing completes, the OMS invokes the caller's callback URL with the final outcome, reporting the updated (residual) quantity for each affected rowId.

Alternate Flows#

1.
Synchronous phase: the API Orchestrated Cancel order validates the request (format, cart/order existence, configuration). If validation passes, it immediately responds to the caller with { success, message }.
2.
Asynchronous phase: the actual cancellation procedure is executed, and the outcome is finally notified to the client by calling the URL passed in vo.callback, with body { success, transactionId, items, message }.
An error in phase 1 blocks the request immediately (the order is never cancelled). An error in phase 2, on the other hand, arrives later, via callback: the initial synchronous request had been accepted successfully, but the operation can still fail afterwards.
Synchronous errors#
Response: { success: false, message: "<message>" }.
MessageCondition
Invalid request: transactionId is mandatorytransactionId (cartId) missing from the body
Invalid request: items is mandatoryitems missing or empty
Invalid request: productId and quantity are mandatory for each iteman item without rowId or without quantity
Invalid request: duplicate rowId in itemstwo or more items with the same rowId
Document not found for passed transactionIdthe order does not exist or is cancelled
Invalid request: cart is not associated to any orderthe order does not exist or is cancelled
Invalid request: order not found for passed transactionIdthe linked order does not exist or is cancelled
Invalid request: order manually managedmanually managed order
Invalid request: order is not Click&Collectthe order is not click&Collect managed
Invalid request: orchestrationConfigId not found for orderthe order does not exist or is cancelled
Invalid request: order is configured to use network stockthe orchestration configuration does not exist, or is use network stock, not manageable by this API)
Invalid request: some rows are invalidthe number of order rows retrieved does not match the number of requested items (non-existent rowIds)
Invalid request: All rows must be of the same carta retrieved row belongs to an order different from the order
Invalid row: <rowId>the row is cancelled
Invalid request: Only products can be cancelledthe row is not of type PRODUCT (e.g. a service)
Invalid request: quantity to cancel is greater than available quantity for rowId: <rowId>quantityToCancel: <n> quantityAvailableToCancel: <n>the quantity requested for cancellation exceeds the quantity still cancellable (order quantity − already cancelled − already fulfilled/invoiced)
Asynchronous errors (via callback)#
Response sent to the callback URL: { success: false, transactionId, items, message }.
Business validation errors#
MessageInternal codeCondition
Invalid request: order not foundORDER_NOT_FOUNDthe order no longer exists or is cancelled
Invalid request: order manually managedORDER_NOT_ORCHESTRATEDthe order switched to manual management between the request and the processing
Invalid request: order is not Click&CollectORDER_NOT_CLICK_AND_COLLECTthe order is not click&Collect managed
Invalid request: row <rowId> not found in order <orderId>ROW_NOT_FOUNDthe requested row is no longer among the order's active rows
Invalid request: quantity to cancel is greater than available quantity for rowId: <rowId>. quantityToCancel: <n>, quantityAvailableToCancel: <n>—re-check of the quantity available for cancellation (may change compared to the synchronous check, e.g. due to concurrent cancellations/fulfillments)
Invalid request: not enough RDC rows to cancel for rowId: <rowId>. quantityToCancel: <n>, availableRDCRows: <n>—there are not enough RDC rows linked to the order row to cover the requested cancellation quantity

Callback Response#

Once the OMS has finished propagating the cancellation through the fulfillment flow, it calls back the URL provided in the request with a JSON payload describing the outcome for each affected row:
{
  "success": true,
  "transactionId": "6df90aa5-7598-4135-9e26-e7a7aa6f40c5",
  "items": [
    {
      "rowId": "c7667656-fc18-4d2b-a7c2-2129df32251f",
      "quantity": 1
    }
  ]
}
success: indicates whether the cancellation was ultimately applied.
transactionId: matches the transactionId of the order, allowing the caller to correlate the callback with the request that triggered it.
items: the list of affected rows, each reporting the rowId and the final residual quantity actually applied by the OMS (which may differ from the quantity originally requested, see Alternate Flows).

Sequence Diagram#

Code Examples in Node.js#

Sending the cancellation request
Handling the asynchronous callback (Express example)

Request

Query Params

Header Params

Body Params application/json

Example
{
    "transactionId": "5c4ae2f5-23da-47a6-b72e-c500a27ec88f",
    "items": [
        {
            "quantity": 2,
            "rowId": "a0895c80-90ba-423a-b5f3-98702f49e7df"
        }
    ],
    "callback": "https://lQrKKQBEKSaCqjWgmfHWGPRIUAuXVuI.jkssOryQbhzNG+sxF76PppFFCm+QkYEMFfWkXvu-1,.AVb"
}

Request Code Samples

Shell
JavaScript
Java
Swift
Go
PHP
Python
HTTP
C
C#
Objective-C
Ruby
OCaml
Dart
R
Request Request Example
Shell
JavaScript
Java
Swift
curl --location --globoff '/api?applicationId={{APPLICATION_ID}}&appId={{APPLICATION_ID}}&cmd=cancelOrder_v1' \
--header 'applicationId: {{APPLICATION_ID}}' \
--header 'appId: {{APPLICATION_ID}}' \
--header 'namespace: {{NAMESPACE}}' \
--header 'languageId: {{LANGUAGE}}' \
--header 'username: {{USERNAME}}' \
--header 'password: {{PASSWORD}}' \
--header 'companyId: {{COMPANY_ID}}' \
--header 'siteId: {{SITE_ID}}' \
--header 'loadRoles: Y' \
--header 'Content-Type: application/json' \
--data '{
    "transactionId": "5c4ae2f5-23da-47a6-b72e-c500a27ec88f",
    "items": [
        {
            "quantity": 2,
            "rowId": "a0895c80-90ba-423a-b5f3-98702f49e7df"
        }
    ],
    "callback": "https://lQrKKQBEKSaCqjWgmfHWGPRIUAuXVuI.jkssOryQbhzNG+sxF76PppFFCm+QkYEMFfWkXvu-1,.AVb"
}'

Responses

🟢200Save cart - success
application/json
Bodyapplication/json

Example
{
    "success": true
}
🟠422Unique constraint error
Modified at 2026-10-16 13:23:06
Previous
Orchestrated Update order
Next
Cart Validation
Built with