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

# Purchase Invoice API

> Create purchase invoices and manage product inventory with file uploads

# Purchase Invoice API

The Purchase Invoice API allows you to create purchase invoices that can either create new products or update existing products with additional inventory. This endpoint supports file uploads for product variant images and handles brand creation automatically.

<Note>
  This endpoint uses `multipart/form-data` format to support file uploads. Make sure to include the proper headers when making requests.
</Note>

## Endpoint Details

**Endpoint:** `POST /purchase-invoices`\
**Content-Type:** `multipart/form-data`\
**Base URL:** `https://jethings-backend.fly.dev`

### Required Headers

```
x-store-id: <store_id>
Authorization: Bearer <token>
```

***

## Request Structure

The request uses `multipart/form-data` format with:

* **`jsonData`**: A JSON string containing the purchase invoice data
* **Files**: Product variant images uploaded with specific field names

### Action Types

The API supports two action types:

<Tabs>
  <Tab title="CREATE" description="Create new products">
    Use `CREATE` when introducing a brand new product to your inventory.

    ```json theme={null}
    {
      "actionType": "CREATE",
      "warehouseId": "uuid",
      "supplierId": "uuid",
      "purchaseDate": "2024-01-15",
      "referenceNumber": "REF-001",
      "amountPaid": 100.80,
      "isShipped": false,
      "isPaid": false,
      "productTypeId": "uuid",
      "product": {
        "title": "Product Name",
        "ref": "PROD-001",
        "description": "Product description",
        "brandName": "Nike"
      },
      "variants": [
        {
          "itemName": "Blue T-Shirt",
          "color": "Blue",
          "pointer": [
            { "qty": 49, "value": 30, "barcode": "PSH-BLUE-30" }
          ]
        }
      ],
      "barcodes": ["B001", "B002"]
    }
    ```

    **Required fields for CREATE:**

    * `actionType`: `"CREATE"`
    * `product.title`: Product name
    * `variants`: Array of variant objects
    * `warehouseId`, `supplierId`, `purchaseDate`, `referenceNumber`, `amountPaid`, `productTypeId`, `isShipped`, `isPaid`
  </Tab>

  <Tab title="UPDATE" description="Add inventory to existing products">
    Use `UPDATE` when adding stock to an existing product.

    ```json theme={null}
    {
      "actionType": "UPDATE",
      "productId": "existing-product-uuid",
      "warehouseId": "uuid",
      "supplierId": "uuid",
      "purchaseDate": "2024-01-15",
      "referenceNumber": "REF-002",
      "amountPaid": 150.50,
      "isShipped": false,
      "isPaid": false,
      "productTypeId": "uuid",
      "variants": [
        {
          "itemId": "existing-item-uuid",
          "itemName": "Blue T-Shirt",
          "color": "Blue",
          "pointer": [
            { "qty": 49, "value": 30 }
          ]
        }
      ]
    }
    ```

    **Required fields for UPDATE:**

    * `actionType`: `"UPDATE"`
    * `productId`: UUID of existing product (required for UPDATE)
    * `variants`: Array of variant objects
  </Tab>
</Tabs>

***

## Data Structures

### Product Object

The `product` object is used in CREATE actions to define product details.

| Field         | Type          | Required | Description                                        |
| ------------- | ------------- | -------- | -------------------------------------------------- |
| `title`       | string        | ✅ Yes    | Product title/name (e.g., "Premium T-Shirt")       |
| `ref`         | string        | No       | Product reference code (e.g., "TSH-001")           |
| `description` | string        | No       | Product description                                |
| `brandId`     | string (UUID) | No       | UUID of an existing brand                          |
| `brandName`   | string        | No       | Brand name (will create brand if it doesn't exist) |

<Warning>
  For brand selection, you can use either `brandId` (existing brand) or `brandName` (auto-create brand). If both are provided, `brandName` takes precedence.
</Warning>

### Variant Structure

The `variants` array contains items and their sizes with quantities.

| Field      | Type   | Required | Description                                                    |
| ---------- | ------ | -------- | -------------------------------------------------------------- |
| `itemId`   | string | No       | **For UPDATE only:** UUID of existing item to add inventory to |
| `itemName` | string | ✅ Yes    | Name for the item variant (e.g., "Blue T-Shirt", "Red Shirt")  |
| `color`    | string | ✅ Yes    | Color variant (e.g., "Blue", "Green", "Red")                   |
| `pointer`  | array  | ✅ Yes    | Array of pointer values (sizes, etc.)                          |

#### Pointer Structure

Each pointer represents a size with quantity:

```json theme={null}
{
  "qty": 49,              // Quantity for this size
  "value": 30,            // Pointer value (e.g., size 30)
  "barcode": "PSH-BLUE-30" // Optional barcode for this pointer
}
```

***

## File Upload Mechanism

### Naming Convention

Product variant images must be uploaded using this naming pattern:

<Tabs>
  <Tab title="CREATE Actions">
    Upload images for **all** variants:

    ```
    variant_0_images: [image1.jpg, image2.jpg]
    variant_1_images: [image1.jpg, image2.jpg]
    variant_2_images: [image1.jpg]
    ```
  </Tab>

  <Tab title="UPDATE Actions">
    Upload images **only for NEW items** (items without `itemId`):

    ```
    variant_0_images: [new-item-image.jpg]  # First new item
    variant_1_images: [another-new-item.jpg]  # Second new item
    ```

    **Important:** Don't upload images for existing items (with `itemId`). The index counts only NEW items.
  </Tab>
</Tabs>

### Multiple Images per Variant

You can upload multiple images for each variant by sending multiple files with the same field name:

```
variant_0_images: [image1.jpg, image2.jpg, image3.jpg]
variant_1_images: [image1.jpg, image2.jpg]
```

### Supported Image Formats

* jpg, jpeg, png, gif, webp

***

## Complete Examples

This section provides detailed examples for both CREATE and UPDATE action types.

<CardGroup cols={2}>
  <Card title="CREATE Examples" icon="plus-circle" href="#create-action-examples">
    Examples for creating new products

    <br />

    <small>Examples 1-2: New products with brand management</small>
  </Card>

  <Card title="UPDATE Examples" icon="refresh" href="#update-action-examples">
    Examples for adding inventory

    <br />

    <small>Examples 3-5: Existing items, new items, or mixed</small>
  </Card>
</CardGroup>

***

## CREATE Action Examples

### Example 1: CREATE - New Product with Brand Creation

This example creates a new product with auto-brand creation.

<Tabs>
  <Tab title="Use Case: CREATE">
    **Use when:** You're introducing a brand new product to your inventory that doesn't exist yet.
  </Tab>
</Tabs>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
    -H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
    -H "Authorization: Bearer <token>" \
    -F 'jsonData={"actionType":"CREATE","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-001","amountPaid":100.80,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","product":{"title":"Premium Cotton T-Shirt","ref":"TSH-001","description":"High-quality cotton t-shirt with premium finish","brandName":"Nike"},"variants":[{"itemName":"Blue T-Shirt","pointer":[{"qty":49,"value":30,"barcode":"PSH-BLUE-30"}],"color":"Blue"},{"itemName":"Green T-Shirt","pointer":[{"qty":49,"value":30,"barcode":"PSH-GREEN-30"}],"color":"Green"}],"barcodes":["0988-TY","09877-GB"]}' \
    -F 'variant_0_images=@blue-image-1.jpg' \
    -F 'variant_0_images=@blue-image-2.jpg' \
    -F 'variant_1_images=@green-image-1.jpg'
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();

  const jsonData = {
    actionType: "CREATE",
    warehouseId: "x1vt8qlr0l7ju7tbe2an6ov0",
    supplierId: "cjdtw2flpntu6jmsh0row6yc",
    purchaseDate: "2024-01-15",
    referenceNumber: "REF-2024-001",
    amountPaid: 100.80,
    isShipped: false,
    isPaid: false,
    productTypeId: "ywb1l1vyre5nm27n2fr8vpwz",
    product: {
      title: "Premium Cotton T-Shirt",
      ref: "TSH-001",
      description: "High-quality cotton t-shirt with premium finish",
      brandName: "Nike"
    },
    variants: [
      {
        itemName: "Blue T-Shirt",
        color: "Blue",
        pointer: [
          { qty: 49, value: 30, barcode: "PSH-BLUE-30" }
        ]
      },
      {
        itemName: "Green T-Shirt",
        color: "Green",
        pointer: [
          { qty: 49, value: 30, barcode: "PSH-GREEN-30" }
        ]
      }
    ],
    barcodes: ["0988-TY", "09877-GB"]
  };

  formData.append('jsonData', JSON.stringify(jsonData));
  formData.append('variant_0_images', fileInput.files[0]);
  formData.append('variant_0_images', fileInput.files[1]);
  formData.append('variant_1_images', fileInput.files[2]);

  const response = await fetch('https://jethings-backend.fly.dev/purchase-invoices', {
    method: 'POST',
    headers: {
      'x-store-id': 'x1vt8qlr0l7ju7tbe2an6ov0',
      'Authorization': 'Bearer <token>'
    },
    body: formData
  });

  const result = await response.json();
  ```

  ```python Python theme={null}
  import requests

  url = "https://jethings-backend.fly.dev/purchase-invoices"

  json_data = {
      "actionType": "CREATE",
      "warehouseId": "x1vt8qlr0l7ju7tbe2an6ov0",
      "supplierId": "cjdtw2flpntu6jmsh0row6yc",
      "purchaseDate": "2024-01-15",
      "referenceNumber": "REF-2024-001",
      "amountPaid": 100.80,
      "isShipped": False,
      "isPaid": False,
      "productTypeId": "ywb1l1vyre5nm27n2fr8vpwz",
      "product": {
          "title": "Premium Cotton T-Shirt",
          "ref": "TSH-001",
          "description": "High-quality cotton t-shirt with premium finish",
          "brandName": "Nike"
      },
      "variants": [
          {
              "itemName": "Blue T-Shirt",
              "color": "Blue",
              "pointer": [
                  {"qty": 49, "value": 30, "barcode": "PSH-BLUE-30"}
              ]
          },
          {
              "itemName": "Green T-Shirt",
              "color": "Green",
              "pointer": [
                  {"qty": 49, "value": 30, "barcode": "PSH-GREEN-30"}
              ]
          }
      ],
      "barcodes": ["0988-TY", "09877-GB"]
  }

  files = [
      ('variant_0_images', ('blue-1.jpg', open('blue-1.jpg', 'rb'), 'image/jpeg')),
      ('variant_0_images', ('blue-2.jpg', open('blue-2.jpg', 'rb'), 'image/jpeg')),
      ('variant_1_images', ('green-1.jpg', open('green-1.jpg', 'rb'), 'image/jpeg'))
  ]

  response = requests.post(
      url,
      headers={
          'x-store-id': 'x1vt8qlr0l7ju7tbe2an6ov0',
          'Authorization': 'Bearer <token>'
      },
      data={'jsonData': json.dumps(json_data)},
      files=files
  )

  print(response.json())
  ```
</CodeGroup>

**Success Response:**

```json theme={null}
{
  "purchaseInvoice": {
    "id": "invoice-uuid",
    "supplierId": "cjdtw2flpntu6jmsh0row6yc",
    "storeId": "x1vt8qlr0l7ju7tbe2an6ov0",
    "supplierInvoiceNo": "REF-2024-001",
    "priceList": "default",
    "postingTime": "2024-01-15T10:00:00.000Z",
    "warehouseId": "x1vt8qlr0l7ju7tbe2an6ov0",
    "amountPaid": 100.80,
    "createAt": "2024-01-15T10:00:00.000Z"
  },
  "product": {
    "success": true,
    "message": "Product and items created successfully",
    "product": {
      "id": "product-uuid",
      "title": "Premium Cotton T-Shirt",
      "ref": "TSH-001",
      "description": "High-quality cotton t-shirt with premium finish",
      "brandId": "brand-uuid"
    },
    "items": [
      {
        "item": {
          "id": "item-uuid-1",
          "productId": "product-uuid"
        },
        "itemVariants": [
          {
            "pointer": 30,
            "color": "Blue",
            "qty": 49,
            "barcode": "PSH-BLUE-30"
          }
        ],
        "images": [
          {
            "success": true,
            "filename": "blue-image-1.jpg",
            "url": "https://storage.example.com/products/items/image.jpg"
          }
        ]
      }
    ]
  }
}
```

***

### Example 2: CREATE - Using Existing Brand

This example creates a new product using an existing brand ID instead of creating a new brand.

<Tabs>
  <Tab title="Use Case: CREATE">
    **Use when:** Creating a new product and want to link to an existing brand in your system.
  </Tab>
</Tabs>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
    -H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
    -H "Authorization: Bearer <token>" \
    -F 'jsonData={"actionType":"CREATE","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-002","amountPaid":150.50,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","product":{"title":"Premium Jeans","ref":"JEAN-001","description":"Classic fit jeans","brandId":"existing-brand-uuid"},"variants":[{"itemName":"Blue Jeans","color":"Blue","pointer":[{"qty":30,"value":32,"barcode":"JEAN-BLUE-32"}]}]}' \
    -F 'variant_0_images=@jean-image.jpg'
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();

  const jsonData = {
    actionType: "CREATE",
    warehouseId: "x1vt8qlr0l7ju7tbe2an6ov0",
    supplierId: "cjdtw2flpntu6jmsh0row6yc",
    purchaseDate: "2024-01-15",
    referenceNumber: "REF-2024-002",
    amountPaid: 150.50,
    isShipped: false,
    isPaid: false,
    productTypeId: "ywb1l1vyre5nm27n2fr8vpwz",
    product: {
      title: "Premium Jeans",
      ref: "JEAN-001",
      description: "Classic fit jeans",
      brandId: "existing-brand-uuid"
    },
    variants: [
      {
        itemName: "Blue Jeans",
        color: "Blue",
        pointer: [
          { qty: 30, value: 32, barcode: "JEAN-BLUE-32" }
        ]
      }
    ]
  };

  formData.append('jsonData', JSON.stringify(jsonData));
  formData.append('variant_0_images', fileInput.files[0]);
  ```

  ```python Python theme={null}
  import requests
  import json

  url = "https://jethings-backend.fly.dev/purchase-invoices"

  json_data = {
      "actionType": "CREATE",
      "warehouseId": "x1vt8qlr0l7ju7tbe2an6ov0",
      "supplierId": "cjdtw2flpntu6jmsh0row6yc",
      "purchaseDate": "2024-01-15",
      "referenceNumber": "REF-2024-002",
      "amountPaid": 150.50,
      "isShipped": False,
      "isPaid": False,
      "productTypeId": "ywb1l1vyre5nm27n2fr8vpwz",
      "product": {
          "title": "Premium Jeans",
          "ref": "JEAN-001",
          "description": "Classic fit jeans",
          "brandId": "existing-brand-uuid"
      },
      "variants": [
          {
              "itemName": "Blue Jeans",
              "color": "Blue",
              "pointer": [
                  {"qty": 30, "value": 32, "barcode": "JEAN-BLUE-32"}
              ]
          }
      ]
  }

  files = [('variant_0_images', ('jean.jpg', open('jean.jpg', 'rb'), 'image/jpeg'))]

  response = requests.post(
      url,
      headers={
          'x-store-id': 'x1vt8qlr0l7ju7tbe2an6ov0',
          'Authorization': 'Bearer <token>'
      },
      data={'jsonData': json.dumps(json_data)},
      files=files
  )
  ```
</CodeGroup>

***

## UPDATE Action Examples

### Example 3: UPDATE - Add Inventory to Existing Item

Use this when adding more stock to an existing color/variant.

<Tabs>
  <Tab title="Use Case: UPDATE with itemId">
    **Use when:** Adding inventory to an existing item variant. No file uploads needed.
  </Tab>
</Tabs>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
    -H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
    -H "Authorization: Bearer <token>" \
    -F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-003","amountPaid":100.80,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemId":"existing-blue-item-uuid","itemName":"Blue T-Shirt","color":"Blue","pointer":[{"qty":49,"value":30}]}]}'
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();

  const jsonData = {
    actionType: "UPDATE",
    productId: "a7hkmoj8p142p2vtp450byk2",
    warehouseId: "x1vt8qlr0l7ju7tbe2an6ov0",
    supplierId: "cjdtw2flpntu6jmsh0row6yc",
    purchaseDate: "2024-01-15",
    referenceNumber: "REF-2024-003",
    amountPaid: 100.80,
    isShipped: false,
    isPaid: false,
    productTypeId: "ywb1l1vyre5nm27n2fr8vpwz",
    variants: [
      {
        itemId: "existing-blue-item-uuid",
        itemName: "Blue T-Shirt",
        color: "Blue",
        pointer: [
          { qty: 49, value: 30 }
        ]
      }
    ]
  };

  formData.append('jsonData', JSON.stringify(jsonData));

  const response = await fetch('https://jethings-backend.fly.dev/purchase-invoices', {
    method: 'POST',
    headers: {
      'x-store-id': 'x1vt8qlr0l7ju7tbe2an6ov0',
      'Authorization': 'Bearer <token>'
    },
    body: formData
  });
  ```
</CodeGroup>

**Note:** No file uploads needed when using `itemId` for existing items.

***

### Example 4: UPDATE - Create New Item (Different Color)

Use this when adding a new color variant to an existing product.

<Tabs>
  <Tab title="Use Case: UPDATE without itemId">
    **Use when:** Creating a new item variant (new color) for an existing product. Requires file uploads.
  </Tab>
</Tabs>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
    -H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
    -H "Authorization: Bearer <token>" \
    -F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-004","amountPaid":75.25,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemName":"Red T-Shirt","color":"Red","pointer":[{"qty":25,"value":30,"barcode":"PSH-RED-30"}]}]}' \
    -F 'variant_0_images=@red-variant-image.jpg'
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();

  const jsonData = {
    actionType: "UPDATE",
    productId: "a7hkmoj8p142p2vtp450byk2",
    warehouseId: "x1vt8qlr0l7ju7tbe2an6ov0",
    supplierId: "cjdtw2flpntu6jmsh0row6yc",
    purchaseDate: "2024-01-15",
    referenceNumber: "REF-2024-004",
    amountPaid: 75.25,
    isShipped: false,
    isPaid: false,
    productTypeId: "ywb1l1vyre5nm27n2fr8vpwz",
    variants: [
      {
        itemName: "Red T-Shirt",
        color: "Red",
        pointer: [
          { qty: 25, value: 30, barcode: "PSH-RED-30" }
        ]
      }
    ]
  };

  formData.append('jsonData', JSON.stringify(jsonData));
  formData.append('variant_0_images', fileInput.files[0]);

  // ... same fetch call as above
  ```
</CodeGroup>

**Note:** When creating a new item (different color) in UPDATE action, you must provide `itemName` and upload images using `variant_0_images`.

***

### Example 5: UPDATE - Mixed (Existing + New Items)

Adding inventory to Blue item and creating Red and Green items.

<Tabs>
  <Tab title="Use Case: UPDATE Mixed">
    **Use when:** Adding inventory to existing items AND creating new item variants in the same request.
  </Tab>
</Tabs>

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://jethings-backend.fly.dev/purchase-invoices \
    -H "x-store-id: x1vt8qlr0l7ju7tbe2an6ov0" \
    -H "Authorization: Bearer <token>" \
    -F 'jsonData={"actionType":"UPDATE","productId":"a7hkmoj8p142p2vtp450byk2","warehouseId":"x1vt8qlr0l7ju7tbe2an6ov0","supplierId":"cjdtw2flpntu6jmsh0row6yc","purchaseDate":"2024-01-15","referenceNumber":"REF-2024-005","amountPaid":200.00,"isShipped":false,"isPaid":false,"productTypeId":"ywb1l1vyre5nm27n2fr8vpwz","variants":[{"itemId":"existing-blue-item-uuid","itemName":"Blue T-Shirt","color":"Blue","pointer":[{"qty":30,"value":30}]},{"itemName":"Red T-Shirt","color":"Red","pointer":[{"qty":25,"value":30,"barcode":"PSH-RED-30"}]},{"itemName":"Green T-Shirt","color":"Green","pointer":[{"qty":20,"value":30,"barcode":"PSH-GREEN-30"}]}]}' \
    -F 'variant_0_images=@red-image.jpg' \
    -F 'variant_1_images=@green-image.jpg'
  ```

  ```javascript JavaScript theme={null}
  const formData = new FormData();

  const jsonData = {
    actionType: "UPDATE",
    productId: "a7hkmoj8p142p2vtp450byk2",
    warehouseId: "x1vt8qlr0l7ju7tbe2an6ov0",
    supplierId: "cjdtw2flpntu6jmsh0row6yc",
    purchaseDate: "2024-01-15",
    referenceNumber: "REF-2024-005",
    amountPaid: 200.00,
    isShipped: false,
    isPaid: false,
    productTypeId: "ywb1l1vyre5nm27n2fr8vpwz",
    variants: [
      {
        itemId: "existing-blue-item-uuid",
        itemName: "Blue T-Shirt",
        color: "Blue",
        pointer: [{ qty: 30, value: 30 }]
      },
      {
        itemName: "Red T-Shirt",
        color: "Red",
        pointer: [{ qty: 25, value: 30, barcode: "PSH-RED-30" }]
      },
      {
        itemName: "Green T-Shirt",
        color: "Green",
        pointer: [{ qty: 20, value: 30, barcode: "PSH-GREEN-30" }]
      }
    ]
  };

  formData.append('jsonData', JSON.stringify(jsonData));
  formData.append('variant_0_images', redImage);
  formData.append('variant_1_images', greenImage);

  // ... fetch call
  ```
</CodeGroup>

<Warning>
  The file indices (`variant_0_images`, `variant_1_images`) correspond to NEW items only (Red and Green), not the existing Blue item.
</Warning>

***

## Response Structure

### Success Response

```json theme={null}
{
  "purchaseInvoice": {
    "id": "invoice-uuid",
    "supplierId": "cjdtw2flpntu6jmsh0row6yc",
    "storeId": "x1vt8qlr0l7ju7tbe2an6ov0",
    "supplierInvoiceNo": "REF-2024-001",
    "priceList": "default",
    "postingTime": "2024-01-15T10:00:00.000Z",
    "dueTime": "2024-01-15T00:00:00.000Z",
    "updateStock": true,
    "warehouseId": "x1vt8qlr0l7ju7tbe2an6ov0",
    "amountPaid": 100.80,
    "createAt": "2024-01-15T10:00:00.000Z",
    "updateAt": "2024-01-15T10:00:00.000Z"
  },
  "purchaseInvoiceItems": [
    {
      "id": "item-1-uuid",
      "purchaseInvoiceId": "invoice-uuid",
      "itemVariantId": "variant-1-uuid",
      "quantity": 49,
      "unitPrice": 2.06,
      "totalPrice": 101.06,
      "isActive": true,
      "createdAt": "2024-01-15T10:00:00.000Z",
      "updatedAt": "2024-01-15T10:00:00.000Z"
    }
  ],
  "product": {
    "success": true,
    "message": "Product and items created successfully",
    "product": {
      "id": "product-uuid",
      "storeId": "x1vt8qlr0l7ju7tbe2an6ov0",
      "productTypeId": "ywb1l1vyre5nm27n2fr8vpwz",
      "brandId": "brand-uuid",
      "title": "Premium Cotton T-Shirt",
      "ref": "TSH-001",
      "description": "High-quality cotton t-shirt with premium finish",
      "isActive": true,
      "createdAt": "2024-01-15T10:00:00.000Z",
      "updatedAt": "2024-01-15T10:00:00.000Z"
    },
    "items": [
      {
        "item": {
          "id": "item-uuid-1",
          "productId": "product-uuid",
          "description": "Item variant 1",
          "isActive": true
        },
        "itemVariants": [
          {
            "itemVariant": {
              "id": "item-variant-uuid"
            },
            "pointer": 30,
            "color": "Blue",
            "qty": 49,
            "barcode": "PSH-BLUE-30"
          }
        ],
        "images": [
          {
            "success": true,
            "filename": "blue-image-1.jpg",
            "url": "https://storage.example.com/products/items/image.jpg"
          }
        ]
      }
    ]
  }
}
```

### Error Responses

#### 400 Bad Request

```json theme={null}
{
  "statusCode": 400,
  "message": "Product type not found",
  "error": "Bad Request"
}
```

#### 403 Forbidden

```json theme={null}
{
  "statusCode": 403,
  "message": "You do not have access to this store",
  "error": "Forbidden"
}
```

#### 404 Not Found

```json theme={null}
{
  "statusCode": 404,
  "message": "Item with id xyz not found",
  "error": "Not Found"
}
```

***

## Important Notes

### CREATE vs UPDATE

<AccordionGroup>
  <Accordion title="CREATE Action">
    * Creates a new product and its items/variants
    * All variants get new items with the provided `itemName`
    * Requires uploading images for all variants
    * Use when introducing completely new products
  </Accordion>

  <Accordion title="UPDATE Action">
    * Updates an existing product
    * Can add to existing items (with `itemId`) or create new items (without `itemId`)
    * Only upload images for new items (without `itemId`)
    * Use when restocking existing products
  </Accordion>
</AccordionGroup>

### itemName Field

* **Always required** for all variants in both CREATE and UPDATE actions
* This name is stored in the `itemVariant.name` column in the database
* Examples: "Blue T-Shirt", "Red Shirt", "Green Variant"

### itemId Usage in UPDATE

<CardGroup cols={2}>
  <Card title="With itemId" icon="plus-circle">
    Add inventory to an existing item

    <br />

    <code>No file uploads needed</code>
  </Card>

  <Card title="Without itemId" icon="file-plus">
    Create a new item

    <br />

    <code>Requires file uploads</code>
  </Card>
</CardGroup>

### File Upload Rules

<Tabs>
  <Tab title="CREATE Actions">
    Upload images for **ALL** variants:

    ```javascript theme={null}
    variant_0_images: [variant-0-img1.jpg, variant-0-img2.jpg]
    variant_1_images: [variant-1-img1.jpg]
    variant_2_images: [variant-2-img1.jpg, variant-2-img2.jpg]
    ```
  </Tab>

  <Tab title="UPDATE with itemId">
    **No uploads needed** for existing items:

    ```javascript theme={null}
    // If all variants have itemId, no file uploads required
    ```
  </Tab>

  <Tab title="UPDATE without itemId">
    Upload **only for NEW items**. Index counts only new items:

    ```javascript theme={null}
    // Example: Blue has itemId, Red and Green are new
    variants: [
      { itemId: "blue-id", ... },  // Existing - no upload
      { itemName: "Red T-Shirt", ... },  // New - variant_0_images
      { itemName: "Green T-Shirt", ... }  // New - variant_1_images
    ]
    ```
  </Tab>
</Tabs>

### Stock Management

* Quantities (`qty` in pointer) automatically update warehouse stock
* Stock is distributed across warehouse bins
* `updateStock: true` enables real-time stock updates

### Brand Handling

<Tabs>
  <Tab title="Using Existing Brand">
    ```json theme={null}
    {
      "product": {
        "title": "Product Name",
        "brandId": "existing-brand-uuid"
      }
    }
    ```

    Use `brandId` to reference an existing brand
  </Tab>

  <Tab title="Auto-Create Brand">
    ```json theme={null}
    {
      "product": {
        "title": "Product Name",
        "brandName": "Nike"
      }
    }
    ```

    Use `brandName` to auto-create a brand if it doesn't exist
  </Tab>

  <Tab title="Priority Rule">
    If both `brandId` and `brandName` are provided, `brandName` takes precedence

    ```json theme={null}
    {
      "product": {
        "brandId": "old-uuid",
        "brandName": "New Brand"  // This wins!
      }
    }
    ```
  </Tab>
</Tabs>

### Barcode Assignment

The API supports two methods for barcode assignment:

1. **Individual barcodes in pointer values** - Specific to each size
2. **Global barcodes array** - Applied to all item variants

Both methods work simultaneously.

***

## Summary

<Steps>
  <Step title="Choose Action Type">
    Select CREATE for new products or UPDATE for existing products
  </Step>

  <Step title="Prepare Data">
    Structure your JSON data with product info, variants, and inventory details
  </Step>

  <Step title="Upload Files">
    Follow the naming convention for variant images based on your action type
  </Step>

  <Step title="Send Request">
    Use multipart/form-data with proper headers
  </Step>

  <Step title="Handle Response">
    Receive complete purchase invoice, product, and stock information
  </Step>
</Steps>

This API provides a flexible way to manage purchase invoices while automatically handling product creation, variant management, inventory updates, and file uploads. Choose the appropriate action type based on whether you're introducing a new product (CREATE) or restocking an existing one (UPDATE).

***

<CardGroup cols={2}>
  <Card title="App Configuration" icon="settings" href="/api-reference/app-config-api">
    Configure your store settings
  </Card>

  <Card title="Store Management" icon="store" href="/api-reference/stores-api">
    Manage stores and permissions
  </Card>
</CardGroup>
