Skip to main content

Available to Promise vs on Hand: Why B2B Storefronts Oversell

On hand is a count; available to promise is a commitment. Why B2B storefronts oversell when they sync the wrong number, and how ATP and CTP fix it.

Available to Promise vs On Hand: Why B2B Storefronts Oversell

The storefront said 40 in stock. The buyer ordered 30. The warehouse had 40 on the shelf, and every one of them was already spoken for: 12 on a counter ticket written that morning, 18 allocated to a job on the shop floor, 10 on an EDI order from a national account.

Nobody made a mistake. The storefront displayed exactly the number it was given, and it was given the wrong number. On hand is what the warehouse has. Available to promise is what the business can still sell. B2B storefronts oversell because the integration feeding them was built around the first number when the buyer was asking about the second.

Quick answer: On hand is a physical count of units at a location. Available to promise (ATP) is the uncommitted portion of that stock plus scheduled supply: on hand, minus everything already promised to other orders, jobs, and demand, plus receipts you can count on. B2B storefronts oversell when the ERP's on-hand figure is pushed into Shopify, because Shopify's own available quantity only subtracts orders Shopify knows about and is blind to counter sales, rep orders, EDI orders, and production allocations sitting in the ERP. The fix is to sync the ERP's ATP rather than its on-hand count, per location, recheck it at checkout, and show a date instead of a quantity for items that are made rather than stocked, which is where capable to promise comes in.

On hand is a count. Available to promise is a promise.

The two numbers answer different questions. On hand answers "what is physically here?" and it is a warehouse fact: count the bins and you have it. Available to promise answers "what can I still commit to a new customer?" and it is a commercial fact that depends on every promise the business has already made.

Oracle's JD Edwards documentation gives the cleanest formal definition: ATP is "the uncommitted portion of a company's inventory or planned acquisitions." Its published calculation shows how much sits between the two numbers: first-period ATP starts from the on-hand balance, subtracts safety stock, adds incoming work orders, purchase orders, and planned orders, then subtracts sales orders, work order parts demand, interplant demand, and expired lot quantities. Forecast is never included, which is the rule that keeps ATP honest: it promises against real orders and real supply, never against hope.

In practice most distributors run a simpler version, on hand minus committed, with incoming supply added only when its arrival date is reliable. The formula matters less than the principle. Every unit a sales rep, a counter clerk, an EDI feed, or a production planner has already claimed must come out of the number before a buyer sees it.

Why the storefront inherits the wrong number

Shopify already understands this distinction for its own orders. Its documented inventory states separate on hand from available: on hand is the total units at a location, made up of committed, unavailable, and available, and committed covers units in unfulfilled orders or reserved in draft orders. So when a web order comes in, Shopify correctly moves those units from available to committed.

The blind spot is everything that did not happen in Shopify. A B2B distributor takes orders at the counter, over the phone, through reps, through EDI from large accounts, and through production allocations that never touch the storefront at all. Those commitments live in the ERP. If the integration writes the ERP's on-hand figure into Shopify, Shopify's available inventory equals that on-hand count minus only the web orders it happened to see. The storefront is being honest about its own commitments and has no way of knowing about anyone else's.

That is why oversell in B2B is structural rather than occasional. It scales with the share of orders that enter through other channels, which in most distributors is still the majority, and it gets worse exactly when demand is highest, because that is when every channel is claiming units at once. The diagnosis of how syncs drift is its own subject; the decision that prevents this particular failure is choosing which number the storefront promises, which is Decision 2 in the Shopify ERP sync design spec.

What "committed" means depends on which ERP you run

The gap between on hand and ATP is not the same shape in every business. The ERP decides what counts as a commitment, and an integration that ignores how its specific ERP counts will oversell in ways nobody predicted.

In manufacturing ERPs, stock is claimed by production. In Epicor Kinetic, a part can be on the shelf and entirely unavailable because it is committed to jobs and work orders, or counted as finished goods already spoken for. Push the raw on-hand figure and the first person to discover the oversell is a production supervisor. The same pattern runs through Infor SyteLine, where Infor's own documentation defines availability as on hand minus allocations, with the option to include released jobs and purchase orders, and where the system already calculates ATP and CTP dates for made-to-order items. For a manufacturer the honest storefront answer is often a date, not a count.

In distribution ERPs, stock is claimed by the branch. A contractor does not care about national inventory; they care whether the branch they can reach today has the part. On Infor SX.e, branch availability is its own design workstream, with rules for which branches each customer sees and whether the number shown is on hand or available after commitments. On Epicor Prophet 21 the subtler failure is timing: a buyer adds the last three on the shelf at a branch while the counter sells them twenty minutes earlier, which no architecture fully eliminates and which is handled honestly by rechecking availability at checkout rather than trusting the number from browse.

And some connectors never had ATP to begin with. Infor's official M3 connector for Shopify, per Infor's own integration guide, sends a stock file once a day on a net change basis, on hand only, with no future available to promise. That is a fine design for the direct-to-consumer case it was built for. It is not a B2B inventory position, because a daily stock file is not availability: it is yesterday's count of what was on the shelf, with none of today's commitments taken out.

Available to promise vs capable to promise

ATP answers from existing stock and scheduled supply. Capable to promise (CTP) goes a step further for items that are made rather than stocked: it checks whether the business has the capacity, the materials, labor, and machine time, to produce the order, and projects the date by which it can actually be completed. ATP asks "do we have it or is it already coming?" CTP asks "can we make it, and when?"

The distinction decides what the storefront should display. A stocked item shows a quantity at the buyer's location, netted of every commitment. A made-to-order item shows a promise date, because a count of zero on a product you build every week tells the buyer something false: that they cannot have it, when the truth is they can have it on the fourteenth. Most manufacturers need both models running on the same catalog, and separating which SKUs use which is early design work, not a post-launch fix.

What a B2B storefront should actually show

Four rules turn the distinction into a store that stops overselling.

Sync ATP, not on hand. The number that crosses from the ERP to Shopify should already have every ERP-side commitment removed: counter sales, rep and EDI orders, production allocations, and safety stock. Shopify then subtracts its own web orders on top, and the two sets of commitments finally add up.

Promise per location. For any distributor with more than one warehouse or branch, a blended national figure is a promise the nearest building cannot keep. Availability should reach the storefront per location, matched to the location that will fulfill the buyer's order.

Recheck at checkout. The number shown at browse is minutes old by the time the buyer submits, and in B2B those minutes include counter sales. A checkout-time availability call against the same logic that produced the browse figure catches the collision before it becomes a short shipment, and tells the buyer immediately, ideally with the next available date.

Show dates where you make things. For made-to-order SKUs, replace the quantity with an ATP or CTP date. A buyer can plan around a real date. They cannot plan around a zero they learn to ignore.

Each of these is standard behavior for a well-built integration rather than custom exotica, and it is how Uncap Connect is designed: the ERP computes availability with its own commitment logic, and Shopify displays the answer instead of recalculating a weaker version of it. Uncap has been a Shopify Platinum Partner since 2013, with 380+ storefronts launched on Shopify, including for manufacturers, distributors, and wholesalers. Book a Demo and bring one SKU your store has oversold. Walking through how its ERP counts commitments is the fastest way to see where the number went wrong.

Frequently asked questions

What is available to promise?

Available to promise (ATP) is the uncommitted portion of a company's inventory and scheduled supply: on-hand stock minus everything already promised to other orders, jobs, and demand, plus incoming receipts the business can rely on. Forecasts are excluded. It answers what a business can still commit to a new customer, and when.

What is the difference between available to promise and on hand?

On hand is a physical count of every unit at a location, including units already sold but not shipped. Available to promise subtracts those commitments, and safety stock, from on hand and adds reliable incoming supply. A storefront that displays on hand will sell units that are already claimed; a storefront that displays ATP will not.

What is the difference between ATP and CTP?

ATP checks existing stock and scheduled supply. Capable to promise (CTP) checks whether the business has the materials and production capacity to make the order, and projects the completion date. Stocked items should show an ATP quantity; made-to-order items should show a CTP or ATP date instead of a count.

Why does my B2B Shopify store oversell?

Usually because the integration pushes the ERP's on-hand figure into Shopify. Shopify's available quantity subtracts only orders placed in Shopify, so counter sales, rep orders, EDI orders, and production allocations recorded in the ERP are invisible to it. Syncing the ERP's ATP per location, and rechecking availability at checkout, closes the gap.

How often should available to promise sync to the storefront?

As often as the stock moves. Fast-moving SKUs need event-driven updates, because oversell exposure grows with sync lag multiplied by sales velocity, while slow movers tolerate scheduled batches. Whatever the cadence, a checkout-time recheck is the safety net for the minutes between the last sync and the buyer's order.

Keep reading
All notes →

ERP APIs Explained: What Each ERP Actually Exposes to an Ecommerce Integration

Sep 25, 2026

What Is an Epicor BAQ, and Why Your Storefront's Inventory Number Depends on One

Sep 25, 2026

SyteLine, CloudSuite Industrial, SX.e, CloudSuite Distribution: Infor's ERP Names Explained

Sep 25, 2026

Matrix Pricing, Contract Pricing and Special Price Agreements: How ERPs Decide What a B2B Buyer Pays

Sep 25, 2026
The Field Notes newsletter

Insights, guides, and trends. Once a month.

One email, last working day of the month. The notes worth keeping from building commerce on Shopify.

InsightsField-tested lessons from live Shopify builds.
GuidesStep-by-step playbooks for B2B, migrations, and performance.
TrendsWhat’s actually moving in commerce and AI, no hype.
Subscribe 2,400+ operators
StrategyWholesaleGrowthAI
Monthly · no spam · unsubscribe anytime
Talk to Our Experts →