Shopify Purchase Orders Have No GraphQL API: Build Your Own Tooling, or Buy an App?
Shopify's native purchase orders in Products > Purchase orders can record a supplier, quantities, cost, and status — but as of the 2026-07 Admin API release, there is still no PurchaseOrder object, query, or mutation anywhere in GraphQL or REST, a gap developers have been filing feature requests against for over a year with no resolution. With Stocky gone for good on August 31, that leaves anyone who assumed the native feature was scriptable with three real choices, and the 'alternatives' roundups don't mention any of them.
There is no purchase order object, query, or mutation anywhere in Shopify's Admin GraphQL API — not in the 2026-07 release, and none in any release before it. The purchase orders you create under Products > Purchase orders live entirely inside the admin UI; the only API surface anywhere near them is InventoryTransfer, which handles the stock movement a PO triggers but knows nothing about suppliers, cost, or PO status.
That gap is worth pinning down precisely, because Stocky — the app that used to be the actual answer for merchants who wanted purchase orders with an API behind them — shuts down for good on August 31, 2026, and "just use the native admin feature instead" is the advice showing up everywhere without the one caveat that decides whether it's usable for you: it isn't scriptable.
What the native purchase orders feature actually gives you
Shopify's built-in purchase orders, reachable from Products > Purchase orders in any admin, are a real and free feature, not a stripped-down placeholder. You pick or create a supplier record with contact details, payment terms, and currency, search or browse products into the order, and set quantities and cost per line. A new order sits in Draft status while you're still building it; moving it to Ordered locks it in as submitted to the supplier and unlocks the next step — creating an inventory transfer from that PO to track the shipment. When stock physically arrives, you open the PO, click Receive inventory, and enter accepted or rejected counts per line, which is what actually updates your available inventory.
That's a genuinely usable purchase-order workflow for a person clicking through the admin. It just isn't accessible any other way.
The part that's missing: any way to touch it programmatically
Developers who've gone looking for a way to read or write purchase orders through the API keep arriving at the same answer, in threads spread out over more than a year on Shopify's own developer community forum. A feature request opened in mid-2026 checked this against the then-current 2026-07 API release and found nothing — no PurchaseOrder object, no query, no mutation — and a reply to that thread linked back to an earlier, separate request asking for exactly the same thing. Two independent asks, over a year apart, both answered by silence from the schema rather than a fix.
The closest thing the Admin GraphQL API has is InventoryTransfer, and it's worth knowing precisely what it does and doesn't cover before you build anything on top of it:
{
inventoryTransfers(first: 10) {
edges {
node {
id
name
status
origin { name }
destination { name }
totalQuantity
receivedQuantity
}
}
}
}
An InventoryTransfer has an origin location, a destination location, line items, a status, and quantities ordered versus received — and mutations to match (inventoryTransferCreate, inventoryTransferSetItems, inventoryTransferMarkAsReadyToShip, among others). What it does not have is a supplier field, a cost field, or any concept of "this transfer came from purchase order #4471." It's a location-to-location stock movement record. A purchase order is a supplier agreement. Shopify's API gives you the first and nothing of the second.
The workaround developers reach for, and why it doesn't hold up
The same community threads that confirm the gap also show what people try instead: storing purchase order data — supplier name, cost, expected date — as metafields on a draft order, since a draft order at least has line items and can be queried and mutated through the API. It works well enough to demo. It breaks in ways that matter once it's carrying real operations.
- A draft order is not a purchase order in the admin's eyes. It won't show up in Products > Purchase orders, so anyone on the team who isn't looking at your metafields directly sees nothing — you've built a system your own staff can't see without a custom UI on top of it.
- Metafields on a draft order aren't filterable or reportable the way native PO fields are. There's no built-in "purchase orders by supplier" or "open POs over 30 days" view; you're rebuilding that from scratch too, on data that lives somewhere the admin doesn't display it.
- Anyone can open that draft order in the admin and edit it by hand, with no awareness that a metafield they can't see is meant to be authoritative. The moment a staff member "fixes" a quantity in the UI, your record and Shopify's disagree, and nothing tells either of you it happened.
It's a workaround built to route around a missing object, not a design anyone would choose starting from a blank page — which is the honest way to think about whether it belongs in what you build.
Why "just use the native feature" is incomplete advice right now
The reason this is worth writing about this week specifically, and not any time in the last year the gap has existed, is that Stocky shuts down for good on August 31, 2026, and it won't export supplier data or historical POs for you when it goes. Every merchant who relied on Stocky for API-driven reordering is being pointed, correctly, at Shopify's native purchase orders as part of the migration — but "native" reads as "supported and complete," and for anyone whose reorder process was ever automated rather than manual, it isn't. Search results for Stocky alternatives are full of comparison posts ranking apps on price and feature checklists. None of the ones we checked while researching this asked the one question that actually matters if API access was why you cared about Stocky in the first place: does the replacement expose one at all.
Three real paths, and who each one is actually for
Stay manual in the admin. If you're placing a handful of purchase orders a month, the native feature is free, complete for a human, and not worth building anything against. Automating a process that takes ten minutes a week is a solution looking for a problem — don't.
Keep the purchase order as your own record, and use Shopify's API only for what it actually supports. This is the honest version of "build it yourself": don't try to make Shopify's admin hold your purchase order data, because there's no API path back out of it. Instead, track supplier, cost, and PO status in your own system — a database, an internal tool, whatever you already run operations on — and use InventoryTransfer only for the part it's built for: the actual stock movement and receiving, reconciled against your own PO record by matching quantities and dates rather than by a shared ID, since Shopify has no field to hold one. This is real engineering work, not a quick script, and if you're running more than one stocking location, the same concurrent-write handling that causes inventory race conditions elsewhere applies directly to transfers being received into two locations at once — don't skip that reconciliation logic to save a sprint.
Buy a dedicated inventory app. The legitimate choice for teams that want purchase orders working without building anything, and there's a real market of apps built specifically to fill the space Stocky left. The step the roundup posts skip is confirming the app you're paying for actually has an API or webhooks of its own — if scriptable purchase orders were the reason Stocky mattered to you, buying a replacement that's just as API-less as Shopify's native feature solves nothing. Before you subscribe, ask the vendor directly: is there a documented API or webhook for purchase order data, or does their app also only expose it through their own admin UI? A feature-comparison page will never answer that question, because it isn't a feature the comparison is built to show.
Who shouldn't do any of this: a store with predictable, low-volume reordering and no downstream system that needs PO data automatically. The native feature was built for exactly that case, and building custom tooling against a gap in Shopify's API to solve a problem you don't actually have is how a five-minute admin task turns into a maintenance burden nobody asked for.
If you're mid-migration off Stocky and the honest answer is that your reorder process actually was automated — webhooks firing purchase orders, a forecasting tool writing directly into Stocky, anything past manual entry — that's a scoping conversation worth having before August 31 closes the door on exporting your historical data. We do this kind of Shopify operations work directly, and if you want a second opinion on which of the three paths above actually fits your order volume before you commit engineering time to it, reach out.