Developer Changelog / Inventory API

Inventory for draft orders, transfers, and shipments moves from
reserved to committed in a one-time migration

A one-time data migration that consolidates "inventory that is held but not yet fulfilled" into committed. available and on_hand are unchanged, and there is no impact on how much can be purchased. No fields are removed or renamed.

What's on this page
  1. Understand it in 30 seconds: what's happening
  2. Diagram: inventory buckets and how they shift
  3. What the migration covers, and what it doesn't
  4. What stays the same (the reassuring part)
  5. What app developers need to do
  6. Impact on reporting
  7. 5 points engineers should know
  8. 3 use cases you can apply at work
  9. A one-line summary you can use in a pitch

1Understand it in 30 seconds: what's happening

Shopify is unifying how "in-progress inventory holds" are represented.
Until now, holds from draft orders, transfers, and shipments were counted in reserved , but they are moving to committed instead.
Order inventory has always been committed , so everything converges on a single meaning:"held but not yet fulfilled" = committed across the board.
RSV CMT

Until now: the meaning was split in two

Holds from orders were committed, while holds from draft orders, transfers, and shipments were reserved. The same "set-aside inventory" had to be read in two different places.

Going forward: consolidated into committed

committed now represents all inventory that has been sold but not yet fulfilled. Holds from draft orders, transfers, and shipments merge into it as well.

This is a one-time data migration. It is not a process that keeps running — it re-points the data as it exists at the moment the migration runs.
The migration date and how affected shops will be notified are not stated.

2Diagram: inventory bucket breakdown and movement

Before (pre-migration) available (purchasable) No change committed Order holds reserved Draft orders / transfers / shipments and more Migration After (post-migration) available (purchasable) Same quantity committed (increases) Orders + draft orders + transfers + shipments reserved Decreases ← on_hand (total inventory) is identical before and after. The full length of the bar does not change →
The key point is thatquantities simply move between the two unavailable buckets. Total inventory stays the same, and so does the number buyers can actually purchase (available).

3What is and is not covered by the migration

In scope

Migrated

  • Active draft orders(active draft orders)
  • Open transfers / shipments(open transfers / shipments)

Both are limited to those that are still holding inventory at the time the migration runs .

Out of scope

Not changed

  • Completed holds
  • Cancelled holds
  • Already-released holds

These no longer hold reserved inventory, so there is nothing to move in the first place.

Because the condition is "at the time the migration runs,"which bucket a draft order lands in depends on whether it was created or closed before or after the migration. The exact timing of the migration is not stated, so take care with reports that span the cutover.

4What doesn't change (the reassuring part)

ItemImpactDetails
available / on_hand No impact Quantities don't change at all. Total inventory is unchanged too — the only movement is between the two "unavailable" buckets.
quantity name Both stay valid reserved and committed both remain valid, queryable names going forward.
Field definitions No removals or renames No API field is removed or renamed. There is no breaking schema change.
Available inventory No impact The quantity buyers can purchase doesn't change. Nothing looks different on the storefront.
Behavior of existing queries No code changes needed No code changes are required to keep your queries running.only the returned values shift between the two states.
Historical data before the migration Left as is Historical data from before the migration is preserved as-is.

5What app developers need to do

1

Find every place that references reserved

InventoryLevel.quantities(names: ["reserved"]) — list every place your code reads it.

2

Sort them by purpose

The ones that matter are those reading reserved to detect draft orders or transfer/shipment holds.

3

Switch those to read committed

Those places should now read committed instead. Everything else needs no code changes.

Quick reference for the swap

What your app does todayWhat happens after the migrationWhat to do
quantities(names: ["reserved"]) is what you read In affected shops, reserved values go down, and by that same amount, committed goes up Check required Revisit your logic assuming these values will shift
You use reserved to identify draft orders and transfer/shipment holds that information disappears from reserved Change required From now on, read committed
You're worried whether your queries will keep working the queries themselves won't break No action needed code changes are not required
You sync inventory based on available / on_hand nothing changes No action needed
The risk of breaking silently : queries won't throw an error — only the numbers they return change. Apps that drive alert thresholds or inventory sync decisions off reserved values will see this surfaceas "the numbers look wrong" rather than as an exception.

6Impact on reports

If you look at reports broken out by inventory state

For merchants using inventory adjustment reports (the type that breaks adjustments down by inventory state),reserved values moving into committedshows up directly in the report.

A one-time correction entry appears

At the moment the migration runs, one-time correction entry is recorded. This covers only draft orders that are active and transfers/shipments that are open at the time of migration.

the total of on_hand and available does not change. And historical data from before the migration is left untouched. In other words, your stock-count numbers will not change retroactively.

75 points developers should know

1. Not a schema break — a consolidation of meaning

No fields are removed or renamed; both reserved and committed remain queryable. What breaks isn't the type, but the implicit assumption that "reserved = draft order holds" .

2. Totals are preserved (a zero-sum move)

Only the breakdown of unavailable changes; on_hand stays the same.If your aggregation looks at reserved + committed combined, the impact is zero. Conversely, only the places that read it on its own will change.

3. The migration is a snapshot at the moment it runs

Only inventory that is on hold at the time of execution is affected. Completed, canceled, and released holds are out of scope.No explicit migration date or time has been statedso factor in that daily batch diff detection may spike temporarily.

4. A single correction entry lands in your reports

A one-time correction entry appears in the inventory adjustment report.It is easy to misread this as "an unexplained adjustment showed up"so if you have anomaly detection rules on the BI side, give your team a heads-up in advance.

names: [...]

5. What to look at: InventoryLevel.quantities(names:) and InventoryQuantity

The impact centers on the InventoryLevel 's quantities(names: [...]) field, plus the per-name InventoryQuantity object.No mention of which API version this applies from, or how affected shops are determined — verify whether you are affected by measuring it on your own store.

8Three use cases you can put to work

reserved reference audit
USE CASE 1

Auditing "reserved dependencies" in client apps and custom integrations

The problem
An inventory integration app you built for your own team or for a client reads quantities(names: ["reserved"]) , and after the migration the value silently drops. No error is raised, so nobody notices.
What to do
Full-text search the codebase for "reserved" , then sort each usage into "hold detection" and "just displaying a total," and switch only the former to committed references.
The payoff
You keep detecting holds from draft orders, transfers, and shipments without missing any. The queries themselves don't need rewriting, so the change stays minimal.
Technical note
Code changes aren't required to keep things running — they're required to preserve meaning. Both names remain valid, sonames: ["reserved","committed"] lets you fetch both and migrate in stages while comparing them.
Migration Time
USE CASE 2

Explain the "step change" in BI dashboards and inventory reports ahead of time

The problem
Adjustment reports broken down by inventory state and reserved-related charts in BI drop sharply from one day on, plus an unfamiliar correction entry shows up — and the team panics, assuming an inventory incident.
What to do
Share in advance that this migration may happen and that it is a reserved → committed relabeling plus a one-time correction, and add a note to the dashboard. If you have anomaly detection rules, loosen the thresholds temporarily.
The payoff
Avoids wasted support tickets and emergency investigations.on_hand and available are unchanged, and history stays as-is — you can say that flatly, so it takes very little explaining.
Technical notes
The correction entries only apply to draft orders that are active and transfers/shipments that are open at the time of migration. Historical data from before the migration is not modified, so the baseline for period-over-period comparisons does not move.
Draft Transfer Shipment com- mitted
USE CASE 3

Consolidating to a single query for "spoken-for inventory"

The problem
To surface "inventory that is held but has not shipped yet," you needed logic that added up two places: committed for orders, and reserved for draft orders, transfers, and shipments.
The move
After the migration, committed alone can express "spoken for but not yet fulfilled," so the aggregation logic collapses into a single path.
The payoff
Report definitions for backorders and allocated inventory get simpler, and one source of numeric drift — missing a state — goes away.
Technical notes
Make the switch only after the migration has actually run. Before the migration, draft orders are not included in committed, so moving to committed alone ahead of time will undercount. The migration date and time is not stated, so the safe approach is to watch both values side by side while you switch over.

9One-line summary you can use in a pitch

"Inventory holds for draft orders, transfers, and shipments move from reserved to committed in a one-time migration, and
committed becomes the single value for 'all spoken-for, unfulfilled inventory.'
available / on_hand are unchanged, no fields are removed or renamed, and queries will not break.
All you have to do is 'reinterpret the places where you detected holds via reserved as committed.'"