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

# Products, Categories, and Inventory in Mutasib

> Manage the items your shop sells. Learn about the product data model, custom categories, barcode lookup, and OpenFood integration.

Products are the items your shop sells, and every product belongs to exactly one shop. Each product record tracks not just the name and price, but also cost, stock level, barcode, and unit of measure. Whether you're running a small bakery or a large electronics store, the product model gives you the flexibility to represent your catalog accurately.

## Product Data Model

The table below covers every key field in the `ProductOut` schema returned by the API.

| Field                 | Type            | Description                                                        |
| --------------------- | --------------- | ------------------------------------------------------------------ |
| `id`                  | integer         | Unique product identifier                                          |
| `shop_id`             | integer         | The shop this product belongs to                                   |
| `name`                | string          | Display name of the product                                        |
| `description`         | string \| null  | Optional longer description                                        |
| `barcode`             | string \| null  | EAN, UPC, or any custom barcode                                    |
| `price`               | string          | Selling price (what customers pay)                                 |
| `cost`                | string \| null  | Purchase/production cost                                           |
| `stock`               | integer         | Current quantity in stock                                          |
| `low_stock_threshold` | integer         | Alert threshold — stock at or below this triggers a low-stock flag |
| `unit`                | string          | Unit of measure: `piece`, `kg`, `liter`, `gram`, `meter`, etc.     |
| `is_active`           | boolean         | Soft-delete flag — inactive products are hidden from all views     |
| `category_id`         | integer \| null | ID of the assigned category                                        |
| `category_name`       | string \| null  | Resolved name of the assigned category                             |
| `images`              | array           | List of image objects attached to the product                      |

## Categories

Custom categories are created per shop and let you organize products in a way that matches your own business logic. Categories support nesting via `parent_id`, so you can build hierarchies like **Beverages → Cold Drinks → Juices**.

```bash theme={null}
# Create a top-level category
curl -X POST https://api.mutasib.com/api/v1/shops/42/categories/ \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Beverages", "parent_id": null }'

# Create a nested sub-category
curl -X POST https://api.mutasib.com/api/v1/shops/42/categories/ \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Cold Drinks", "parent_id": 10 }'
```

## Barcode Lookup

Mutasib supports two barcode lookup paths: one scoped to your shop, and one that queries the global OpenFood database.

### Lookup Within Your Shop

Find a product in your shop's catalog by scanning its barcode. This is the endpoint used by the POS screen when a cashier scans an item.

```bash theme={null}
curl https://api.mutasib.com/api/v1/shops/42/products/barcode/6281234567890/ \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

If the barcode matches a product in your shop, the full `ProductOut` object is returned. If no match is found, the API returns `404`.

### Global OpenFood Database

If a scanned barcode doesn't exist in your shop yet, you can look it up in the OpenFood global database to pre-fill product details before creating a new record.

```bash theme={null}
curl "https://api.mutasib.com/api/v1/products/barcode/6281234567890?country=world" \
  -H "Authorization: Bearer YOUR_API_TOKEN"
```

The `country` query parameter scopes the lookup; pass `world` to search the global OpenFood dataset. The response includes publicly available product metadata such as name, brand, and images sourced from OpenFood contributors worldwide.

<Info>
  The OpenFood lookup is read-only — it never creates a product in your shop automatically. You still need to call `POST /api/v1/shops/{shop_id}/products/` with the returned data to add the item to your catalog.
</Info>

## API Endpoints

| Method   | Endpoint                                                           | Description                                       |
| -------- | ------------------------------------------------------------------ | ------------------------------------------------- |
| `POST`   | `/api/v1/shops/{shop_id}/products/`                                | Create a new product                              |
| `GET`    | `/api/v1/shops/{shop_id}/products/`                                | List all products in the shop                     |
| `GET`    | `/api/v1/shops/{shop_id}/products/{product_id}/`                   | Get a single product by ID                        |
| `PATCH`  | `/api/v1/shops/{shop_id}/products/{product_id}/`                   | Update product fields                             |
| `DELETE` | `/api/v1/shops/{shop_id}/products/{product_id}/`                   | Soft-delete a product                             |
| `GET`    | `/api/v1/shops/{shop_id}/products/barcode/{barcode}/`              | Find a product by barcode within your shop        |
| `GET`    | `/api/v1/shops/{shop_id}/products/search/`                         | Search products in your shop                      |
| `POST`   | `/api/v1/shops/{shop_id}/products/{product_id}/images/`            | Upload a product image                            |
| `DELETE` | `/api/v1/shops/{shop_id}/products/{product_id}/images/{image_id}/` | Delete a product image                            |
| `GET`    | `/api/v1/products/barcode/{barcode}`                               | Look up a barcode in the global OpenFood database |
| `GET`    | `/api/v1/products/search`                                          | Search OpenFood by keyword                        |
| `GET`    | `/api/v1/products/browse/{category}`                               | Browse OpenFood by category                       |
| `POST`   | `/api/v1/shops/{shop_id}/categories/`                              | Create a custom category                          |
| `GET`    | `/api/v1/shops/{shop_id}/categories`                               | List your shop's custom categories                |
| `PATCH`  | `/api/v1/shops/{shop_id}/categories/{category_id}/`                | Update a category                                 |
| `DELETE` | `/api/v1/shops/{shop_id}/categories/{category_id}/`                | Delete a category                                 |
