Working with Draft Orders

What this covers

All actions you can perform while an order is DRAFT in Order-based Checkout: create, update metadata & addresses, add/read/remove lines, and delete.

At a glance

  • All edits happen while the order is DRAFT.
  • After placement, the Commercial Order becomes immutable; progression is reflected by Logistic Orders.
  • Payment lock: when a card payment authorization is initiated (AUTHORIZATION_PENDING), the order is temporarily locked — its logistic status moves from DRAFT_ORDER to CREATED, blocking all modifications until the PSP responds. If the payment is refused, the order returns to DRAFT_ORDER and becomes editable again.
  • This page is header-level for the order; detailed line payloads are shown only where relevant to DRAFT actions.
  • The steps below (lines, addresses, sync, placement) can be performed in any order as long as the order is DRAFT. There is no mandatory sequence — just ensure all required data is present before placement.

Identifier types per endpoint

V2 endpoints use the REFERENCE (business reference) as the path parameter. V1 endpoints accept multiple id types via the idType query parameter.

EndpointVersionPath param typeidType query param
POST /v2/shop/commercial-ordersV2
GET /v1/shop/commercial-orders/{id}V1AnyDJUST_ID / EXTERNAL_ID / REFERENCE
PUT /v2/shop/commercial-orders/{id}V2REFERENCE onlyNot supported
PUT /v2/shop/commercial-orders/{id}/linesV2REFERENCE onlyNot supported
GET /v1/shop/commercial-orders/{id}/linesV1REFERENCE onlyFor filter params only
DELETE /v2/shop/commercial-orders/{id}/linesV2REFERENCE onlyNot supported
PUT /v2/shop/commercial-orders/{id}/shipping-informationV2REFERENCE onlyNot supported
PUT /v2/shop/commercial-orders/{id}/billing-informationV2REFERENCE onlyNot supported
PUT /v1/shop/commercial-orders/{id}/syncV1REFERENCE onlyNot supported
PUT /v2/shop/commercial-orders/{id}/createdV2REFERENCE onlyNot supported
DELETE /v2/shop/commercial-orders/{id}V2REFERENCE onlyNot supported
⚠️

Warning: V2 endpoints only accept REFERENCE as path parameter. Passing a DJUST_ID or EXTERNAL_ID will result in a 404. The only V1 endpoint that supports idType for the path parameter is GET /v1/shop/commercial-orders/{id}.


📑 Quick navigation


🆕 Create a DRAFT order

Create an empty DRAFT order that becomes the single source of truth for the checkout session.

OperationId: ORDER-108

Endpoint: POST /v2/shop/commercial-orders


Behavior

  • Initializes header-level fields (identifiers, scope, timestamps).
  • May store snapshots for account/user.
  • Does not pre-create lines by default.
  • Supports order-level custom fields at creation.

Feature flag: required only when sourceType=OPERATION (flag OPERATIONS). Not required for QUOTE.


{
  "sourceType": "OPERATION | QUOTE",
  "sourceId": "string",
  "isFull": true,
	"customFields": [
    { 
      "customFieldId": "string",
      "customFieldValue": "string" 
		}
	],
	"customFieldIdType": "DJUST_ID | EXTERNAL_ID"
}

Default:

  • customFieldIdType = "EXTERNAL_ID".
  • When a source is provided, isFull defaults to true.

Response : 201 Created with the id and reference of the created order.


Line selection

  • OPERATION
    • isFull=true: add all eligible & visible Operation lines.
    • isFull=false: create empty order linked to the Operation; add lines later via ORDER-150.
  • QUOTE
    • Only isFull=true is supported (forced).
    • Attempt all quote lines; stock check only at init. Out-of-stock lines are ignored.
    • The created order starts at DRAFT_ORDER_ON_HOLD and is non-editable: ORDER-150, ORDER-213, ORDER-215 are rejected. Payment via PAY-101 is authorized; on success the order transitions to CREATED.

Flows

Standard creation

flowchart LR
  A[Request to create order] --> H[Headers & scope check<br>Account • Store • Store-view]
  H --> INIT[Initialize Draft<br>header fields • snapshots]
  INIT --> RES[Return Draft Order]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

  class A,H,INIT sys
  class RES ok

  style A rx:8,ry:8
  style H rx:8,ry:8
  style INIT rx:8,ry:8
  style RES rx:8,ry:8

From QUOTE creation

flowchart LR
  IN[POST /v2/shop/commercial-orders<br>sourceType=QUOTE] --> AUTH[Auth & headers<br>dj-client=ACCOUNT - api-key]
  AUTH --> STORE[Resolve effective store<br>dj-store or tenant default]
  STORE --> ATT[Check store attachment<br>caller attached?]
  ATT -->|No| ERR403S[403 F-E-030]
  ATT -->|Yes| OWN[Check quote ownership<br>same account?]
  OWN -->|No| ERR403O[403 F-E-030]
  OWN -->|Yes| QST[Check quote status<br>WAITING_FOR_CUSTOMER & not expired]
  QST -->|No| ERR422S[422 F-E-040]
  QST --> LINES[Collect quote lines<br>stock check only]
  LINES --> NONE[No eligible line?]
  NONE -->|Yes| ERR422E[422 F-E-039]
  NONE -->|No| CREATE[Create Commercial Order<br>add eligible quote lines]
  CREATE --> OUT[201 Created]

  %% Styles
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,AUTH,STORE,ATT,OWN,QST,LINES,NONE sys
  class CREATE,OUT ok
  class ERR403S,ERR403O,ERR422S,ERR422E stop

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style STORE rx:8,ry:8
  style ATT rx:8,ry:8
  style OWN rx:8,ry:8
  style QST rx:8,ry:8
  style LINES rx:8,ry:8
  style NONE rx:8,ry:8
  style CREATE rx:8,ry:8
  style OUT rx:8,ry:8
  style ERR403S rx:8,ry:8
  style ERR403O rx:8,ry:8
  style ERR422S rx:8,ry:8
  style ERR422E rx:8,ry:8

📘 Read a draft order

OperationId: ORDER-500

Endpoint: GET /v1/shop/commercial-orders/{commercialOrderId}


Path: {commercialOrderId}is the order identifier. In Order-based Checkout, using the business reference is recommended; if your tenant supports multiple id kinds on this route, add?idType=REFERENCE.


Query parameters

  • idType (optional) - DJUST_ID | EXTERNAL_ID | REFERENCE. Use when passing a non-default id kind.

Response (summary)

Header-level data only: identifiers, timestamps, orderLogisticPrices (aggregates), productCount, lineCount, account/user snapshots, and optional source { sourceType, sourceId }.

Lines are not included — use Read lines - (ORDER-561).


Example

GET /v1/shop/commercial-orders/FO-2025-000123?idType=REFERENCE

Resolution flow

flowchart LR
  IN[GET order] --> AUTH[Auth & headers<br>dj-client=ACCOUNT - api-key]
  AUTH --> SCOPE[Resolve effective scope<br>store / store-view]
  SCOPE --> RID[Resolve id by idType<br>DJUST_ID - EXTERNAL_ID - REFERENCE]
  RID --> FIND[Load Commercial Order<br>header only]
  FIND --> OUT[200 OK<br>order header]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

  class IN,AUTH,SCOPE,RID,FIND sys
  class OUT ok

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style SCOPE rx:8,ry:8
  style RID rx:8,ry:8
  style FIND rx:8,ry:8
  style OUT rx:8,ry:8

✏️ Update metadata (custom fields)

Edit your own model with custom fields on a DRAFT order.

OperationId: ORDER-222

Endpoint: PUT /v2/shop/commercial-orders/{commercialOrderId}


Rules

  • Only DRAFT is editable. If the order is in CREATED status (payment authorization in progress), the update is rejected.
  • Some fields are immutable (e.g., Order ID, creation timestamps).
  • Stores and store-views must remain compatible with the buyer context.

Path parameter

  • {commercialOrderId} is the business reference (REFERENCE).
  • No idType query; do not accept other id kinds (external/internal IDs).

{
	"customFields": [
    { 
      "customFieldId": "string",
      "customFieldValue": "string" 
		}
	],
	"customFieldIdType": "DJUST_ID | EXTERNAL_ID"
}

Default: customFieldIdType = "EXTERNAL_ID".


➕ Add lines

Add or augment product lines on the DRAFT order.

OperationId: ORDER-150

Endpoint: PUT /v2/shop/commercial-orders/{commercialOrderId}/lines


Path: {commercialOrderId} is a REFERENCE (business ref only; no internal/external IDs).

{
	"lineType": "OFFER_PRICE",             // "OFFER_PRICE" | "PRODUCT_VARIANT" (default: OFFER_PRICE)
	"lineIdType": "EXTERNAL_ID",           // "EXTERNAL_ID" | "DJUST_ID" (today: EXTERNAL_ID only)
	"customFieldIdType": "EXTERNAL_ID",    // "EXTERNAL_ID" | "DJUST_ID" (default: EXTERNAL_ID)
	"updateOrderCommercialLines": [
		{
			"id": "123456",                    // offer price id or variant id per lineType
			"quantity": 10,
			"updateAction": "ADD_QUANTITY",    // "ADD_QUANTITY" | "REMOVE_QUANTITY" | "REPLACE_QUANTITY"
			"customFields": [
        { 
          "customFieldId": "string", 
          "customFieldValue": "string" 
				}
			]
		}
  ]
}

Defaults

  • lineType: OFFER_PRICE
  • lineIdType: EXTERNAL_ID
  • Today only EXTERNAL_ID is supported for lineIdType.

Rules

  • Order must be DRAFT_ORDER. If the order is in CREATED status (payment authorization in progress), the call is rejected.
  • Up to 1000 lines per call.
  • Quantity semantics via updateAction:
    • ADD_QUANTITY: add to existing.
    • REMOVE_QUANTITY: subtract from existing.
    • REPLACE_QUANTITY: set new value (≥ 0).
  • Reject or warn on invalid combinations:
    • Unknown lineType / lineIdType / updateAction.
    • updateAction provided but missing quantity, or quantity provided without updateAction.
  • Constraints: negative qty; > stock; > max orderable; < min orderable; not multiple of pack.
  • Non-owner edits: allowed when the user belongs to the same Account and holds permission ORDER_UPDATE_LINES_ON_ALL_ACCOUNT.

Validation pipeline

flowchart LR
  IN[Incoming lines<br>id • qty • updateAction] --> TYPE[lineType / lineIdType<br>resolve targets]
  TYPE --> VIS[Visibility check<br>Catalog Views]
  VIS --> QTY[Quantity rules<br>min • max • pack • stock]
  QTY --> ACT[Apply updateAction<br>ADD / REMOVE / REPLACE]
  ACT --> LIM[Limit check<br>≤ 1000 lines]
  LIM --> OUT[Merge or create lines]

	classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
	classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;

	class IN,TYPE,VIS,QTY,ACT,LIM sys
  class OUT ok

  style IN rx:8,ry:8
  style TYPE rx:8,ry:8
  style VIS rx:8,ry:8
  style QTY rx:8,ry:8
  style ACT rx:8,ry:8
  style LIM rx:8,ry:8
  style OUT rx:8,ry:8

Source-based starts: if the Draft was initialized from a Quote or an Operation, lines are re-validated at add time and again at placement.


📖 Read lines

Retrieve the current lines of the DRAFT order for display and checks.

OperationId: ORDER-561

Endpoint: GET /v1/shop/commercial-orders/{commercialOrderId}/lines


Path param: {commercialOrderId} is a REFERENCE (business reference only; not internal/external IDs).

Query parameters

  • currency (required) — currency for computing/returning totals on lines.
  • supplierIds (optional) — filter by supplier id(s).
  • productVariantIds (optional) — filter by variant id(s).
  • offerPriceIds (optional) — filter by offer price id(s).
  • idType (optional)DJUST_ID or EXTERNAL_ID; applies only to the filter ids above.
    • (The path param remains a REFERENCE; idType does not affect it.)

Response

  • Paginated list of Commercial Order lines.
  • Line items reuse the existing Logistic Order line model (same fields & semantics).
  • Includes monetary fields expressed in the requested currency.

Notes

  • Expect standard pagination where applicable.
  • Lines reflect server-evaluated visibility and pricing for the buyer context.
  • Avoid assuming totals from the lines list; use the order’s aggregated prices for consistency.

➖ Remove lines

Remove one or more lines from a DRAFT order.

OperationId: ORDER-350

Endpoint: DELETE /v2/shop/commercial-orders/{commercialOrderId}/lines


Path: {commercialOrderId} is a REFERENCE (business reference only).

{
  "lines": [
    { 
      "offerPriceId": "string" 
		}
	]
}

Rules

  • Order must be DRAFT_ORDER. If the order is in CREATED status (payment authorization in progress), the call is rejected.
  • The caller must act within the same Account as the order.
  • Non-owner deletion allowed if the user has ORDER_UPDATE_LINES_ON_ALL_ACCOUNT and belongs to the same Account.
  • Cascade: if all lines of a child Logistic Order are removed, that Logistic Order (and its linked objects) is deleted.
  • Path param is REFERENCE-only.

Decision flow

flowchart LR
  IN[DELETE order lines] --> AUTH[Auth & headers<br>dj-client=ACCOUNT • api-key]
  AUTH --> SCOPE[Account scope check]
  SCOPE --> PERM[Right check<br>OWNER or ORDER_UPDATE_LINES_ON_ALL_ACCOUNT]
  PERM --> STATE[Order is DRAFT_ORDER?]
  STATE -->|Yes| APPLY[Delete requested lines<br>cascade delete empty Logistics]
  STATE -->|No| ERR400[400 F-E-028]
  APPLY --> OK[204 No Content]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,AUTH,SCOPE,PERM,STATE sys
  class APPLY,OK ok
  class ERR400 stop

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style SCOPE rx:8,ry:8
  style PERM rx:8,ry:8
  style STATE rx:8,ry:8
  style APPLY rx:8,ry:8
  style OK rx:8,ry:8
  style ERR400 rx:8,ry:8

📦 Update shipping information

Update the shipping information of a Commercial Order during checkout.

The update is applied to the order and to all linked Logistic Orders.

OperationId: ORDER-215

Endpoint: PUT /v2/shop/commercial-orders/{commercialOrderId}/shipping-information


Path: {commercialOrderId} is a REFERENCE (business reference only).


Request body

{
  "shippingAddressId": "EXT-ADDR-001",
  "shippingType": "EXPRESS"
}
  • shippingAddressId - external id (typed as shipping) of a valid shipping address.
  • shippingType - free string indicating delivery mode (e.g., STANDARD, EXPRESS, PICKUP).

Both fields are required.

⚠️

The order must be DRAFT_ORDER. If the order is in CREATED status (payment authorization in progress), the call is rejected.


Flow

flowchart LR
  IN[PUT shipping-information] --> HDR[Headers & auth]
  HDR --> RID[Resolve order by REFERENCE id]
  RID --> VAL[Validate body<br>external shippingAddressId - shippingType]
  VAL -->|Invalid| ERR404[404 Not Found]
  VAL -->|OK| APPLY[Apply to order<br>+ all linked Logistic Orders]
  APPLY --> OUT[204 No Content]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,HDR,RID,VAL,APPLY sys
  class OUT ok
  class ERR404 stop

  style IN rx:8,ry:8
  style HDR rx:8,ry:8
  style RID rx:8,ry:8
  style VAL rx:8,ry:8
  style APPLY rx:8,ry:8
  style OUT rx:8,ry:8
  style ERR404 rx:8,ry:8

🧾 Update billing information

Update the billing information of a Commercial Order during checkout.

The update is applied to the order and to all linked Logistic Orders.

OperationId: ORDER-213

Endpoint: PUT /v2/shop/commercial-orders/{commercialOrderId}/billing-information

Path: {commercialOrderId} is a REFERENCE (business reference only).

Request body

{
  "billingAddressId": "EXT-BILLING-001"
}
  • billingAddressId - external id (typed as billing) of a valid billing address.
⚠️

The order must be DRAFT_ORDER. If the order is in CREATED status (payment authorization in progress), the call is rejected.

Flow

flowchart LR
  IN[PUT billing-information] --> HDR[Headers & auth]
  HDR --> RID[Resolve order by REFERENCE id]
  RID --> VAL[Validate body<br>external billingAddressId - typed as billing]
  VAL -->|Invalid| ERR404[404 Not Found]
  VAL -->|OK| APPLY[Apply to order<br>+ all linked Logistic Orders]
  APPLY --> OUT[204 No Content]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,HDR,RID,VAL,APPLY sys
  class OUT ok
  class ERR404 stop

  style IN rx:8,ry:8
  style HDR rx:8,ry:8
  style RID rx:8,ry:8
  style VAL rx:8,ry:8
  style APPLY rx:8,ry:8
  style OUT rx:8,ry:8
  style ERR404 rx:8,ry:8

🔄 Synchronize the order

Reconcile all existing lines of a DRAFT order with the current DJUST catalog: prices, stock, quantity rules, visibility, and custom fields.

A draft order acts as the functional equivalent of a cart. Between creation and placement, catalog data can change. Sync ensures the order reflects the latest reality.

OperationId: ORDER-223

Endpoint: PUT /v1/shop/commercial-orders/{commercialOrderId}/sync


When to call sync

  • On order display - every time the buyer opens or returns to the draft order view, to ensure displayed prices and availability are accurate.
  • After editing lines - after adding, removing, or changing quantities, to revalidate the full order.
  • Before placement - as a final coherence check before ORDER-212.

Behavior

  • Validates all existing lines against persisted DJUST data (no external API involved).
  • Returns an array of warnings, each with a blocked flag:
    • blocked: true - blocking: the order is not updated. All warnings are returned for the caller to fix.
    • blocked: false - informational: the order is updated. The warning reports a change that was applied automatically (e.g. price update).
  • If at least one blocking warning exists, no modification is applied to the order.
  • On success, lastSyncAt is updated on the order.
  • Sync does not add or remove lines - it only validates and updates existing ones.

Rules

  • Order must be DRAFT and not yet validated (validatedAt empty).
  • Only dj-client: ACCOUNT is accepted.
  • Caller must be the order owner or hold the required edit permissions.
  • Path param {commercialOrderId} is a REFERENCE (business reference only).

Decision flow

flowchart LR
  IN[PUT sync] --> AUTH[Auth & headers<br>dj-client=ACCOUNT • api-key]
  AUTH --> STATE[Order is DRAFT<br>& not validated?]
  STATE -->|No| ERR409[409 F-E-028]
  STATE -->|Yes| EVAL[Evaluate all lines<br>prices • stock • qty • visibility • CFs]
  EVAL --> BLK{Blocking<br>warnings?}
  BLK -->|Yes| NOOP[Order unchanged<br>return all warnings]
  BLK -->|No| APPLY[Update order<br>set lastSyncAt]
  APPLY --> OUT[200 OK<br>informational warnings]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;
  classDef decision fill:#fff4e5,stroke:#f59e0b,stroke-width:2px,color:#7a3e00;

  class IN,AUTH,STATE,EVAL sys
  class BLK decision
  class APPLY,OUT ok
  class ERR409,NOOP stop

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style STATE rx:8,ry:8
  style EVAL rx:8,ry:8
  style BLK rx:8,ry:8
  style APPLY rx:8,ry:8
  style OUT rx:8,ry:8
  style ERR409 rx:8,ry:8
  style NOOP rx:8,ry:8

For the complete list of blocking/informational warning codes and integration patterns, see Synchronize a Draft Order.


✅ Place (validate) the order

Validate a DRAFT_ORDER Commercial Order and transition it to placed. This action transitions all child Logistic Orders to CREATED for OMS processing, locks further edits on the Commercial Order, and sets validatedAt.

Note: The CREATED status on Logistic Orders can also be reached temporarily during a payment authorization flow (see At a glance). In that context, CREATED acts as a lock until the PSP responds. Placement via ORDER-212 is the definitive transition that freezes the Commercial Order.

OperationId: ORDER-212

Endpoint: PUT /v2/shop/commercial-orders/{commercialOrderId}/created


Pre-checks (high level)

  • The order must be DRAFT_ORDER, owned and in scope for the caller. Validation enforces typical business constraints:
  • ORDER_VALIDATE right: the caller must hold the ORDER_VALIDATE permission. When set to false, the user cannot validate their own orders. If combined with ORDER_VALIDATE_ON_ALL_ACCOUNT, the user can only validate orders of other users in the same account. If the right is missing, the endpoint returns 403 — F-E-030.
  • Activation state: product, variant, offer inventory, offer price, and supplier are ACTIVE.
  • Quantity & stock: requested qty > 0; within min/max; respects pack multiple; stock ≥ requested.
  • Addresses & shipping: shipping and billing addresses present; shipping method/type present when required.
  • Custom fields: mandatory role-based fields (e.g., product/shipping roles) are filled when roles are enabled.
  • Payment readiness (if applicable): a PSP is configured or the “no-payment” mode is allowed.

What happens

  1. Final visibility/stock checks on lines.
  2. Split into child Logistic Orders per OMS rules (supplier/warehouse, etc.).
  3. Set each child Logistic Order to CREATED (ready for OMS).
  4. Freeze the Commercial Order (immutable) and set validatedAt.
  5. Recompute aggregates on the Commercial Order (orderLogisticPrices, productCount, lineCount).

Decision flow

flowchart LR
  IN[Place order - ORDER-212] --> AUTH[Auth & headers<br>dj-client=ACCOUNT • api-key]
  AUTH --> PERM[ORDER_VALIDATE right check]
  PERM -->|No| ERR403[403 F-E-030]
  PERM -->|Yes| SCOPE[Scope & store check]
  SCOPE --> STATE[Order is DRAFT_ORDER?]
  STATE -->|No| ERR400[400 Not in draft]
  STATE -->|Yes| REQ[Required data present?<br>addresses • shipping • mandatory CFs]
  REQ -->|No| ERR422A[422 Missing/invalid fields]
  REQ -->|Yes| LNS[Lines valid?<br>active objects • qty bounds • pack • stock]
  LNS -->|No| ERR422L[422 Line validation]
  LNS -->|Yes| SPLIT[Create child Logistic Orders]
  SPLIT --> SET[Set child LOs to CREATED]
  SET --> LOCK[Lock Commercial Order<br>set validatedAt • recompute aggregates]
  LOCK --> OUT[Order placed]

  %% ---------- Styles ----------
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,AUTH,PERM,SCOPE,STATE,REQ,LNS,SPLIT,SET,LOCK sys
  class OUT ok
  class ERR403,ERR400,ERR422A,ERR422L stop

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style PERM rx:8,ry:8
  style SCOPE rx:8,ry:8
  style STATE rx:8,ry:8
  style REQ rx:8,ry:8
  style LNS rx:8,ry:8
  style SPLIT rx:8,ry:8
  style SET rx:8,ry:8
  style LOCK rx:8,ry:8
  style OUT rx:8,ry:8
  style ERR403 rx:8,ry:8
  style ERR400 rx:8,ry:8
  style ERR422A rx:8,ry:8
  style ERR422L rx:8,ry:8

🔒 Order lock during payment authorization

When a payment is initiated via PAY-101, the order is temporarily locked to prevent modifications while the payment authorization is being processed.

⚠️

Warning: Initiating a payment also requires the ORDER_VALIDATE right. If the customer user does not hold ORDER_VALIDATE, the call to PAY-101 returns 403 — F-E-030.

What happens

  1. When the payment status transitions to AUTHORIZATION_PENDING, the order's logistic status automatically transitions from DRAFT_ORDER to CREATED.
  2. While in CREATED, the order is read-only — all modification endpoints are rejected (lines, addresses, shipping, billing, custom fields, delete).
  3. Depending on the authorization result:
    • Authorized — the order remains in CREATED and proceeds to WAITING_SUPPLIER_APPROVAL (standard flow).
    • Refused — the order transitions back to DRAFT_ORDER, allowing the customer to correct the order (update lines, addresses, etc.) and retry payment.
⚠️

Warning: This means the CREATED status can appear temporarily during checkout, before the order is fully placed. Do not treat CREATED as a final state — it may revert to DRAFT_ORDER if the payment is refused.


Affected endpoints

The following endpoints reject calls when the order is in CREATED:

EndpointOperationIdBehavior
Add linesORDER-150Rejected
Remove linesORDER-350Rejected
Update shippingORDER-215Rejected
Update billingORDER-213Rejected
Update custom fieldsORDER-222Rejected
Delete orderORDER-300Rejected
Read orderORDER-500Allowed (read-only)
Read linesORDER-561Allowed (read-only)
Sync orderORDER-223Rejected

Status flow

flowchart LR
  %% Styles (Readme)
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;
  classDef decision fill:#fff4e5,stroke:#f59e0b,stroke-width:2px,color:#7a3e00;
  classDef update fill:#e0f7fa,stroke:#06b6d4,stroke-width:2px,color:#0c4a6e;

  A["📝 DRAFT_ORDER<br>editable"]:::sys
  B["💳 PAY-101 called<br>AUTHORIZATION_PENDING"]:::update
  C["🔒 CREATED<br>read-only"]:::update
  D{{"📩 Authorization<br>result"}}:::decision
  E["✅ WAITING_SUPPLIER_APPROVAL<br>standard flow continues"]:::ok
  F["📝 DRAFT_ORDER<br>customer can retry"]:::stop

  A --> B --> C --> D
  D -->|Authorized| E
  D -->|Refused| F

  style A rx:8,ry:8
  style B rx:8,ry:8
  style C rx:8,ry:8
  style E rx:8,ry:8
  style F rx:8,ry:8

🗑️ Delete the order

Deletion is allowed only in DRAFT and only when no blocking links exist (e.g., payment intents, shipments, or other downstream objects).

OperationId: ORDER-300

Endpoint: DELETE /v2/shop/commercial-orders/{commercialOrderId}


Path: {commercialOrderId} is a REFERENCE (business reference only; do not accept internal/external IDs).


Rules

  • Requires permission CHECKOUT_ORDER_DELETE.
  • The order must be DRAFT_ORDER, e.g. all child Logistic Orders must also be DRAFT_ORDER.
  • Caller must be in the same Account (buyer scope).
  • Cascade: deletes the Commercial Order and its child Logistic Orders.
  • Path param is REFERENCE-only (do not accept internal/external ids).

Decision flow

flowchart LR
  IN[DELETE order] --> AUTH[Auth & headers<br>dj-client=ACCOUNT • api-key]
  AUTH --> PERM[Check right<br>CHECKOUT_ORDER_DELETE]
  PERM --> SCOPE[Account scope check]
  SCOPE --> DRAFT[Order status is DRAFT_ORDER<br>& all child Logistics are DRAFT_ORDER?]
  DRAFT -->|Yes| DEL[Delete Commercial Order<br>& child Logistic Orders]
  DRAFT -->|No| ERR400[400 F-E-028]

  %% Styles
  classDef sys fill:#f2f4f7,stroke:#475569,stroke-width:2px,color:#111827;
  classDef ok fill:#ecfdf5,stroke:#10b981,stroke-width:2px,color:#064e3b;
  classDef stop fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

  class IN,AUTH,PERM,SCOPE,DRAFT sys
  class DEL ok
  class ERR400 stop

  style IN rx:8,ry:8
  style AUTH rx:8,ry:8
  style PERM rx:8,ry:8
  style SCOPE rx:8,ry:8
  style DRAFT rx:8,ry:8
  style DEL rx:8,ry:8
  style ERR400 rx:8,ry:8

🧯 Troubleshooting

SymptomLikely causeFix
Cannot update orderOrder not in DRAFTKeep edits in DRAFT; after placement it is immutable
Cannot modify order (lines, addresses, metadata) during checkoutPayment authorization is in progress — the order is temporarily in CREATED statusWait for the PSP response. If the payment is refused, the order returns to DRAFT_ORDER and becomes editable again.
Some items cannot be addedNot visible for the AccountAdjust Catalog Views or choose eligible items
Quantity rejectedMin / Max / Pack constraintRespect constraints; adjust quantity
Delete rejectedBlocking links existRemove links first or keep the DRAFT for audit
Can’t place the orderMissing addresses/shipping, inactive objects, quantity/pack/stock constraints, or required custom fields missing.Complete mandatory fields; ensure products/suppliers/prices are ACTIVE; fix quantities; ensure stock.
Order already placedOrder is no longer in DRAFT (already validated).Use read-only endpoints; amendments must follow post-placement flows.
Stale prices on commercial order displaySync not called when buyer reopened the draft orderCall ORDER-223 on every commercial order page load
Sync returns blocking warningsInactive product/offer/supplier, stock insufficient, or quantity rule violationReview each warning's code and detail; fix or remove affected lines via ORDER-150/ORDER-350, then retry

🔗 API quicklinks

Also useful