Hi @PMcDougle_Rothys
I used the Dev MCP to see what recommendations it would provide for this, and this is what it generated. Make sure to test everything before adding to prod:
Handle restock notifications and fulfillment orders (Continue selling when out of stock)
1) Get notified when on‑hand inventory lands
- Use a webhook on topic:
INVENTORY_LEVELS_UPDATE.
- Optional filter: narrow by
inventory_item_id and/or location_id.
- Detect “restock” app-side by comparing new
available vs your last seen value (no built-in “crossed from <=0 to >0” filter).
Validated GraphQL:
mutation CreateInventoryLevelUpdateWebhook($callback: String!) {
webhookSubscriptionCreate(
topic: INVENTORY_LEVELS_UPDATE
webhookSubscription: { uri: $callback, format: JSON }
) {
webhookSubscription { id topic uri }
userErrors { field message }
}
}
Note: “Continue selling when out of stock” is ProductVariant.inventoryPolicy = CONTINUE; it doesn’t change how you’re notified—use inventory level webhooks.
2) Fetch fulfillmentOrders for the SKU that just restocked
- Direct (fastest): query
fulfillmentOrders using search syntax
Example query: sku:YOUR-SKU status:OPEN (optionally add assigned_location_id:gid://shopify/Location/...)
- Only on hold: use
manualHoldsFulfillmentOrders(query: "sku:YOUR-SKU")
- Fallback: query
orders then read their fulfillmentOrders
Example query: fulfillment_status:unfulfilled AND sku:YOUR-SKU
Validated GraphQL:
A) Direct fulfillmentOrders by SKU
query FulfillmentOrdersBySku($first: Int!, $query: String!) {
fulfillmentOrders(first: $first, query: $query) {
nodes {
id
status
order { id name }
lineItems(first: 10) { nodes { id sku remainingQuantity } }
}
}
}
B) Only those on hold
query ManualHoldsFulfillmentOrdersBySku($first: Int!, $query: String!) {
manualHoldsFulfillmentOrders(first: $first, query: $query) {
nodes {
id
status
fulfillmentHolds { id reason }
lineItems(first: 10) { nodes { id sku remainingQuantity } }
}
}
}
C) Orders → fulfillmentOrders fallback
query OrdersBySkuUnfulfilled($first: Int!, $query: String!) {
orders(first: $first, query: $query) {
nodes {
id
name
fulfillmentOrders(first: 10) {
nodes {
id
status
lineItems(first: 10) { nodes { id sku remainingQuantity } }
}
}
}
}
}
Act on the returned fulfillmentOrders
Remove holds
mutation ReleaseHold($id: ID!) {
fulfillmentOrderReleaseHold(id: $id) {
fulfillmentOrder { id status }
userErrors { field message }
}
}
Request fulfillment (third‑party service)
mutation SubmitFulfillmentRequest($id: ID!, $message: String) {
fulfillmentOrderSubmitFulfillmentRequest(id: $id, message: $message) {
originalFulfillmentOrder { id requestStatus }
submittedFulfillmentOrder { id requestStatus }
unsubmittedFulfillmentOrder { id requestStatus }
userErrors { field message }
}
}
Merchant‑managed fulfillment
mutation FulfillmentCreate($input: FulfillmentInput!) {
fulfillmentCreate(fulfillment: $input) {
fulfillment { id status }
userErrors { field message }
}
}
Docs
Info on how to use the Dev MCP yourself for more personalised responses: Meet Shopify Dev Assistant: Build Shopify Apps Faster Than Ever (2025) - Shopify Ireland