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.
  • This page is header-level for the order; detailed line payloads are shown only where relevant to DRAFT actions.

📑 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.

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.
  • 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.
  • 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.
  • 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.


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.

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

✅ 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.

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:
  • 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 --> 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,SCOPE,STATE,REQ,LNS,SPLIT,SET,LOCK sys
  class OUT ok
  class ERR400,ERR422A,ERR422L stop

  style IN rx:8,ry:8
  style AUTH 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 ERR400 rx:8,ry:8
  style ERR422A rx:8,ry:8
  style ERR422L 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
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.

🔗 API quicklinks

Also useful