> ## 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.

# Product Type API

> Manage product types and their required variants with pagination, search, and filtering

# Product Type API

Audience: Frontend engineers managing product types and their required variants.

* Base URL: `https://jethings-backend.fly.dev`
* Content-Type: `application/json`

### Conventions

* All responses are JSON.
* Errors follow standard HTTP status codes with `{ message: string }` body.
* Unless noted, successful responses are `200 OK`.
* All endpoints require authentication via Bearer token.

***

## Get All Product Types

GET `/product-types`

**Requires Authentication:** Bearer token in Authorization header

Retrieve all product types in the system with support for pagination, search, and filtering.

### Query Parameters

| Parameter   | Type      | Required | Default     | Description                                                 |
| ----------- | --------- | -------- | ----------- | ----------------------------------------------------------- |
| `page`      | `number`  | No       | `1`         | Page number for pagination                                  |
| `limit`     | `number`  | No       | `10`        | Number of records per page (max: 100)                       |
| `search`    | `string`  | No       | -           | Search across nameEn, nameFr, nameAr, code, and description |
| `isActive`  | `boolean` | No       | -           | Filter by active status (`true` or `false`)                 |
| `sortBy`    | `string`  | No       | `createdAt` | Sort field: `createdAt`, `updatedAt`, `nameEn`, or `code`   |
| `sortOrder` | `string`  | No       | `desc`      | Sort order: `asc` or `desc`                                 |

### Success Response

```json theme={null}
{
  "data": [
    {
      "id": "pt_123456",
      "code": "CLOTHING",
      "nameEn": "Clothing",
      "nameFr": "Vêtements",
      "nameAr": "ملابس",
      "description": "All types of clothing items",
      "icon": "https://example.com/icons/clothing.png",
      "isActive": true,
      "createdAt": "2024-01-15T10:00:00.000Z",
      "updatedAt": "2024-01-15T10:00:00.000Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 25,
    "totalPages": 3,
    "hasNext": true,
    "hasPrev": false
  }
}
```

### Response Fields

| Field                   | Type                  | Description                        |
| ----------------------- | --------------------- | ---------------------------------- |
| `data`                  | `array`               | Array of product type objects      |
| `data[].id`             | `string`              | Product type unique identifier     |
| `data[].code`           | `string`              | Product type code                  |
| `data[].nameEn`         | `string`              | Product type name in English       |
| `data[].nameFr`         | `string`              | Product type name in French        |
| `data[].nameAr`         | `string`              | Product type name in Arabic        |
| `data[].description`    | `string \| undefined` | Product type description           |
| `data[].icon`           | `string \| undefined` | Icon URL for the product type      |
| `data[].isActive`       | `boolean`             | Whether the product type is active |
| `data[].createdAt`      | `string`              | Creation timestamp (ISO 8601)      |
| `data[].updatedAt`      | `string`              | Last update timestamp (ISO 8601)   |
| `pagination`            | `object`              | Pagination metadata                |
| `pagination.page`       | `number`              | Current page number                |
| `pagination.limit`      | `number`              | Number of items per page           |
| `pagination.total`      | `number`              | Total number of product types      |
| `pagination.totalPages` | `number`              | Total number of pages              |
| `pagination.hasNext`    | `boolean`             | Whether there is a next page       |
| `pagination.hasPrev`    | `boolean`             | Whether there is a previous page   |

### Possible Errors

* `401 Unauthorized`: Missing or invalid authentication token
* `500 Internal Server Error`: Server error

### Example Requests

#### Basic Request (Default Pagination)

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

#### With Pagination

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types?page=2&limit=20" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

#### With Search

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types?search=clothing" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

#### Filter by Active Status

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types?isActive=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

#### With Sorting

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types?sortBy=nameEn&sortOrder=asc" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

#### Combined Filters

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types?page=1&limit=10&search=lens&isActive=true&sortBy=code&sortOrder=asc" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

***

## Get Product Type Required Variants

GET `/product-types/:productTypeId/required-variants`

**Requires Authentication:** Bearer token in Authorization header

Retrieve all required variants associated with a specific product type.

### Path Parameters

| Parameter       | Type     | Required | Description                   |
| --------------- | -------- | -------- | ----------------------------- |
| `productTypeId` | `string` | Yes      | Product type ID (UUID format) |

### Success Response

```json theme={null}
{
  "productTypeId": "pt_123456",
  "requiredVariants": [
    {
      "id": "rv_123456",
      "variantName": "Size",
      "allowedValues": ["S", "M", "L", "XL"]
    },
    {
      "id": "rv_789012",
      "variantName": "Color",
      "allowedValues": ["Red", "Blue", "Green"]
    }
  ]
}
```

### Response Fields

| Field                              | Type               | Description                                 |
| ---------------------------------- | ------------------ | ------------------------------------------- |
| `productTypeId`                    | `string`           | The product type ID                         |
| `requiredVariants`                 | `array`            | Array of required variant objects           |
| `requiredVariants[].id`            | `string`           | Required variant unique identifier          |
| `requiredVariants[].variantName`   | `string \| null`   | Name of the variant (e.g., "Size", "Color") |
| `requiredVariants[].allowedValues` | `string[] \| null` | Array of allowed values for this variant    |

### Possible Errors

* `401 Unauthorized`: Missing or invalid authentication token
* `404 Not Found`: Product type not found
* `500 Internal Server Error`: Server error

### Example Request

```bash theme={null}
curl -X GET "https://jethings-backend.fly.dev/product-types/pt_123456/required-variants" \
  -H "Authorization: Bearer $ACCESS_TOKEN"
```

***

## Create Product Type with Variants

POST `/product-types`

**Requires Authentication:** Bearer token in Authorization header

Create a new product type along with its required variants in a single transaction.

### Request Body

```json theme={null}
{
  "code": "CLOTHING",
  "nameEn": "Clothing",
  "nameFr": "Vêtements",
  "nameAr": "ملابس",
  "description": "All types of clothing items",
  "icon": "https://example.com/icons/clothing.png",
  "requiredVariants": [
    {
      "variantName": "Size",
      "allowedValues": ["S", "M", "L", "XL", "XXL"]
    },
    {
      "variantName": "Color",
      "allowedValues": ["Red", "Blue", "Green", "Black"]
    }
  ]
}
```

### Request Body Fields

| Field              | Type     | Required | Description                           |
| ------------------ | -------- | -------- | ------------------------------------- |
| `code`             | `string` | Yes      | Product type code (unique identifier) |
| `nameEn`           | `string` | Yes      | Product type name in English          |
| `nameFr`           | `string` | Yes      | Product type name in French           |
| `nameAr`           | `string` | Yes      | Product type name in Arabic           |
| `description`      | `string` | No       | Product type description              |
| `icon`             | `string` | No       | Icon URL for the product type         |
| `requiredVariants` | `array`  | No       | Array of required variants to create  |

#### Required Variant Object

| Field           | Type       | Required | Description                                                                               |
| --------------- | ---------- | -------- | ----------------------------------------------------------------------------------------- |
| `variantName`   | `string`   | Yes      | Name of the variant (e.g., "Size", "Color", "Material")                                   |
| `allowedValues` | `string[]` | No       | Array of allowed values for this variant. If not provided, the variant accepts any value. |

### Success Response

```json theme={null}
{
  "productType": {
    "id": "pt_123456",
    "code": "CLOTHING",
    "nameEn": "Clothing",
    "nameFr": "Vêtements",
    "nameAr": "ملابس",
    "description": "All types of clothing items",
    "icon": "https://example.com/icons/clothing.png",
    "isActive": true,
    "createdAt": "2024-01-15T10:00:00.000Z",
    "updatedAt": "2024-01-15T10:00:00.000Z"
  },
  "requiredVariants": [
    {
      "id": "rv_123456",
      "variantName": "Size",
      "allowedValues": ["S", "M", "L", "XL", "XXL"]
    },
    {
      "id": "rv_789012",
      "variantName": "Color",
      "allowedValues": ["Red", "Blue", "Green", "Black"]
    }
  ]
}
```

### Response Fields

| Field              | Type     | Description                               |
| ------------------ | -------- | ----------------------------------------- |
| `productType`      | `object` | The created product type object           |
| `requiredVariants` | `array`  | Array of created required variant objects |

### Possible Errors

* `400 Bad Request`: Invalid request data or validation errors
* `401 Unauthorized`: Missing or invalid authentication token
* `409 Conflict`: Product type code already exists
* `500 Internal Server Error`: Server error

### Example Request

```bash theme={null}
curl -X POST "https://jethings-backend.fly.dev/product-types" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "code": "CLOTHING",
    "nameEn": "Clothing",
    "nameFr": "Vêtements",
    "nameAr": "ملابس",
    "description": "All types of clothing items",
    "icon": "https://example.com/icons/clothing.png",
    "requiredVariants": [
      {
        "variantName": "Size",
        "allowedValues": ["S", "M", "L", "XL", "XXL"]
      },
      {
        "variantName": "Color",
        "allowedValues": ["Red", "Blue", "Green", "Black"]
      }
    ]
  }'
```

***

## Add Required Variants to Product Type

POST `/product-types/:productTypeId/required-variants`

**Requires Authentication:** Bearer token in Authorization header

Add one or more required variants to an existing product type.

### Path Parameters

| Parameter       | Type     | Required | Description                   |
| --------------- | -------- | -------- | ----------------------------- |
| `productTypeId` | `string` | Yes      | Product type ID (UUID format) |

### Request Body

```json theme={null}
{
  "requiredVariants": [
    {
      "variantName": "Material",
      "allowedValues": ["Cotton", "Polyester", "Wool"]
    },
    {
      "variantName": "Pattern",
      "allowedValues": null
    }
  ]
}
```

### Request Body Fields

| Field              | Type    | Required | Description                       |
| ------------------ | ------- | -------- | --------------------------------- |
| `requiredVariants` | `array` | Yes      | Array of required variants to add |

#### Required Variant Object

| Field           | Type       | Required | Description                                                                                         |
| --------------- | ---------- | -------- | --------------------------------------------------------------------------------------------------- |
| `variantName`   | `string`   | Yes      | Name of the variant (e.g., "Size", "Color", "Material")                                             |
| `allowedValues` | `string[]` | No       | Array of allowed values for this variant. If `null` or not provided, the variant accepts any value. |

### Success Response

```json theme={null}
{
  "productTypeId": "pt_123456",
  "requiredVariants": [
    {
      "id": "rv_345678",
      "variantName": "Material",
      "allowedValues": ["Cotton", "Polyester", "Wool"]
    },
    {
      "id": "rv_901234",
      "variantName": "Pattern",
      "allowedValues": null
    }
  ]
}
```

### Response Fields

| Field                              | Type               | Description                                    |
| ---------------------------------- | ------------------ | ---------------------------------------------- |
| `productTypeId`                    | `string`           | The product type ID                            |
| `requiredVariants`                 | `array`            | Array of created required variant objects      |
| `requiredVariants[].id`            | `string`           | Required variant unique identifier             |
| `requiredVariants[].variantName`   | `string \| null`   | Name of the variant                            |
| `requiredVariants[].allowedValues` | `string[] \| null` | Array of allowed values (null if unrestricted) |

### Possible Errors

* `400 Bad Request`: Invalid request data or validation errors
* `401 Unauthorized`: Missing or invalid authentication token
* `404 Not Found`: Product type not found
* `500 Internal Server Error`: Server error

### Example Request

```bash theme={null}
curl -X POST "https://jethings-backend.fly.dev/product-types/pt_123456/required-variants" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -d '{
    "requiredVariants": [
      {
        "variantName": "Material",
        "allowedValues": ["Cotton", "Polyester", "Wool"]
      },
      {
        "variantName": "Pattern",
        "allowedValues": null
      }
    ]
  }'
```

***

## DTOs Overview

### GetProductTypesDto (Query Parameters)

```typescript theme={null}
{
  page?: number;           // Default: 1
  limit?: number;          // Default: 10, Max: 100
  search?: string;         // Search across nameEn, nameFr, nameAr, code, description
  isActive?: boolean;      // Filter by active status
  sortBy?: 'createdAt' | 'updatedAt' | 'nameEn' | 'code';  // Default: 'createdAt'
  sortOrder?: 'asc' | 'desc';  // Default: 'desc'
}
```

### PaginatedProductTypesResponseDto

```typescript theme={null}
{
  data: ProductTypeResponseDto[];
  pagination: {
    page: number;
    limit: number;
    total: number;
    totalPages: number;
    hasNext: boolean;
    hasPrev: boolean;
  };
}
```

### ProductTypeResponseDto

```typescript theme={null}
{
  id: string;
  code: string;
  nameEn: string;
  nameFr: string;
  nameAr: string;
  description?: string;
  icon?: string;
  isActive: boolean;
  createdAt: Date;
  updatedAt: Date;
}
```

### CreateProductTypeWithVariantsDto

```typescript theme={null}
{
  code: string;
  nameEn: string;
  nameFr: string;
  nameAr: string;
  description?: string;
  icon?: string;
  requiredVariants?: CreateRequiredVariantDto[];
}
```

### AddRequiredVariantToProductTypeDto

```typescript theme={null}
{
  requiredVariants: CreateRequiredVariantDto[];
}
```

### CreateRequiredVariantDto

```typescript theme={null}
{
  variantName: string;
  allowedValues?: string[] | null;
}
```

### RequiredVariantResponse

```typescript theme={null}
{
  id: string;
  variantName: string | null;
  allowedValues: string[] | null;
}
```

***

## Business Logic

### Product Type Creation Flow

1. User creates a product type with multilingual names (English, French, Arabic)
2. Product type is created with `isActive: true` by default
3. Required variants can be created in the same transaction
4. Each required variant can have optional allowed values to restrict input

### Required Variants

* Required variants define what attributes must be specified when creating products of this type
* Examples: Size, Color, Material, Pattern, etc.
* `allowedValues` can be:
  * An array of specific values (e.g., `["S", "M", "L"]`) - restricts to these values only
  * `null` or omitted - allows any value to be entered
* Variants are linked to product types through a many-to-many relationship

### Transaction Safety

* Creating a product type with variants uses a database transaction
* If any variant creation fails, the entire operation is rolled back
* Adding variants to an existing product type also uses transactions for consistency

### Use Cases

* **Clothing**: Size, Color, Material
* **Electronics**: Model, Storage Capacity, Color
* **Food Items**: Weight, Unit, Expiry Date
* **Custom Products**: Any custom attributes defined by the business

***

## Error Responses

### Common Error Codes

* `400 Bad Request`: Invalid request data or validation errors
* `401 Unauthorized`: Missing or invalid authentication token
* `404 Not Found`: Product type not found
* `409 Conflict`: Product type code already exists
* `500 Internal Server Error`: Server error

### Error Response Format

```json theme={null}
{
  "message": "Error description",
  "statusCode": 400
}
```

### Example Error Responses

#### 400 Bad Request

```json theme={null}
{
  "statusCode": 400,
  "message": "Validation failed",
  "error": "Bad Request"
}
```

#### 404 Not Found

```json theme={null}
{
  "statusCode": 404,
  "message": "Product type not found",
  "error": "Not Found"
}
```

#### 409 Conflict

```json theme={null}
{
  "statusCode": 409,
  "message": "Product type with code 'CLOTHING' already exists",
  "error": "Conflict"
}
```
