Draft order with custom line items (overridden originalUnitPrice) — how to deduct inventory on payment?

Hi all,

We’re building a B2B/wholesale flow that creates Shopify draft orders via the GraphQL Admin API (draftOrderCreate, version 2025-07).

The constraint: the wholesale customer should see only their final wholesale price on the draft order’s invoice — no retail price crossed out, no “discount −$X” line.

What we ended up doing (the only approach we found): every line item is a custom line — no variantId, just title + originalUnitPrice + customAttributes carrying the variant link:

mutation OrderProcessingDraftOrderCreate($input: DraftOrderInput!) {
  draftOrderCreate(input: $input) {
    draftOrder { id invoiceUrl }
    userErrors { field message }
  }
}
{
  "input": {
    "lineItems": [
      {
        "title": "Wholesale Product · Black / Large",
        "quantity": 2,
        "originalUnitPrice": "20.00",
        "taxable": true,
        "requiresShipping": true,
        "sku": "SKU123",
        "customAttributes": [
          { "key": "_variant_id",  "value": "12345" },
          { "key": "_variant_gid", "value": "gid://shopify/ProductVariant/12345" },
          { "key": "_product_gid", "value": "gid://shopify/Product/678" },
          { "key": "_sku",         "value": "SKU123" }
        ]
      }
    ],
    "acceptAutomaticDiscounts": false,
    "purchasingEntity": { "customerId": "gid://shopify/Customer/9999" }
  }
}

This works perfectly for the invoice UX — the customer sees Wholesale Product · Black / Large — $20 × 2 = $40, full stop. No retail price comparison.

The problem: when the customer pays the invoice URL and the draft order converts to a real order, inventory is not deducted. The variant’s available count stays the same. We understand why — the line has no variantId, so Shopify has nothing to debit. reserveInventoryUntil also doesn’t apply for the same reason (no inventory binding).

What we’ve tried / ruled out:

  • Switching to variant-backed line items + appliedDiscount — works for inventory, but renders a “−$X” discount line on the invoice, which leaks the retail price to wholesale customers. We don’t want that.
  • appliedDiscount.description: "Wholesale price" — softens the language, but the original price + discount split still shows.
  • Cart Transform — can split/merge/update existing lines but can’t add new ones, so doesn’t help here.
  • Searching the schema for an originalUnitPriceOverride-style field on variant-backed lines — couldn’t find one in 2025-07.

Specific questions:

  1. Is there any current Admin API mechanism that lets us provide a variantId AND a custom originalUnitPrice on the same draft-order line, so Shopify keeps the inventory binding? (i.e., variant-backed line, but with the price overridden — like a “negotiated price” without rendering the discount line.)
  2. If not, is the recommended pattern to subscribe to ORDERS_CREATE (or ORDERS_PAID), read a custom attribute back to the variant, and call inventoryAdjustQuantities to manually debit stock? Are there any pitfalls with this approach (e.g., race conditions with overselling, multi-location handling, refund/cancel restock parity)?
  3. Is anyone aware of a planned API change that would allow per-line price override on variant-backed draft order lines without surfacing a discount line on the invoice? Is this on the roadmap?
  4. For shops with tracked: true inventory items, what’s the right name/reason combo on inventoryAdjustQuantities for “this is a sale debit, not an admin correction” — i.e., the same semantics Shopify itself uses internally when an order pays? We’ve been considering name: "available", reason: "correction" but worried that pollutes inventory history.

Happy to share more of our setup if it helps.

Thanks!

Hey @Shrutika_Lokhande! You’re right that fully custom draft order lines are not tied to a variant, so Shopify does not have variant inventory to debit. For this use case on 2025-07, you should be able to keep the variant binding and override the draft order line price with the priceOverride field on DraftOrderLineItemInput.

Use variantId, quantity, and priceOverride together. That avoids modeling the item as a custom line with originalUnitPrice or exposing the price change as a line discount with appliedDiscount.

mutation draftOrderCreate($input: DraftOrderInput!) {
  draftOrderCreate(input: $input) {
    draftOrder {
      id
      invoiceUrl
    }
    userErrors {
      field
      message
    }
  }
}

{
  "input": {
    "acceptAutomaticDiscounts": false,
    "lineItems": [
      {
        "variantId": "gid://shopify/ProductVariant/12345",
        "quantity": 2,
        "priceOverride": {
          "amount": "20.00",
          "currencyCode": "USD"
        }
      }
    ],
    "purchasingEntity": {
      "customerId": "gid://shopify/Customer/9999"
    }
  }
}

priceOverride is a MoneyInput and should be set in presentment currency. The docs note that originalUnitPriceWithCurrency is for custom line items and is ignored when variantId is provided, and originalUnitPrice is deprecated.

One caveat is bundles. Price overrides cannot be applied to bundle components, and Shopify removes the override if the line becomes part of a bundle.

I would avoid the ORDERS_CREATE or ORDERS_PAID plus inventoryAdjustQuantities workaround unless you intentionally keep fully custom lines. That path means your app owns location selection, idempotency, oversell handling, and refund or cancellation restock parity. Keeping the line variant-backed with priceOverride is the cleaner route.