# Availability

The Stock module exposes read-only availability for Commerce products: a batch endpoint for listing pages and a single-product endpoint that can drill down to one variant. Both routes live under `/v1/api/stock`, require the `stock:read` scope on your API key, and require the `stock` module to be enabled for your store (`403 {"error":"Module not enabled: stock"}` otherwise).

## The availability object

| Field | Type | Description |
| --- | --- | --- |
| `product_id` | string (uuid) | The Commerce product id. |
| `variant_id` | string (uuid) or null | Only on the single-product endpoint. Echoes the `variant_id` query parameter; `null` when omitted. |
| `tracked` | boolean | `false` when `stock_status` is `untracked`, `true` otherwise. |
| `available` | integer or null | Sum of `quantity - reserved` across the store's active stock locations, in integer units. `null` when untracked. |
| `stock_status` | string | One of `untracked`, `in_stock`, `low_stock`, `out_of_stock`, `backorder`. |

`stock_status` is derived as follows:

- No stock rows exist for the product (or variant): `untracked`.
- `available` is 0 or less: `backorder` if any stock row allows backorders, otherwise `out_of_stock`.
- Any stock row is at or below its low-stock threshold: `low_stock`.
- Otherwise: `in_stock`.

## GET /v1/api/stock/availability

Batch product-level availability for up to 100 products in one request. The response contains one entry per known product id; unknown ids are silently omitted (the endpoint never returns 404 for an unknown id in the batch). This endpoint is product-level only and has no variant keys; use the single-product endpoint for variant availability.

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `ids` | array of string (uuid) | Yes | Product ids, sent as repeated `ids[]=...` parameters. Maximum 100 entries; each entry must be a UUID. |

```bash title="Request"
curl --globoff "https://api.borkol.com/v1/api/stock/availability?ids[]=7c1f4b2e-9a3d-4e5f-8b6c-0d1e2f3a4b5c&ids[]=8d2e5c3f-0b4e-4f6a-9c7d-1e2f3a4b5c6d" \
  -H "Authorization: Bearer {api_key}"
```

```javascript title="Request (JS)"
const params = new URLSearchParams();
for (const id of productIds) params.append("ids[]", id);
const res = await fetch(
  `https://api.borkol.com/v1/api/stock/availability?${params}`,
  { headers: { Authorization: `Bearer ${apiKey}` } },
);
const { data } = await res.json();
```

Status: `200 OK`.

```json title="Response"
{
  "data": [
    {
      "product_id": "7c1f4b2e-9a3d-4e5f-8b6c-0d1e2f3a4b5c",
      "tracked": true,
      "available": 42,
      "stock_status": "in_stock"
    },
    {
      "product_id": "8d2e5c3f-0b4e-4f6a-9c7d-1e2f3a4b5c6d",
      "tracked": false,
      "available": null,
      "stock_status": "untracked"
    }
  ]
}
```

### Errors

- `422` when `ids` is missing, has more than 100 entries, or any entry is not a UUID. Per-entry failures appear under keyed error fields, for example `errors["ids.0"]`.
- `403` `{"error":"Module not enabled: stock"}` when the Stock module is disabled.
- `403` `{"message":"Invalid ability provided."}` when the API key lacks the `stock:read` scope.

## GET /v1/api/stock/products/{productId}

Availability for a single product, optionally scoped to one variant. When `variant_id` is given, the response reflects only that variant's stock rows.

### Path parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `productId` | string (uuid) | Yes | A Commerce product id. |

### Query parameters

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `variant_id` | string (uuid) | No | Restrict the calculation to this variant's stock rows. Echoed back in the response; `null` when omitted. An unknown `variant_id` does not 404; it simply reports `untracked`. |

```bash title="Request"
curl "https://api.borkol.com/v1/api/stock/products/7c1f4b2e-9a3d-4e5f-8b6c-0d1e2f3a4b5c?variant_id=3a4b5c6d-7e8f-4a1b-9c2d-0e1f2a3b4c5d" \
  -H "Authorization: Bearer {api_key}"
```

Status: `200 OK`.

```json title="Response"
{
  "data": {
    "product_id": "7c1f4b2e-9a3d-4e5f-8b6c-0d1e2f3a4b5c",
    "variant_id": "3a4b5c6d-7e8f-4a1b-9c2d-0e1f2a3b4c5d",
    "tracked": true,
    "available": 3,
    "stock_status": "low_stock"
  }
}
```

### Errors

- `404` when the product id does not exist for this store.
- `403` module and scope errors as on the batch endpoint.
