---
title: "When the quote and the Shopify order disagree: what drifts after conversion"
description: "After conversion, quote, draft order, order and ERP drift apart in 19 documented ways: how to detect each, repair it, and who owns which field."
url: "https://www.quotway.com/blog/quote-to-order-out-of-sync"
type: "blog post"
category: "For Shopify agencies"
published: "2026-10-09"
verified: "2026-10-09"
shopify_api_version: "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"
locale: "en"
source: "QuotWay - B2B Quote & Negotiation App for Shopify"
---

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

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](/blog/idempotent-draft-order-creation); what breaks *at* conversion is in [the 17 failure modes](/blog/quote-to-draft-order-failure-modes); a price that was wrong from the start is diagnosed in [why a quote converts at the wrong price](/blog/quote-converts-at-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.
>
> 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](/blog/idempotent-draft-order-creation#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](/blog/shopify-b2b-erp-crm-pim-integration-patterns#ownership) 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](/blog/idempotent-draft-order-creation#sweep).

## 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](/docs/converting-to-orders/convert-a-quote-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](/docs/converting-to-orders/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](/docs/api/events)). Plans are on the [pricing page](/pricing); conversion is described on [convert quotes to orders](/features/convert-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:

- [draftOrderUpdate](https://shopify.dev/docs/api/admin-graphql/2026-10/mutations/draftOrderUpdate) - an update unlinks a checkout in progress and the draft stays open
- [DraftOrder](https://shopify.dev/docs/api/admin-graphql/2026-10/objects/DraftOrder) and [DraftOrderInput](https://shopify.dev/docs/api/admin-graphql/2026-10/input-objects/DraftOrderInput) - status, `order`, tags
- [Draft orders](https://help.shopify.com/en/manual/fulfillment/managing-orders/create-orders) - deletion after a year without an edit for drafts created on or after 1 April 2025; payment creates the order
- [Order](https://shopify.dev/docs/api/admin-graphql/2026-10/objects/Order) - original and current totals, `edited`, `cancelledAt`, `requestedOrderEdits`
- [Edit existing orders](https://shopify.dev/docs/apps/build/orders-fulfillment/order-management-apps/edit-orders) - app-created orders can be edited by the admin and other apps; the 60-day order window
- [orderCancel](https://shopify.dev/docs/api/admin-graphql/2026-10/mutations/orderCancel) - cancellation is irreversible
- [tagsAdd](https://shopify.dev/docs/api/admin-graphql/2026-10/mutations/tagsAdd) - adding tags without overwriting
- [Webhook topics](https://shopify.dev/docs/api/admin-graphql/2026-10/enums/WebhookSubscriptionTopic) and [HTTPS webhook delivery](https://shopify.dev/docs/apps/build/webhooks/subscribe/https) - topics; delivery isn't guaranteed
- [Events are now generally available](https://shopify.dev/changelog/next-generation-events-are-now-generally-available) and [events and webhooks](https://shopify.dev/docs/apps/build/events-webhooks) - topics, field triggers, classic webhooks continue
- [Release notes 2026-10](https://shopify.dev/changelog/release-notes/2026-10) - buyer-requested order edits

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