Inventory
Stock is tracked per variant (and at the item level for items without
variants). Every row exposes three quantities plus a derived status. Examples
reuse the api() helper.
| Field | Meaning |
|---|---|
onHand | Physical units in stock |
reserved | Units held (e.g. for pending orders) |
available | onHand − reserved — what a storefront can sell |
stockStatus | IN_STOCK · LOW_STOCK · OUT_OF_STOCK (derived) |
lowStockThreshold | At/below available, status becomes LOW_STOCK (0 disables) |
Read stock
// Public — a storefront checking availability for a PDP
const rows = await api<Inventory[]>(`/public/inventory/${itemId}`);
// Merchant — filterable, enriched with item name/slug
const { rows: m } = await api<{ rows: Inventory[] }>(
"/merchant/inventory?stockStatus=LOW_STOCK", { token },
);
// Merchant — counts by status for a dashboard
const summary = await api("/merchant/inventory/summary", { token });
// → { IN_STOCK, LOW_STOCK, OUT_OF_STOCK, total }Mutations
All mutations are POST /merchant/inventory/:id/<action> where :id is the
inventory row id. Mutations require inventory:adjust; Owner/Admin retain
broad access, and Staff needs that group.
// Adjust on-hand by a signed delta (receiving stock, shrinkage, corrections)
await api(`/merchant/inventory/${id}/adjust`, { method: "POST", token,
body: JSON.stringify({ delta: 24, reason: "Received PO #1182" }) });
// Hold units (moves available → reserved). Rejects if quantity > available.
await api(`/merchant/inventory/${id}/reserve`, { method: "POST", token,
body: JSON.stringify({ quantity: 2, reason: "manual hold" }) });
// Release a hold (reserved → available). Rejects if quantity > reserved.
await api(`/merchant/inventory/${id}/release`, { method: "POST", token,
body: JSON.stringify({ quantity: 2 }) });
// Low-stock alarm. 0 disables it. Recomputes stockStatus immediately.
await api(`/merchant/inventory/${id}/threshold`, { method: "POST", token,
body: JSON.stringify({ lowStockThreshold: 5 }) });adjust rejects a delta that would push available negative. reason is
required on adjust (1–200 chars) and optional on reserve/release — it's
written into the audit log so stock movements are
traceable.
Related
- Catalog: products & variants — what stock attaches to
- Audit log — every adjustment is recorded