# Reorder status

Set reorder points, then review status and the exact projected gap.

Canonical HTML: https://developer.shelfcycle.com/guides/reorder-status

Set product-and-warehouse reorder points, then find the positions that need attention with current stock, demand context, projected availability, the exact threshold gap, and complete status counts.

Use `GET /reorder-status` for dashboards, worklists, and connected assistants that need to review the reorder points already configured in ShelfCycle.

## Access

Reading status requires `reorder:read` plus the acting user's current access to view Products and Lots. Setting or clearing thresholds requires `reorder:write` and current organization access. `GET /me` reports these through `effectiveCapabilities.reorder.status` and `effectiveCapabilities.writeReadiness.reorderPoints.write`.

```bash
curl "$SHELFCYCLE_API_BASE_URL/reorder-status?status=below_on_hand&limit=25" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "X-ShelfCycle-Client: Reorder attention dashboard"
```

## Set or clear reorder points

`POST /reorder-points` accepts 1 to 50 product-and-warehouse positions in one request. Every `reorderPoint` is an integer. Use the product's base unit for variable products and package count for fixed products.

Preview a group before saving it:

```bash
curl "$SHELFCYCLE_API_BASE_URL/reorder-points?dryRun=true" \
  -X POST \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "warehouseId": "warehouse-id",
        "productId": "drum-product-id",
        "reorderPoint": 12
      },
      {
        "warehouseId": "warehouse-id",
        "productId": "tote-product-id",
        "reorderPoint": 4
      }
    ]
  }'
```

Remove `dryRun=true` to apply the same group. A repeated value returns `changed: false`. Send zero or a negative value to clear an existing reorder point.

```json
{
  "data": {
    "changed": true,
    "items": [
      {
        "warehouseId": "warehouse-id",
        "productId": "drum-product-id",
        "reorderPoint": 12,
        "changed": true
      }
    ]
  }
}
```

After saving, use `GET /reorder-status` to confirm the configured thresholds alongside current availability and demand.

## Filters

| Parameter | Use it for |
| --- | --- |
| `productId` | One exact product. |
| `productFamilyId` | Configured products in one family. |
| `warehouseId` | Configured products at one physical warehouse. |
| `status` | `below_on_hand`, `below_projected`, or `ok`. |
| `limit` | Rows per page from 1 to 100. The default is 25. |

Filters can be combined on the first request. Status counts continue to cover the complete product, family, and warehouse selection before the status filter, so one filtered response can still power an accurate summary.

## Read a reorder row

```json
{
  "data": [
    {
      "type": "reorder_status",
      "product": {
        "id": "product-id",
        "code": "IPA-DRUM",
        "family": { "id": "product-family-id", "name": "Isopropyl Alcohol" }
      },
      "warehouse": { "id": "warehouse-id", "name": "Main Warehouse" },
      "basis": {
        "type": "package_count",
        "unitOfMeasure": "GALLON",
        "packaging": { "id": "packaging-id", "name": "55 gallon drum" }
      },
      "reorderPoint": "12",
      "onHand": "16",
      "allocated": "3",
      "committed": "5",
      "projectedAvailable": "8",
      "projectedDeficit": "4",
      "status": "below_projected"
    }
  ],
  "meta": {
    "configuredRows": 18,
    "returnedRows": 1,
    "hasMore": false,
    "statusCounts": {
      "scope": "entity_filters_excluding_status",
      "belowOnHand": 4,
      "belowProjected": 3,
      "ok": 11
    },
    "configuredCoverage": {
      "configuredProducts": 14,
      "activeProducts": 92,
      "excludedArchivedConfigured": 2,
      "excludedDirectShipConfigured": 0
    },
    "nextCursor": null,
    "ordering": "product_id_asc_warehouse_id_asc",
    "observedAt": "2026-08-24T16:30:00.000Z",
    "currentState": true,
    "snapshotIsolatedAcrossRequests": false,
    "requestId": "request-id"
  }
}
```

All quantities are decimal strings in the row's stated basis. `projectedAvailable` is on hand less allocated and committed quantities. `projectedDeficit` is the gap between the configured reorder point and projected availability, with `0` when projected availability meets or exceeds the threshold.

Use `projectedDeficit` to show how far a position sits below its configured threshold. Pair it with `allocated` and `committed` to explain the current demand behind the result while keeping the row's quantity basis visible.

| Status | Meaning | Display label |
| --- | --- | --- |
| `below_on_hand` | Current on-hand quantity is below the configured reorder point. | Critical |
| `below_projected` | On hand is at or above the reorder point, but projected availability after allocations and committed demand is below it. | Low |
| `ok` | Projected availability is at or above the configured reorder point. | OK |

> **Planning context**: Reorder status includes committed demand and does not include inbound or on-order quantities. Keep that distinction visible when presenting a below-threshold result.

## Use complete counts

Use `meta.statusCounts` for summaries instead of counting the current page. The counts cover the selected product, family, and warehouse population before the `status` filter.

Use `meta.configuredCoverage` to explain how much of the active product population has reorder points configured. For the example above, say "14 of 92 active products have reorder points configured; 4 configured positions are Critical and 3 are Low." Do not describe that result as the health of all 92 products.

A response with `configuredRows: 0` means no reorder points are configured in the selected scope. A status-filtered response can return no rows while `statusCounts` still shows the complete configured population.

## Continue and refresh

When `meta.hasMore` is true, call the endpoint again with `meta.nextCursor` by itself:

```bash
curl "$SHELFCYCLE_API_BASE_URL/reorder-status?cursor=$NEXT_CURSOR" \
  -H "Authorization: Bearer $SHELFCYCLE_API_KEY"
```

Do not combine a cursor with the original filters. The cursor retains the selection, status, page size, ordering, organization, and key needed for continuation.

Each response is a current view observed at `meta.observedAt`. For a complete refresh, restart from the original filters and continue through the newly returned cursors.

> **Guardrail**: Keep each row's product, warehouse, quantity basis, and unit with its quantities. Compare or add values only when that context makes the operation meaningful.
