# Get stock levels for products

```http
POST https://secure.yoprint.com/v1/api/store/{team_slug}/product_stock
```

- API version: v1
- Operation ID: `v1_public_misc_product_stock`
- Section: Products and catalog › [Product stock](https://developer.yoprint.com/reference/product-stock.md)
- Web page: https://developer.yoprint.com/reference/product-stock/v1-misc-product-stock/
- Authentication: `Authorization: Bearer YOUR_API_KEY`

Read-only: returns the shop stock you hold for each product you list. Nothing is reserved or moved. Stock adjustments, stock takes and transfers are not part of the public API.

For each product the answer has `id`, `type` and `total`: `stock_on_hand`, `stock_incoming` (on purchase orders not yet received), `stock_not_usable` and `qty_need_ordering`, as decimal strings with eight decimal places, such as `"24.00000000"` (`"0"` when no stock row or aggregate matches; parse them as decimals), summed over your warehouses or, with `warehouse_id`, for that warehouse only. `inventories` lists the stock rows behind the totals, one per warehouse.

Customer-owned stock and hidden or deleted stock rows are left out. `custom` items are skipped, so the answer can be shorter than the list you sent.

Type names differ by operation. Here and on Load a product for a sales order line, your own simple product is `db_simple`; on sales order lines the same product is `user_simple`. A variant is `db_variant` and a catalog product `db_catalog` everywhere.

## Permission

Any member of the team.

## Business rules

- Deleted simple products and variants are still answered; an id that does not exist fails the whole request with 404.

## Path parameters

- `team_slug` (string, required): Your team slug, shown as Team ID next to your API key in Profile. Example `your-team`.

## Request body

Content type `application/json`, required.

Fields:

- `product` (array of objects, required): At least 1 item.
  - Each item:
    - `type` (string, required): A simple product, a variant, a catalog product, or a custom line (skipped). One of: `"db_simple"`, `"db_variant"`, `"db_catalog"`, `"custom"`.
    - `id` (string, optional): Required unless `type` is `custom`. A product or variant hash id, or a catalog product id such as `ssa-B00000001`.
- `warehouse_id` (string, optional): A company location that holds stock. Leave it out to sum all of them.

### Example request

```bash
curl -X POST 'https://secure.yoprint.com/v1/api/store/your-team/product_stock' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Accept: application/json' \
  -H 'X-Yoprint-Decimal-Format: exact-v1' \
  -H 'Content-Type: application/json' \
  -d '{
    "product": [
      {
        "id": "nFsgC7x4kiFeXu",
        "type": "db_variant"
      },
      {
        "id": "ssa-B00000001",
        "type": "db_catalog"
      }
    ],
    "warehouse_id": "ILBTtiKrRcSSGA"
  }'
```

## Response

`200` Successful response.

Fields:

- `data` (array of objects, required)
  - Each item:
    - `id` (string, required)
    - `total` (object, required)
      - `qty_need_ordering` (string, required): How many sales orders need that stock does not cover. A decimal string, such as `"24.00000000"`; parse it as a decimal (`"0"` when there is no aggregate).
      - `stock_incoming` (string, required): A decimal string, such as `"24.00000000"`; parse it as a decimal.
      - `stock_not_usable` (string, required): A decimal string, such as `"24.00000000"`; parse it as a decimal.
      - `stock_on_hand` (string, required): A decimal string, such as `"24.00000000"`; parse it as a decimal (`"0"` when there is no stock row).
    - `type` (string, required): The line type: `db_simple`, `db_variant` or `db_catalog`.
    - `inventories` (array of objects, optional)
      - Each item:
        - `id` (string, optional)
        - `stock_incoming` (string | null, optional): A decimal string, such as `"24.00000000"`; parse it as a decimal.
        - `stock_on_hand` (string | null, optional): A decimal string, such as `"24.00000000"`; parse it as a decimal.
        - `trashed` (boolean, optional)
        - `warehouse_id` (string, optional)
- `status` (integer, required)
- `success` (boolean, required)

Example response:

```json
{
  "data": [
    {
      "id": "nFsgC7x4kiFeXu",
      "inventories": [
        {
          "id": "XBJYHgQMugO9Kv",
          "stock_incoming": "48.00000000",
          "stock_on_hand": "24.00000000",
          "trashed": false,
          "warehouse_id": "ILBTtiKrRcSSGA"
        }
      ],
      "total": {
        "qty_need_ordering": "0.00000000",
        "stock_incoming": "48.00000000",
        "stock_not_usable": "0.00000000",
        "stock_on_hand": "24.00000000"
      },
      "type": "db_variant"
    }
  ],
  "status": 200,
  "success": true
}
```

## Errors

- `401` The API key is missing or wrong (`unauthenticated`).
- `403` You are not allowed to do this. `api_access_not_in_plan`: your team's plan doesn't include API access (Pro and above, with an active subscription or trial), so every request answers this until the team upgrades. When your role lacks the permission the operation needs, the body is only `{"message": "Insufficient Permission"}`. Other refusals use the error envelope, with `unauthorized` or `user_is_not_authorized`.
- `404` Not found. `page_not_found`: the team slug is unknown, you are not a member of the team, or an id in the path is not one of this team's. `code: null`, with a message that starts "No query results for": there is no record with that id.
  - When: An id does not exist for its `type`. Nothing is returned for the others. `error.code` is null and `error.message` names the record type. Fix: Check each id and type.
- `422` The request was refused and changed nothing. `validation_failed` lists what to fix in `error.fields`; other codes name a business rule, explained in `error.message`. A few checks answer with only `{"message": "..."}`. An operation that calls another service (a payment provider, a carrier, an accounting app) can answer `connect_timeout` ("Please retry again") when that service does not answer in time: the change may or may not have happened there, so read the record back before you retry.
  - When: `product` is empty, a `type` is not allowed, or an `id` is missing. `error.code` is `validation_failed`. Fix: Fix each field named in `error.fields`; its keys are field paths such as `contact.0.phone`.

## Notes

- This is your own stock. A supplier's stock comes from Get live supplier inventory.

## Related

- [Get live supplier inventory for catalog products](https://developer.yoprint.com/reference/supplier-catalog/v1-real-time-data-fetcher-inventory.md): `POST /v1/api/store/{team_slug}/real_time_data_fetcher/inventory`
- [Load a product for a sales order line](https://developer.yoprint.com/reference/products/v1-hydrate-imported-product.md): `POST /v1/api/store/{team_slug}/hydrate_product`
- [List company locations](https://developer.yoprint.com/reference/company-locations/v1-location-index.md): `GET /v1/api/store/{team_slug}/setting/location`
