> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sitestorepro.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Inventory and Multi-Warehouse Management in Site Store Pro

> Track stock levels across multiple warehouses, run bulk CSV imports, sync inventory via webhook API, and configure multi-location fulfillment in Site Store Pro.

Site Store Pro's inventory system supports multi-location stock tracking per variant — combining shelf stock, primary warehouse stock (tagged via a Primary Warehouse Location selector), and location-dependent child warehouse inventory levels into a calculated total. You can update stock in bulk via CSV import at `/admin/ecommerce/inventory`, or push real-time updates from any external WMS or ERP using the `POST /webhooks/inventory-update` webhook API. Multi-warehouse fulfillment and facility locations are managed through the Warehouse Locations panel in the Shipping Console (`/admin/ecommerce/shipping?tab=warehouses`).

## Inventory Page

The main inventory management interface is at `GET /admin/ecommerce/inventory` (paginated **25 items per page**).

From this page you can view all variants' stock levels across locations, edit individual records, run bulk CSV imports, and navigate directly to manage warehouse locations.

***

## Warehouse Stock Calculations & Primary Location Selector

Site Store Pro uses a **multi-warehouse stock tracking** model per variant:

| Value                          | Field / Relation               | Description                                                                     |
| ------------------------------ | ------------------------------ | ------------------------------------------------------------------------------- |
| **Available Stock**            | `quantity_available`           | Physical shelf/pick stock under your direct control                             |
| **Primary Warehouse Facility** | `location_id`                  | Primary default warehouse facility selected for the main warehouse stock level  |
| **Main Warehouse Stock Level** | `warehouse_stock_level`        | Remote/main warehouse stock quantity assigned to the primary warehouse facility |
| **Child Warehouse Stocks**     | `product_inventory_warehouses` | Warehouse-specific inventory levels assigned per additional warehouse location  |
| **Reserved Stock**             | `reserved_stock`               | Quantities set aside or allocated to pending orders                             |

<Note>
  **Mutual Exclusion Rule**: The **Primary Warehouse Facility** selector and **Child Warehouse Location** stock lines are mutually exclusive. Once a facility is assigned as Primary (`location_id`), it is excluded from selection in child warehouse lines, preventing duplicate warehouse counting.
</Note>

### Calculation Toggle

An admin checkbox (`use_warehouse_stock = 1`) on each inventory record controls which formula is used:

<Tabs>
  <Tab title="Toggle ON">
    ```text theme={null}
    Available Stock + Main Warehouse Stock + SUM(Child Warehouse Stocks) - Reserved Stock = Calculated Inventory Total
    ```

    Shelf stock, main warehouse stock, and all assigned child warehouse inventory levels are summed, then reserved quantities are deducted.
  </Tab>

  <Tab title="Toggle OFF">
    ```text theme={null}
    Available Stock - Reserved Stock = Calculated Inventory Total
    ```

    Only local shelf stock is used; all main and child warehouse stock levels are ignored in the calculation.
  </Tab>
</Tabs>

### Real-Time Calculator & Child Builder

A **dynamic totals preview** is displayed on the product variant inventory edit panel. As you adjust `Available Stock`, `Main Warehouse Stock`, `Reserved Stock`, or add/modify **Warehouse Location Stock Lines**, the calculated **Total Available Calculated Stock** updates in real time — before clicking Save.

A direct link to **Manage Warehouses & Fulfillment Locations** (`/admin/ecommerce/shipping?tab=warehouses`) is included directly inside the variant inventory section.

***

## Bulk CSV Import

Update large numbers of SKUs at once using the CSV import tool built directly into the **Stock Control panel** at `/admin/ecommerce/inventory`.

### File Format

Files may be **comma-separated** or **pipe-separated**:

```text theme={null}
SKU|stock_level|warehouse_level|locationid
```

**Example rows:**

```text theme={null}
SKU-AAA-001|50|200|1
SKU-BBB-002,30,100,2
SKU-CCC-003|0|500|1
```

### Field Mappings

| Column            | Maps To                 | Description                                                             |
| ----------------- | ----------------------- | ----------------------------------------------------------------------- |
| `SKU`             | Auto-match by SKU       | Matches an existing product variant by its SKU                          |
| `stock_level`     | `quantity_available`    | Updates the available/shelf stock level                                 |
| `warehouse_level` | `warehouse_stock_level` | Updates the main external warehouse stock level                         |
| `locationid`      | `location_id`           | Assigns or moves the record to the specified primary warehouse location |

<Note>
  The import **auto-matches by SKU**. Any row whose SKU does not match an existing variant is skipped and logged in the import report.
</Note>

***

## Automated Inventory Webhook API

For real-time inventory sync from external WMS, ERP, or fulfillment systems, Site Store Pro provides a dedicated webhook endpoint that supports both primary and location-dependent warehouse updates.

### Endpoint

```http theme={null}
POST /webhooks/inventory-update
```

<Note>
  CSRF verification is **bypassed automatically** for this endpoint — no CSRF token is required in webhook payloads.
</Note>

### Authentication

The request must include **one** of the following credentials, all matching the `INVENTORY_WEBHOOK_SECRET` environment variable:

| Method          | How to Pass                           |
| --------------- | ------------------------------------- |
| Custom header   | `X-Inventory-Webhook-Token: <secret>` |
| Bearer token    | `Authorization: Bearer <secret>`      |
| Query parameter | `?api_token=<secret>`                 |

### Request Payload

```json theme={null}
{
  "sku": "SKU-AAA-123",
  "stock_level": 150,
  "warehouse_level": 80,
  "use_warehouse_stock": true,
  "location_id": 2,
  "warehouse_stocks": [
    { "warehouse_location_id": 1, "stock_level": 50 },
    { "warehouse_location_id": 2, "stock_level": 30 }
  ]
}
```

| Field                                      | Type    | Description                                              |
| ------------------------------------------ | ------- | -------------------------------------------------------- |
| `sku`                                      | string  | SKU of the variant to update (Required)                  |
| `stock_level`                              | integer | New available/shelf stock level                          |
| `warehouse_level`                          | integer | New main external warehouse stock level                  |
| `use_warehouse_stock`                      | boolean | Whether to apply the warehouse stock calculation formula |
| `location_id`                              | integer | Primary warehouse location ID                            |
| `warehouse_stocks`                         | array   | Optional array of warehouse-specific stock levels        |
| `warehouse_stocks.*.warehouse_location_id` | integer | Valid ID from `warehouse_locations` table                |
| `warehouse_stocks.*.stock_level`           | integer | Assigned stock quantity for this warehouse location      |

### Response

A successful call returns the **JSON representation of the updated inventory record** including assigned warehouse child stocks and the newly calculated inventory total.

<CodeGroup>
  ```json Success Response theme={null}
  {
    "status": "success",
    "message": "Inventory for SKU 'SKU-AAA-123' updated successfully.",
    "data": {
      "id": 42,
      "variant_id": 17,
      "sku": "SKU-AAA-123",
      "quantity_available": 150,
      "warehouse_stock_level": 80,
      "reserved_stock": 5,
      "use_warehouse_stock": true,
      "location_id": 1,
      "calculated_total": 305,
      "warehouse_stocks": [
        { "warehouse_location_id": 2, "stock_level": 50 },
        { "warehouse_location_id": 3, "stock_level": 30 }
      ],
      "updated_at": "2026-08-15T03:26:14.000000Z"
    }
  }
  ```

  ```json Error Response (Unauthorized) theme={null}
  {
    "status": "error",
    "message": "Unauthorized: Invalid or missing webhook token."
  }
  ```
</CodeGroup>

***

## Multi-Warehouse Locations Architecture

### Database Schema

The `warehouse_locations` table stores facility details, while `product_inventory_warehouses` links specific stock levels to inventory records:

```text theme={null}
ProductVariant
  └── HasOne → ProductInventory (`products_inventory`)
                 └── HasMany → ProductInventoryWarehouse (`product_inventory_warehouses`)
```

| Table                          | Column                                                                     | Description                                            |
| ------------------------------ | -------------------------------------------------------------------------- | ------------------------------------------------------ |
| `warehouse_locations`          | `id`, `name`, `code`, `address`, `state_code`, `country_code`, `is_active` | Facility metadata and regional location codes          |
| `product_inventory_warehouses` | `product_inventory_id`, `warehouse_location_id`, `stock_level`             | Dependent stock levels assigned per warehouse location |

### Fulfillment Origin & Available Stock Resolution

At checkout and storefront product views, Site Store Pro resolves available stock via:

```php theme={null}
$variant->inventory->available_stock
// or for location-based address matching:
$variant->getStockForFulfillment($countryCode, $stateCode)
```

<Steps>
  <Step title="Region Match">
    Checks for an **active warehouse** whose `state_code` and/or `country_code` matches the buyer's shipping address.
  </Step>

  <Step title="Calculated Total Fallback">
    If no regional match is found, **sums available shelf stock, main warehouse stock, and child warehouse stock levels** (minus reserved stock) to determine total available inventory.
  </Step>

  <Step title="Order Deduction">
    At point of order confirmation, stock is decremented from the designated warehouse location closest to the buyer.
  </Step>
</Steps>

***

## Warehouse Locations Admin Panel

Warehouse location management is available in the **Warehouse Locations sub-panel** inside the Shipping Console:

`/admin/ecommerce/shipping?tab=warehouses`

Full **CRUD operations** are supported:

<CardGroup cols={3}>
  <Card title="Add Location" icon="plus">
    Create a new fulfillment warehouse with name, code, address, region codes, and ShipStation carrier ID
  </Card>

  <Card title="Edit Location" icon="pencil">
    Update any field on an existing warehouse, including activating or deactivating it
  </Card>

  <Card title="Delete Location" icon="trash">
    Remove a warehouse location (ensure all inventory records are reassigned first)
  </Card>
</CardGroup>

<Warning>
  Deleting a warehouse location that still has associated child inventory records will cascade and remove child inventory entries for that location. Reassign or zero-out location stock levels before deletion.
</Warning>
