Skip to content
v0.3

read.internal.stock_levels

Stock per PRODUCT in ONE warehouse (on hand, reserved, available, backordered — aggregated over the product’s SKUs, with the SKU lines inline), for the operator’s stock screen. Pages by PRODUCT: limit counts products, never SKUs. Lists the products this warehouse stocks something of, and each row carries EVERY SKU of the product: the ones with no stock line here come with present: false, zeroed counters and a null state — absent is not zeroed, so they are excluded from zeroed_count and counted in missing_count. The warehouse is the SCOPE of the answer, not a filter over all of them; availability narrows to in_stock (something sellable) | low (some SKU at 1..5) | partial (some stocked SKU at zero, not all) | out (every stocked SKU at zero). Searches product title and SKU code — matching a code returns the whole product. Products with more than 50 SKUs come with skus truncated and skus_truncated: true; the aggregates always cover every SKU. Internal face only.

  • Surface: GET /v1/read/internal/stock_levels · MCP tool read.internal.stock_levels
  • Auth:Internal read (operator) — a tenant credential is REQUIRED; requires the logistics.read scope. The tenant is resolved from the CALLER’s identity, never from store. Personal fields come back MASKED for an actor without pii.read (the shape is unchanged).
{
"properties": {
"availability": {
"enum": [
"all",
"in_stock",
"low",
"partial",
"out"
],
"type": "string"
},
"limit": {
"default": 25,
"maximum": 200,
"minimum": 1,
"type": "integer"
},
"page": {
"default": 1,
"maximum": 9007199254740991,
"minimum": 1,
"type": "integer"
},
"q": {
"minLength": 1,
"type": "string"
},
"sort": {
"enum": [
"product_asc",
"available_asc",
"recent"
],
"type": "string"
},
"warehouse_id": {
"type": "string"
}
},
"type": "object"
}

Open (unknown) — this capability does not declare an output schema.

validation_failed (400) · not_found (404) · unauthorized (401) · forbidden (403)