Activity history & stock timeline
The per-product timeline of stock movements and record changes — what appears, how the running balance works, who did what, and the API behind it.
Every product, variant, assembly, bundle, work order, and warehouse stock row has an Activity History: stock movements and record changes on one timeline, newest first, with a running on-hand balance. It’s the answer to “why is this number what it is.”
Where it is
- Product page → the Activity History card near the bottom. Also on variant, assembly, bundle, and work-order pages, and as Movement history in the warehouse stock item sheet.
- The header reads “N stock movements · M changes”, with one filter: All activity / Stock movements / Changes only.
- Each row: timestamp, an event badge, the quantity (
+12/−3), the balance before → after, a one-line summary. Expand a row for location, SKU, reason, the reference it came from (linked when it’s an order, PO, work order, or invoice), who did it, and per-field old → new values.
Stock movements
Every change to on-hand is a movement of one of these kinds:
| Movement | Written by |
|---|---|
RECEIPT | Receiving a purchase order |
SALE | Marking an order fulfilled (this is the only thing a sale writes — status changes don’t) |
ADJUSTMENT | Manual adjustments, with a reason |
COUNT | Applying a stock count — including the zeroing pass of a full count |
TRANSFER_OUT / TRANSFER_IN | Warehouse transfers and bin moves, as a matched pair |
BUILD_CONSUME / BUILD_PRODUCE | Completing a work order: parts out, finished units in |
UNBUILD_CONSUME / UNBUILD_PRODUCE | Unbuilding: the reverse |
The running balance
The before → after figures are the SKU’s on-hand in that warehouse, across all its bins. Bins partition where stock sits; the balance is the warehouse total, so a bin move shows as two movements that net to zero.
The balance is anchored to the present: the newest row’s after equals today’s on-hand, and history is walked backwards from there. Stock that existed before movement tracking began therefore shows as a constant offset at the start of the timeline rather than as a phantom receipt.
Record changes
Alongside movements, the timeline shows structural events on the product and its variants: created, promoted from a source SKU, merged, listed on a channel, type converted, archived or restored, trashed or restored, bill-of-materials edits, and warehouse events such as shipped_short (an order shipped beyond counted stock) and inventory_received.
What it deliberately does not show: ordinary field edits — a price, name, or SKU change on the product form — and import or channel-sync events, which are logged against the source or channel rather than the product. For “who changed this price,” see the price-change history on the channel instead.
Who did it
Each activity entry records how it was made:
| Shown as | Meaning |
|---|---|
| A user’s email | A signed-in person, in the admin or through a connector authorized as that person (for example Claude via the Foundry connector) |
| API key | A fims_* API key — an integration, an automation, or Claude connected with a key |
| Webhook (incoming from a channel) | Triggered by a channel’s webhook, such as a new order |
| System (automatic) | A scheduled job — reconciles, auto-listing, nightly rollups |
Entries written before attribution existed have no actor and show nothing on the By line. Stock movements themselves carry the reason and reference, not an actor — the actor is on the adjustment or count event that produced them.
API
GET /activity-logs/timeline returns the same merged feed. Scope it with one of productId, variantId, warehouseId, or binId (binId=unassigned for stock with no bin), or by referenceType + referenceId to see everything one order or work order caused. kind=all|stock|activity mirrors the UI filter; types= narrows to specific movement kinds; limit (max 100) and offset page through. Each entry is kind: "movement" (quantity, balanceBefore, balanceAfter, variant, warehouse, bin, reference) or kind: "activity" (action, changes, actor). Requires activity.read; movement rows additionally require warehouses.read, which every human role has.
For an org-wide view rather than one product’s, the Activity page in the sidebar lists everything with entity filters, and the Audit log covers security-relevant events.
Related
- Warehouse operations — counts, adjustments, and moves, and what each writes
- Trash & recovery — when a change needs undoing rather than explaining
- Authentication & API keys — key types and roles