The inventory_levels/update webhook gives you state, not a diff. Its available field is the new quantity; the payload has no previous value, delta, or adjustment reason.
For best-effort near-real-time handling, store the last known available value for each inventory_item_id and location_id, then calculate:
delta = new_available - previous_available
After processing, replace the stored value with the new one.
There are a few important reliability requirements:
-
Deduplicate deliveries using X-Shopify-Webhook-Id.
-
Use X-Shopify-Triggered-At or updated_at to organize out-of-order deliveries.
-
Periodically reconcile current inventory through the Admin API.
I would not treat that calculated delta as a complete audit log. Shopify does not guarantee webhook ordering or delivery, and rapid changes can result in multiple webhook payloads containing the same final available value.
For the manual-adjustment audit, Shopify now has a better source: the ShopifyQL inventory_adjustment_history schema. It exposes inventory_adjustment_change as a signed delta, along with the staff member, reason, location, inventory state, app, and reference document.
A starting query for staff-associated adjustments is:
FROM inventory_adjustment_history
SHOW inventory_adjustment_change
WHERE staff_member_name IS NOT NULL
GROUP BY second, inventory_adjustment_id, product_variant_sku,
inventory_location_name, inventory_state,
staff_member_name, inventory_change_reason
HAVING inventory_adjustment_change != 0
SINCE startOfDay(-30d) UNTIL today
ORDER BY second DESC
LIMIT 1000
Including inventory_state lets you distinguish Available changes from Committed, Reserved, Incoming, and other inventory states.
If you call this through the Admin API, shopifyqlQuery requires API version 2025-10 or later, the read_reports scope, and Level 2 protected customer data access. ShopifyQL is analytics data rather than a real-time event stream.
So I would use the webhook plus stored state for operational synchronization, and inventory_adjustment_history for the historical adjustment audit. I would not classify an update as manual merely because it could not be matched to a recent order or fulfillment.