---
title: "Bulk read stockchanges"
method: GET
path: "/v1/stock-changes"
tags: ["StockChanges"]
---

# Bulk read stockchanges

`GET /v1/stock-changes`

## Request

- Base URL: `https://api.finalpos.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.finalpos.com/v1/stock-changes`
- Auth: API key in header `x-api-key`

Retrieves a list of stockchanges. Supports filtering by fields, sorting, and pagination.

## Query parameters

- `skip` number
- `limit` number
- `sortBy` 'createdAt' | 'updatedAt'
- `sortOrder` 'asc' | 'desc'
- `createdAt` object
  - `gte` string, date-time
  - `lte` string, date-time
  - `gt` string, date-time
  - `lt` string, date-time
- `updatedAt` object
  - `gte` string, date-time
  - `lte` string, date-time
  - `gt` string, date-time
  - `lt` string, date-time

## Response `200`

Successfully retrieved list of items

- object
  - `data` StockChangeResponseDto[]
    - `id` string: Unique identifier for the StockChange.
    - `createdAt` string, date-time: Timestamp when the StockChange was created.
    - `updatedAt` string, date-time: Timestamp when the StockChange was last updated.
    - `companyId` string: Company ID associated with the StockChange.
    - `userId` string: User ID who made the stock change.
    - `source` string: Source of the Stock Change Event.
    - `productId` string: Product ID affected by the stock change.
    - `variantId` string: Variant ID affected by the stock change.
    - `variantName` string: How `variantId` read on the day — attribute values or SKU, frozen at write. A rename or a deletion must not rewrite the ledger; the id above stays so the variant is findable historically. Absent on rows written before names were frozen — resolve those by id.
    - `outletId` string: Outlet ID where the stock change occurred.
    - `baseAction` 'ADD' | 'REMOVE' | 'RECOUNT' | 'SKIP': Base action type for the stock change.
    - `specificAction` 'STOCK_RECEIVED' | 'INVENTORY_RECOUNT' | 'DAMAGE' | 'THEFT' | 'LOSS' | 'RESTOCK_RETURN' | 'REFUND_RESTOCK_RETURN' | 'REFUND_DAMAGE' | 'SALE' | 'COMPOSED_FOR_SALE' | 'UNIT_FAMILY_CHANGED' | 'TRANSFER' | 'BULK_RECOUNT' | 'APPLIED_FROM_WOO' | 'PO_RECEIVED' | 'EXTERNAL_SALE' | 'EXTERNAL_RESTOCK' | 'CUSTOM': Specific action type for the stock change.
    - `customActionId` string: The company action used when `specificAction` is CUSTOM.
    - `customActionName` string: How the custom action was named on the day — renaming it later does not rewrite history.
    - `quantity` number: How much the shelf moved, in WHOLE BASE UNITS of the family — grams, millilitres, pieces. Not in `unitId`: that names the unit the movement was keyed in, and the two differ by the unit's ratio. `unitQuantity` is the same movement as the person keyed it.
    - `updatedQuantity` number: On-hand level after the change, in the SAME base units as `quantity` — again not in `unitId`. It has no keyed counterpart: a reader renders it by dividing with the ratio, so unlike `unitQuantity` this figure does restate if the unit is later re-rated.
    - `unitId` string: Unit this movement was keyed in — the one the person saw on screen. Differs from what moved when a variant draws from a sibling pool: three burgers leave a kilogram pool. Absent on entries written before units existed, which are pieces.
    - `unitQuantity` number: The amount as keyed, in `unitId` — frozen, never recomputed. `quantity` stays in base units for arithmetic; this is what the movement meant to the person who made it. Dividing the base amount by the unit ratio at read time would rewrite history: receive 5 burgers today, double the burger's weight tomorrow, and yesterday's entry would claim 2.5.
    - `viaVariantId` string: The variant the movement was keyed through when it is not `variantId` — the Glass that was sold when a Bottle pool drains. The row lands on the pool owner, whose balance moved; without this the ledger never names what was actually sold. Absent on direct movements.
    - `viaVariantName` string: How `viaVariantId` read on the day — same freeze as `variantName`.
    - `compositeProductId` string: The composite this item was sold (or refunded) in — "Sold in Combo #1" (FT-83, D26). Absent on every other movement.
    - `compositeName` string: How that composite read on the day — same freeze as `variantName`.
    - `idempotencyKey` string: Caller-supplied key that lets the writer safely retry a stock mutation. The unique index drops duplicates so the same logical change is not applied twice. Keys prefixed `sarnia:` are RESERVED for the FinalPOS sync lane — its outbound subscriber skips those events as its own writes, so external callers must not use that prefix or their movements will not sync to connected platforms.
  - `meta` object
    - `count` number: Total number of items matching the query filters
    - `skip` number: Number of items skipped
    - `limit` number: Maximum number of items returned

## Other responses

- `400`: Bad request. Returns validation errors or other request-related errors.
- `404`: The resource(s) were not found.

---

[API](https://skmtc.dev/finalpos/apis/final-pos-public-api.md) · [All operations](https://skmtc.dev/finalpos/apis/final-pos-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/finalpos/apis/final-pos-public-api/revisions/6a6842dcb479?raw)
