Skip to content

For Shopify agencies

When the quote and the Shopify order disagree: what drifts after conversion

By Jahangir Alam · October 9, 2026 · 12 min read

Last verified
Shopify API
2026-10
Audience
Shopify agencies and developers keeping a quote layer, Shopify and an ERP or CRM in agreement after conversion
Scope
After conversion at API 2026-10: draft edits and unlinked checkouts, deleted and purged drafts, unpaid invoices, missed order webhooks, order edits, buyer-requested edits, cancellations, refunds and fulfilment, split deals, currency, linkage keys and tag overwrites, identity changes, field ownership, Events versus webhooks, and a reconciliation job

After a quote converts on Shopify, four records describe the same deal: the accepted quote, the draft order, the order, and whatever the ERP or CRM holds. They stop agreeing in a small number of documented ways - a draft edited after conversion, a draft still open after its order exists, a draft deleted or purged after a year, an order edited, cancelled or refunded, a buyer-requested change, a tag list overwritten by a connector. Each drift is detectable by comparing two specific fields, and each field has one owner. Reconciliation is choosing those owners and checking the pairs on a schedule.

This page is the catalogue of what drifts after the draft exists, how to detect each case, how to repair it, and who owns which field from conversion on. Creating exactly one draft is covered in how one accepted quote becomes exactly one draft order; what breaks at conversion is in the 17 failure modes; a price that was wrong from the start is diagnosed in why a quote converts at the wrong price. "Reconciliation" here means quote-to-order data, not payout or bank reconciliation.

Everything about Shopify below was checked against Shopify's own pages on 9 October 2026 at API version 2026-10; sources are at the end.

The four comparisons

Four records, four comparisons Four boxes in a row: the accepted quote, the draft order, the order, and the ERP or CRM. Between each pair, the comparison that detects drift: quote to draft by the totals stored at conversion; draft to order by the draft's order field; the order to itself by original total against current total; order to ERP by the conversion attribute or tags and the presentment money. Accepted quote what was agreed Draft order payable until paid Order edits, refunds, fulfilment ERP or CRM what was booked totals stored at conversion DraftOrder.order and status original vs current total attribute or tags, presentment money
Every drift in the table below shows up in one of these four comparisons.

What drifts, and how to catch it

Grouped by when it happens. "Source of truth" is the record that wins from conversion on.

Before the order exists

# What drifts Cause in Shopify Detect Repair Source of truth
1 The draft's lines or totals versus what was accepted Staff edit the draft after conversion; updating tags overwrites the whole list draft_orders/update payload totals against the totals stored at conversion; DraftOrder.tags against the tags you wrote A commercial change is a new proposal or counter-offer and a new draft, with the old draft deleted; a logistics change is recorded The accepted version, until payment
2 The draft is still open although its order exists An update while a checkout was in progress unlinked the checkout: the order is created, and "the draft will remain open even after the order is created" An order carries your conversion attribute, but DraftOrder.order is null or the status isn't COMPLETED Link the order by the attribute; a person deletes the stale draft The order
3 The quote points at a draft that no longer exists Staff deleted it draft_orders/delete; as a backstop, draftOrder(id) returns nothing Mark the draft lost; confirm no order carries the attribute; re-create or close Shopify
4 The same, after a year Drafts created on or after 1 April 2025 are deleted after a year without an edit draftOrder(id) returns nothing - Shopify doesn't document whether the purge sends a delete webhook Decide well before the year whether the deal is lost or re-quoted Shopify
5 The invoice went out and was never paid An order exists only once the draft is paid or completed draftOrders(query: "tag:… status:invoice_sent") plus age Chase, extend, or delete the draft and close the quote - together The draft's status
6 The quote expired, the draft is still payable A draft has no deadline other than the purge The quote is expired while DraftOrder.status is OPEN or INVOICE_SENT Delete the draft when the quote expires, or don't expire quotes after the invoice Choose one - but only one
7 A paid order the quote layer or ERP doesn't know about Webhook delivery isn't guaranteed draftOrder.order is set but no order id is stored; or orders(query: "tag:… updated_at:>…") against stored ids Replay through the same webhook handler (the sweep) The order

After the order exists

# What drifts Cause in Shopify Detect Repair Source of truth
8 The order's lines or total versus the accepted version The merchant or another app edits the order: Shopify says an app-created draft's order "can be edited in your Shopify admin, and by other apps" orders/edited; Order.edited; originalTotalPriceSet against currentTotalPriceSet Record the reason on the order; don't rewrite the quote; the ERP follows the order The order for fulfilment and invoicing; the quote for what was agreed
9 A pending buyer change the ERP or warehouse doesn't see From 2026-10, a buyer can request removal of unfulfilled lines requested_order_edit/* webhooks; Order.requestedOrderEdits Hold fulfilment while it's pending; accept or decline; an accepted request arrives as an order edit The order
10 The quote shows a live deal, the order is cancelled Cancellation is "irreversible" orders/cancelled; cancelledAt Record it per order; the quote stays the record; a re-quote is new The order
11 Amounts after refunds and returns Refunds per line or shipping; returns refunds/create; returns/*; currentSubtotalPriceSet The ERP's credit note comes from the refund, not from the quote The order's refunds
12 Fulfilment state copied in several places A warehouse or ERP writes fulfilments into Shopify fulfillments/*; displayFulfillmentStatus Don't mirror fulfilment into the quote layer The warehouse or ERP, through Shopify

The shape of the deal and its keys

# What drifts Cause Detect Repair Source of truth
13 "The quote has one order, it should have two" Partial acceptance or split conversion makes one draft per group; lines left for later are still open, not declined Converted groups against stored order ids; each order's subtotal against its accepted lines Reconcile per group; open lines aren't missing The quote layer for which lines are open; the orders for what was bought
14 The quote total doesn't match the ERP's amount The draft and order are in the presentment currency; shopMoney is converted Compare the quote with presentmentMoney only Book from one side deliberately Presentment money
15 The order is no longer recognisable as from the quote Tags overwritten by a full-list write; the attribute or note edited orders(query: "tag:…") against stored ids; Events triggers on order.tags and order.customAttributes Restore from the quote record; integrations add tags with tagsAdd, never by rewriting the list The quote layer, which wrote the keys once
16 The buyer's identity changed after conversion A contact removed, a location deleted or changed, customers merged company_contacts/delete, company_locations/delete, customers/merge against stored ids Before payment, re-create the draft for the right location; after, fix the customer master, not the order The ERP's customer master, or Shopify - one of them
17 A connector rewrites fields the quote layer owns Two writers on one field Field-level Events triggers; diff against what the quote layer wrote Restrict the connector to its own fields One writer per field
18 An integration missed quote-layer events At-least-once, out-of-order delivery; an endpoint down Gaps in the event sequence; deliveries the sender gave up on Replay from the events feed, then from the API The quote layer's event log
19 A reconciliation job reports "all good" on old orders Apps see the last 60 days of orders unless they have read_all_orders The job's scope against the order's age Request read_all_orders, or reconcile within the window -

Who owns which field after conversion

ERP, CRM and PIM integration patterns has the ownership table for the life of an integration. This one starts at the moment the draft exists:

Field Owner after conversion Everyone else Why
Agreed lines, quantities, unit prices, terms, version The quote layer - the sealed accepted version, never edited Read for audit It is the record of the agreement; a sent proposal is locked
Which lines are still open The quote layer The CRM reads it as pipeline Not converted, and not lost
The draft's content until payment The quote layer wrote it once; staff edits are exceptions to record The ERP ignores drafts The draft is payable - changing it changes the deal
The order's lines, quantities and totals The Shopify order The ERP and warehouse read; the quote layer doesn't mirror Edits, refunds and returns happen on the order
Payment and refunds Shopify The ERP books from refunds; the quote layer records end states only Money moves on the order
Fulfilment The warehouse or ERP, writing into Shopify The quote layer: nothing One writer
Invoice, ledger, credit notes The ERP or accounting system - Shopify isn't the ledger
Linkage keys - the quote's tags, conversion attribute, note line The quote layer writes them once Others append with tagsAdd Updating tags overwrites the list
Company, location, contact The ERP's customer master or Shopify - one of them The quote layer reads One writer
Quote status after conversion The quote layer, derived from Shopify's order events Integrations read Derived, never the other way round

The rule that falls out of it: never write order changes back into the quote. The quote is what was agreed; the order is what is being fulfilled and paid. When they differ, record why on the order.

Events or webhooks for this

Shopify's Events became generally available with API 2026-10 as the successor to classic webhooks, and classic webhooks keep working. Events has topics for orders, refunds, returns, fulfilment orders, companies and customers, with triggers on individual fields - order.tags, order.customAttributes, order.lineItems.quantity among them - which suits rows 8, 15 and 17. It has no draft-order topic, so rows 1 to 6 still need the classic draft_orders/* webhooks. Shopify doesn't document Events' delivery guarantees, so keep the reconciliation job below whichever you use.

A reconciliation job you can copy

Run it on a schedule, against the stored ids, inside the order-access window:

  1. Drafts you created and haven't seen paid: draftOrders(query: "tag:<your-tag> updated_at:>…"). For each, status and order: an order without a stored id is row 7; a missing draft is row 3 or 4; an old INVOICE_SENT draft is row 5 or 6.
  2. Orders that carry your key: orders(query: "tag:<your-tag> updated_at:>…"). Compare originalTotalPriceSet with currentTotalPriceSet (row 8), check cancelledAt and the financial status (rows 10, 11), requestedOrderEdits (row 9), and that the tags and conversion attribute are still there (row 15).
  3. Outside systems: for each order, the ERP's amount against presentmentMoney (row 14), the number of orders against converted groups (row 13).
  4. Scope: without read_all_orders, only the last 60 days of orders are visible (row 19).

The create side - the sweep that finds a conversion whose outcome is unknown - is in the idempotent conversion post.

How QuotWay behaves

One implementation, described as it works today:

  • What it matches on. Every draft QuotWay creates carries the tags quotway and quotway-<quote reference>, a merchant-only note with the quote reference and version, and one conversion attribute that links the order back to its conversion group. QuotWay never edits, completes or deletes a draft after creating it, and never edits orders.
  • What it records. A change to a converted draft's totals is recorded on the quote's activity log, with the before and after amounts. Once a quote is at Order completed, QuotWay records it on the quote when its order is cancelled or fully refunded. Partial refunds, returns, order edits and fulfilment stay on the Shopify order - check the order for those (converting to a draft order).
  • Split and partial conversions. Each accepted group becomes its own draft and order; lines the buyer left for later stay open on the quote and can be converted later (partial acceptance and split conversion).
  • Missed order webhooks. A sweep checks invoiced quotes after seven days without an order and, if Shopify shows one, replays it through the same handler.
  • For integrations. On the Enterprise plan - including during the 14-day free trial - the API's quote object lists the quote's Shopify draft-order and order ids, and a 30-day events feed is the recovery path for missed webhooks (the events feed). Plans are on the pricing page; conversion is described on convert quotes to orders.

FAQ

Why is a Shopify draft order still open after the customer paid?

An update was made to the draft while its checkout was in progress, which unlinks the checkout: the order is created, but "the draft will remain open even after the order is created". Check DraftOrder.order, link the order by your own key, and delete the stale draft.

Is there a webhook for when a draft order is paid?

Not a draft-order "paid" topic. Payment creates an order, so listen to orders/create and match it to the draft with your own attribute or tag; the draft's status becomes COMPLETED and its order field is set. draft_orders/update covers changes to the draft, and Shopify's Events has no draft-order topic at 2026-10.

Should the quote change when the order is edited?

No. The quote is the record of what was agreed; the order is what is fulfilled and paid. Record the reason for an edit on the order and let the ERP follow the order.

How do I detect order edits for my ERP?

The orders/edited webhook, the order's edited field, and a difference between originalTotalPriceSet and currentTotalPriceSet. With Events, a trigger on order.lineItems.quantity does the same for quantities.

What are buyer-requested order edits?

From API 2026-10, a buyer can ask to remove unfulfilled lines from an order. The request arrives as requested_order_edit/* webhooks and is visible on Order.requestedOrderEdits; hold fulfilment while it's pending, and an accepted request becomes an ordinary order edit.

Do unpaid draft orders expire?

Drafts created on or after 1 April 2025 are deleted after a year without an edit. Nothing else expires them, so a quote that expires earlier leaves its draft payable unless you delete it.

Does Shopify Events replace webhooks for reconciliation?

Events is the successor to classic webhooks and classic webhooks keep working, but it has no draft-order topic, so drafts still need draft_orders/*. Shopify doesn't document Events' delivery guarantees, so keep a reconciliation job either way.

Why doesn't the ERP total match the quote?

The quote, the draft and the order are in the buyer's presentment currency; shopMoney is converted. Refunds and order edits change the order's current total. Compare the quote with the order's presentment money and its original total.

Sources

Shopify pages, read on 9 October 2026 at API version 2026-10:

QuotWay behaviour is described from its public documentation and the app's source, read on 9 October 2026.

Related articles

See how QuotWay handles this on your store.

We’d like to set analytics cookies to understand how the site is used. They’re not required — declining changes nothing about how the site works, and you can change your mind any time on our privacy page.