Synchronize a Draft Order

Introduction

A commercial order in DRAFT status is editable and evolves until placement. Between the moment it is created and the moment it is placed, catalog data can change: prices may be updated, stock levels may decrease, products may become inactive, or quantity rules may evolve.

The sync endpoint reconciles a draft order with the current state of the DJUST catalog and returns a detailed list of warnings - either blocking (the order cannot be updated) or informational (the order was updated, but differences were detected).

When to sync

Synchronization is not limited to a pre-placement check. It should be called whenever the order needs to reflect the latest catalog reality:

  • On order display - When a buyer reopens a draft order, call sync to refresh prices, stock, and availability before rendering the page. This ensures the buyer always sees accurate, up-to-date information.
  • After a period of inactivity - If a draft order has been idle for hours or days, catalog data may have drifted significantly.
  • Before placement - As a final validation step before calling the placement endpoint (ORDER-212), to catch any last-minute changes.
  • After editing lines - When lines have been added or quantities changed, sync ensures the full order remains coherent.
✅

Tip: Synchronization works with DJUST as the single source of truth (standard mode). No external pricing or stock system is required.


Key Concepts

Standard Mode

In standard mode, synchronization relies exclusively on data persisted in DJUST:

  • Catalog: product and variant activation status, catalog view eligibility for the buyer's context
  • Offer prices: price values, eligibility per account or account group
  • Stock / availability: offer inventory levels
  • Quantity rules: minimum, maximum, item per pack
  • Custom fields: offer-level and order-level custom field validity

No external real-time pricing (RTP) source is involved. Everything described on this page applies to the standard mode; tenants running Real-Time Pricing differ on several points, gathered in Real-Time Pricing tenants.

What Gets Rewritten, and From Where

Every value written on a synchronized line comes from the offer price the line already points to, and from its offer, product variant and product:

Data rewritten on the lineSource
Unit price (the price tier matching the line quantity, discounted price when one is set) and item per packOffer price
Currency, packing type, quantity per item, minimum and maximum order quantitiesOffer
Product and shipping tax rates and codesOffer custom fields carrying the tax roles
Amounts excluding and including taxes, tax amounts and totalsRecomputed with the tax calculation mode and rounding of the logistic order
Product snapshot: SKU, external ID, names, descriptions, brand, unit, tags, attributes, classification category and finest navigation categoryProduct
Variant snapshot: SKU, external ID, names, descriptions, EAN, MPN and attributesProduct variant
Offer custom field snapshotActive custom fields of the offer

On the order itself, the sync writes the synchronization timestamp; on each logistic order, the totals, the line count and the product count are recomputed from its lines. Shipping fees are recomputed only when the shipping matrix is active.

What Is Never Changed

  • The set of lines — no line is added or removed, and each line keeps its offer price, even when another price now applies to the account.
  • The line quantity.
  • The line custom fields — their values are kept as they are, including the value of a custom field deactivated since.
  • The order status, the customer user and customer account snapshots, the supplier and the addresses.
📘

Note: Since 3.139, the standard mode no longer rewrites the line custom fields with their own values. A line carrying a deactivated custom field is therefore synchronized without raising any warning for it.

Catalog View Eligibility

Each order line is verified against the catalog views assigned to the customer user. If a product has been removed from a catalog view, or if the buyer's catalog view scope has changed, the product is flagged with a blocking warning (F-W-015).

This same eligibility check is also enforced when adding a product to an order (add-to-cart). A product that is not visible in the buyer's current catalog view context cannot be added to a commercial order.

⚠️

Warning: A product that was previously valid may become ineligible after a catalog view configuration change. Always call sync before placement to catch these cases.

Blocking vs. Informational Warnings

Each warning returned by the sync endpoint carries a blocked flag:

TypeblockedBehavior
BlockingtrueThe line is left untouched: not corrected, not deleted, not partially written. The other lines of the same order are synchronized normally.
InformationalfalseThe line is updated. Warnings notify the caller about changes that were automatically applied (e.g. price update, quantity adjustment).
⚠️

Warning: A blocking warning stops the synchronization of its own line only. The call fails with a 400 solely when no line survives — see Error handling.

Warning Structure

Each warning in the response array contains:

{
  "id": "OFFP-EXT-00042",
  "code": "F-W-018",
  "blocked": true,
  "detail": "Requested quantity is lower than the minimum order quantity.",
  "changes": [
    {
      "field": "quantity",
      "previousValue": "2",
      "newValue": "5"
    }
  ]
}
FieldDescription
idExternal identifier of the offer price concerned
codeWarning code (see Error / Warning codes)
blockedtrue if blocking, false if informational
detailHuman-readable description of the issue
changes(optional) Array of before/after value differences. Each entry contains field (string), previousValue (string), and newValue (string). Present only when a meaningful value comparison applies. Absent for existence, activation, or eligibility warnings.

How to read changes depending on the warning type:

  • Informational (blocked: false): previousValue is the old value on the order line, newValue is the new value that was applied by the sync.
  • Blocking (blocked: true): previousValue is the current value on the order line, newValue is the constraint or limit that the line violates (e.g. the minimum order quantity). No change is applied.

Preconditions

Before calling the sync endpoint, ensure:

  • The commercial order has not been validated (validatedAt must be empty)
  • The order is in a modifiable state (DRAFT)
  • The order was created in an Order-based Checkout context
  • The caller is either the order owner or has the required permissions to edit order lines

If any precondition is not met, the sync is rejected with an error response (see Error handling).


API Reference

Endpoint

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

operationId: ORDER-223

Path Parameters

ParameterTypeDescription
commercialOrderIdstringCommercial order identifier (REFERENCE)

Headers

HeaderRequiredDescription
dj-clientYesMust be ACCOUNT
dj-api-keyYesAPI key
dj-storeNoStore context
dj-store-viewNoStore view context
⚠️

Warning: Only dj-client: ACCOUNT is accepted on this endpoint.

Request Body

No request body. The sync applies to all existing lines on the order.

Response

200 OK - Returns an array of warnings (may be empty if everything is up to date):

[
  {
    "id": "OFFP-EXT-00042",
    "code": "F-W-014",
    "blocked": true,
    "detail": "The product variant with id PV-00042 is inactive."
  },
  {
    "id": "OFFP-EXT-00099",
    "code": "F-W-018",
    "blocked": true,
    "detail": "Requested quantity is lower than the minimum order quantity.",
    "changes": [
      {
        "field": "quantity",
        "previousValue": "2",
        "newValue": "5"
      }
    ]
  },
  {
    "id": "OFFP-EXT-00110",
    "code": "F-W-026",
    "blocked": false,
    "detail": "Unit price has been updated.",
    "changes": [
      {
        "field": "unitPrice",
        "previousValue": "12.50",
        "newValue": "13.20"
      }
    ]
  }
]

When the response contains only non-blocking warnings (or no warnings at all), the order has been updated successfully. The lastSyncAt timestamp is set on the order.

📘

Note: The warnings report a subset of what changes, not all of it. Every other price field (amounts excluding taxes, tax amounts, totals, packing information, order quantity bounds) and every snapshot is recalculated without any warning. An empty response therefore does not mean that nothing changed — read the lines back with ORDER-561 when you need the resulting values.


What Gets Checked

Blocking Warnings (blocked: true)

The following conditions prevent the line from being updated. The line is left exactly as it was, while the other lines of the order are synchronized normally.

Product / Variant

CodeConditionchanges
F-W-001The variant referenced in the order line does not existNo
F-W-014The variant exists but is INACTIVENo
F-W-014The parent product is INACTIVENo
F-W-015The product is not eligible in the current catalog view contextNo

Offer / Pricing

CodeConditionchanges
F-W-001The offer price does not existNo
F-W-014The offer price is INACTIVENo
F-W-001The offer inventory does not existNo
F-W-014The offer inventory is INACTIVENo
F-W-015The offer price is not eligible for this accountNo
F-W-016The offer price does not match the variant on the order lineNo
F-W-014The supplier owning the offer is INACTIVENo

Quantity Rules

CodeConditionchanges
F-W-017Quantity < 0Yes - quantity: requested value vs 0
F-W-018Quantity < minimum order quantityYes - quantity: requested value vs minOrderQuantity
F-W-019Quantity > maximum order quantityYes - quantity: requested value vs maxOrderQuantity
F-W-020Quantity is not a multiple of item per packYes - quantity: requested value vs itemPerPack
F-W-021Zero quantity is not allowed for this lineNo
📘

Zero quantity behavior

During synchronization, an order line whose quantity becomes 0 is removed by default and warning F-W-021 is raised. This behavior can be overridden at tenant level with the CART_LINES_0_QUANTITY_AUTHORIZED feature flag — when enabled, order lines with a quantity of 0 are accepted and kept in the synchronized order; only negative quantities (F-W-017) are rejected. Contact your CSM to enable this flag on your tenant.

Stock

CodeConditionchanges
F-W-022Not enough stock available for the requested quantityYes - quantity: requested value vs available stock

Custom Fields

CodeConditionchanges
F-W-023Offer custom field configuration is missing or no longer validNo
F-W-024Offer custom field value is invalidNo
F-W-025Required custom field value is missing at offer or order levelNo
📘

Note: At order line level, F-W-025 is not blocking — see below.

Informational Warnings (blocked: false)

The following changes are applied automatically and reported for traceability. The changes field provides the before/after values for each applied change.

ℹ️

Important: Informational warnings reflect a diff between the order line and the current catalog state. Once the sync applies the changes, calling sync again immediately will not return these warnings because the order is now in sync with the catalog. This is expected behavior - it means the order is up to date.

CodeChange appliedchanges
F-W-026Unit price has been updatedunitPrice: old price vs new price
F-W-027Currency has been updatedcurrency: old currency vs new currency
F-W-028Tax values have been updatedtaxRate, taxCode, shippingTaxRate, shippingTaxCode (one entry per change)
F-W-029Quantity has been automatically adjusted (Real-Time Pricing only)quantity: old quantity vs adjusted quantity
F-W-030Custom field values have been resynchronized — never the line custom fields in standard modeOne entry per custom field changed (field = custom field key)
F-W-025An active and mandatory line custom field has no value. The line is synchronized anyway and its custom fields are left unchanged.No

A change of the shipping fees of a logistic order is also reported with F-W-026, with the logistic order as id.

For the full warning code reference, see Error / Warning codes.


Real-Time Pricing tenants

Everything above describes the standard mode. When the tenant runs with Real-Time Pricing (RTP), the lines are sent to an external pricing system and its answer replaces the catalog data on the following points:

PointBehavior under Real-Time Pricing
Set of linesComes from the pricing system: a line may be added (F-W-031) or removed (F-W-032). Logistic orders left without any line are deleted.
QuantityComes from the pricing system; a change is reported with F-W-029.
Prices and stockCome from the pricing system instead of the offer price.
Line custom fieldsThe values returned by the pricing system overwrite the stored ones, without any warning. The custom fields it does not return are kept. An invalid value is reported with F-W-025.
Quantity rulesMinimum, maximum and pack constraints are not enforced.
Status and eligibility checksOffer, offer stock, product and supplier status, and account eligibility are not checked. Catalog view visibility still applies.
⚠️

Warning: The handling of line custom fields is the main difference between the two modes. In standard mode they are never rewritten; under Real-Time Pricing they are replaced by whatever the pricing system returns.


Typical Workflow

flowchart LR
    %% Styles (Readme)
    classDef create   fill:#e8f1ff,stroke:#2f6feb,stroke-width:2px,color:#0b3d91;
    classDef read     fill:#ede9fe,stroke:#7c3aed,stroke-width:2px,color:#1e1b4b;
    classDef update   fill:#e0f7fa,stroke:#06b6d4,stroke-width:2px,color:#0c4a6e;
    classDef decision fill:#fff4e5,stroke:#f59e0b,stroke-width:2px,color:#7a3e00;
    classDef place    fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d;
    classDef stop     fill:#fee2e2,stroke:#ef4444,stroke-width:2px,color:#7f1d1d;

    A[📘 Buyer opens<br>draft order] --> B[🔄 Call sync<br>ORDER-223]
    B --> C{Blocking<br>warnings}
    C -->|None| D[✅ Order updated<br>lastSyncAt set]
    D --> E{Buyer<br>action}
    E -->|Continue editing| A
    E -->|Place order| F[➡️ ORDER-212]
    C -->|At least one| G[⛔ Flagged lines<br>left untouched]
    G --> H[🔧 Remove or fix<br>affected lines]
    H --> B

    A:::create
    B:::update
    C:::decision
    D:::place
    E:::decision
    F:::place
    G:::stop
    H:::update

Recommended integration patterns

Pattern 1 - Sync on order display (recommended)

Call sync every time the buyer opens or returns to the draft order view. This keeps prices and availability up to date and allows the UI to display warnings immediately.

  1. Buyer navigates to the draft order view
  2. Call sync (ORDER-223)
  3. Render the order with fresh data and display any warnings to the buyer
  4. Buyer edits lines if needed → re-sync after edits
  5. When ready → place order (ORDER-212)

Pattern 2 - Sync before placement only

Call sync as a final validation step just before placing the order. Simpler to implement, but the buyer may discover stale data only at checkout time.

  1. Build your draft order (create, add lines, set addresses)
  2. Call sync (ORDER-223) before placement
  3. If blocking warnings → display issues, fix lines, retry sync
  4. If no blocking warnings → proceed to placement (ORDER-212)
✅

Tip: Sync does not add or remove lines - it only validates and updates existing ones. To remove problematic lines, use the line deletion endpoint (ORDER-350) before retrying sync.


Error Handling

No line could be applied

When no line survives validation, nothing is written and the call returns a 400. The error code now tells apart the two most frequent causes, so a buyer can be shown the right message instead of a generic one:

CodeReturned when
OR0038No line was applied and every blocking warning concerns the available stock (F_W_022)
OR0039No line was applied and every blocking warning concerns the packing of the offer (F_W_020)
OR0034Any other case: mixed causes, another reason, or an empty line list. Unchanged.

The detail field keeps its current format in all three cases, and the general behaviour is unchanged: when no line survives validation, nothing is written.

⚠️

Warning: Action required — an integration that tests OR0034 today to detect a stock or a packing problem must now handle OR0038 and OR0039 as well.

The same three codes apply to ORDER-150 (PUT /v2/shop/commercial-orders/{commercialOrderId}/lines) — see Working with Draft Orders.

Other errors

HTTPCodeMessage
400F-E-012Invalid string value for commercialOrderId. Expected a REFERENCE identifier.
401F-E-032Unauthorized. Missing or invalid authentication token.
403F-E-030Caller is not allowed to synchronise this commercial order.
404F-E-002Commercial order not found for the provided commercialOrderId.
409F-E-028Commercial order must not be in status VALIDATED to perform this operation.
422F-E-039No eligible order lines could be processed for synchronisation.

For the full error reference, see Error / Warning codes.


Best Practices

  • Sync on every order display - Call sync whenever the buyer opens the draft order view, not just before placement. This ensures prices and stock are always accurate.
  • Handle blocking warnings gracefully - Display the detail message to the user and let them decide whether to fix or remove affected lines.
  • Use lastSyncAt for freshness - After a successful sync, lastSyncAt is updated on the order. You can use this to decide whether a re-sync is needed (e.g. skip sync if lastSyncAt is less than a few minutes old).
  • Re-sync after line edits - After adding, removing, or changing quantities on lines, call sync again to revalidate the full order.
  • Understand idempotent behavior - Informational warnings only appear when there is a difference to report. A second consecutive sync call returns no informational warnings because the first call already applied the changes. This is expected - it means the order is up to date.
  • Do not use sync as a create mechanism - In standard mode, sync never creates new lines. It only validates and updates existing ones.

Common Mistakes

MistakeConsequenceFix
Calling sync on a validated order409 errorOnly sync orders where validatedAt is empty
Using dj-client: OPERATOR403 errorUse dj-client: ACCOUNT
Expecting sync to add new linesLines are not addedSync only validates existing lines in standard mode
Ignoring informational warningsMissing price or quantity changesAlways check the full warning array, even when blocked: false
Expecting informational warnings on a second callNo warnings returnedThis is normal - the first sync applied changes, so there is no longer a diff to report
Using DJUST_ID in the path400 errorUse the REFERENCE identifier for commercialOrderId
Parsing the detail text to tell a stock problem from a packing oneFragile integration that breaks on any wording changeRead the error code: OR0038 for stock, OR0039 for packing, OR0034 for anything else
Testing only OR0034 to detect a stock or packing rejectionStock and packing rejections are no longer caughtHandle OR0038 and OR0039 too
Relying on sync to refresh the line custom fields in standard modeValues stay exactly as they were, including those of a custom field deactivated sinceWrite the line custom fields explicitly with the order line endpoints
Assuming a blocking warning cancels the whole synchronizationThe other lines have already been updatedRead the order back with ORDER-561 after any sync that returned warnings

Did this page help you?